1ecaafb7bSJinzhou Su /*
2ecaafb7bSJinzhou Su * Copyright 2021 Advanced Micro Devices, Inc.
3ecaafb7bSJinzhou Su *
4ecaafb7bSJinzhou Su * Permission is hereby granted, free of charge, to any person obtaining a
5ecaafb7bSJinzhou Su * copy of this software and associated documentation files (the "Software"),
6ecaafb7bSJinzhou Su * to deal in the Software without restriction, including without limitation
7ecaafb7bSJinzhou Su * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8ecaafb7bSJinzhou Su * and/or sell copies of the Software, and to permit persons to whom the
9ecaafb7bSJinzhou Su * Software is furnished to do so, subject to the following conditions:
10ecaafb7bSJinzhou Su *
11ecaafb7bSJinzhou Su * The above copyright notice and this permission notice shall be included in
12ecaafb7bSJinzhou Su * all copies or substantial portions of the Software.
13ecaafb7bSJinzhou Su *
14ecaafb7bSJinzhou Su * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ecaafb7bSJinzhou Su * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ecaafb7bSJinzhou Su * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17ecaafb7bSJinzhou Su * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18ecaafb7bSJinzhou Su * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ecaafb7bSJinzhou Su * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20ecaafb7bSJinzhou Su * OTHER DEALINGS IN THE SOFTWARE.
21ecaafb7bSJinzhou Su *
22ecaafb7bSJinzhou Su *
23ecaafb7bSJinzhou Su */
24ecaafb7bSJinzhou Su #include <linux/debugfs.h>
25ecaafb7bSJinzhou Su #include <linux/pm_runtime.h>
26ecaafb7bSJinzhou Su
27ecaafb7bSJinzhou Su #include "amdgpu.h"
28ecaafb7bSJinzhou Su #include "amdgpu_securedisplay.h"
29ecaafb7bSJinzhou Su
30ecaafb7bSJinzhou Su /**
31ecaafb7bSJinzhou Su * DOC: AMDGPU SECUREDISPLAY debugfs test interface
32ecaafb7bSJinzhou Su *
33ecaafb7bSJinzhou Su * how to use?
34ecaafb7bSJinzhou Su * echo opcode <value> > <debugfs_dir>/dri/xxx/securedisplay_test
35ecaafb7bSJinzhou Su * eg. echo 1 > <debugfs_dir>/dri/xxx/securedisplay_test
36ecaafb7bSJinzhou Su * eg. echo 2 phy_id > <debugfs_dir>/dri/xxx/securedisplay_test
37ecaafb7bSJinzhou Su *
38ecaafb7bSJinzhou Su * opcode:
39ecaafb7bSJinzhou Su * 1:Query whether TA is responding used only for validation pupose
40ecaafb7bSJinzhou Su * 2: Send region of Interest and CRC value to I2C. (uint32)phy_id is
41ecaafb7bSJinzhou Su * send to determine which DIO scratch register should be used to get
42ecaafb7bSJinzhou Su * ROI and receive i2c_buf as the output.
43ecaafb7bSJinzhou Su *
44ecaafb7bSJinzhou Su * You can refer more detail from header file ta_securedisplay_if.h
45ecaafb7bSJinzhou Su *
46ecaafb7bSJinzhou Su */
47ecaafb7bSJinzhou Su
psp_securedisplay_parse_resp_status(struct psp_context * psp,enum ta_securedisplay_status status)48ecaafb7bSJinzhou Su void psp_securedisplay_parse_resp_status(struct psp_context *psp,
49ecaafb7bSJinzhou Su enum ta_securedisplay_status status)
50ecaafb7bSJinzhou Su {
51ecaafb7bSJinzhou Su switch (status) {
52ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__SUCCESS:
53ecaafb7bSJinzhou Su break;
54ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE:
55ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Generic Failure.");
56ecaafb7bSJinzhou Su break;
57ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__INVALID_PARAMETER:
58ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Invalid Parameter.");
59ecaafb7bSJinzhou Su break;
60ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__NULL_POINTER:
61ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Null Pointer.");
62ecaafb7bSJinzhou Su break;
63ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__I2C_WRITE_ERROR:
64ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Failed to write to I2C.");
65ecaafb7bSJinzhou Su break;
66ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__READ_DIO_SCRATCH_ERROR:
67ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Failed to Read DIO Scratch Register.");
68ecaafb7bSJinzhou Su break;
69ecaafb7bSJinzhou Su case TA_SECUREDISPLAY_STATUS__READ_CRC_ERROR:
70ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Failed to Read CRC");
71ecaafb7bSJinzhou Su break;
721c7b0adaSJinzhou Su case TA_SECUREDISPLAY_STATUS__I2C_INIT_ERROR:
731c7b0adaSJinzhou Su dev_err(psp->adev->dev, "Secure display: Failed to initialize I2C.");
741c7b0adaSJinzhou Su break;
75ecaafb7bSJinzhou Su default:
76ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "Secure display: Failed to parse status: %d\n", status);
77ecaafb7bSJinzhou Su }
78ecaafb7bSJinzhou Su }
79ecaafb7bSJinzhou Su
psp_prep_securedisplay_cmd_buf(struct psp_context * psp,struct ta_securedisplay_cmd ** cmd,enum ta_securedisplay_command command_id)80f6e856e7SAaron Liu void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct ta_securedisplay_cmd **cmd,
81ecaafb7bSJinzhou Su enum ta_securedisplay_command command_id)
82ecaafb7bSJinzhou Su {
83f6e856e7SAaron Liu *cmd = (struct ta_securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf;
84f6e856e7SAaron Liu memset(*cmd, 0, sizeof(struct ta_securedisplay_cmd));
85ecaafb7bSJinzhou Su (*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE;
86ecaafb7bSJinzhou Su (*cmd)->cmd_id = command_id;
87ecaafb7bSJinzhou Su }
88ecaafb7bSJinzhou Su
89195c41fbSJinzhou Su #if defined(CONFIG_DEBUG_FS)
90195c41fbSJinzhou Su
amdgpu_securedisplay_debugfs_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)91ecaafb7bSJinzhou Su static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __user *buf,
92ecaafb7bSJinzhou Su size_t size, loff_t *pos)
93ecaafb7bSJinzhou Su {
94ecaafb7bSJinzhou Su struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
95ecaafb7bSJinzhou Su struct psp_context *psp = &adev->psp;
96f6e856e7SAaron Liu struct ta_securedisplay_cmd *securedisplay_cmd;
97ecaafb7bSJinzhou Su struct drm_device *dev = adev_to_drm(adev);
98ecaafb7bSJinzhou Su uint32_t phy_id;
99ecaafb7bSJinzhou Su uint32_t op;
100ecaafb7bSJinzhou Su char str[64];
101ecaafb7bSJinzhou Su int ret;
102ecaafb7bSJinzhou Su
103ecaafb7bSJinzhou Su if (*pos || size > sizeof(str) - 1)
104ecaafb7bSJinzhou Su return -EINVAL;
105ecaafb7bSJinzhou Su
106ecaafb7bSJinzhou Su memset(str, 0, sizeof(str));
107ecaafb7bSJinzhou Su ret = copy_from_user(str, buf, size);
108ecaafb7bSJinzhou Su if (ret)
109ecaafb7bSJinzhou Su return -EFAULT;
110ecaafb7bSJinzhou Su
111ecaafb7bSJinzhou Su ret = pm_runtime_get_sync(dev->dev);
112ecaafb7bSJinzhou Su if (ret < 0) {
113ecaafb7bSJinzhou Su pm_runtime_put_autosuspend(dev->dev);
114ecaafb7bSJinzhou Su return ret;
115ecaafb7bSJinzhou Su }
116ecaafb7bSJinzhou Su
117ecaafb7bSJinzhou Su if (size < 3)
118ecaafb7bSJinzhou Su sscanf(str, "%u ", &op);
119ecaafb7bSJinzhou Su else
120ecaafb7bSJinzhou Su sscanf(str, "%u %u", &op, &phy_id);
121ecaafb7bSJinzhou Su
122ecaafb7bSJinzhou Su switch (op) {
123ecaafb7bSJinzhou Su case 1:
1247117007eSAlan Liu mutex_lock(&psp->securedisplay_context.mutex);
125ecaafb7bSJinzhou Su psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
126ecaafb7bSJinzhou Su TA_SECUREDISPLAY_COMMAND__QUERY_TA);
127ecaafb7bSJinzhou Su ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
128ecaafb7bSJinzhou Su if (!ret) {
129ecaafb7bSJinzhou Su if (securedisplay_cmd->status == TA_SECUREDISPLAY_STATUS__SUCCESS)
130ecaafb7bSJinzhou Su dev_info(adev->dev, "SECUREDISPLAY: query securedisplay TA ret is 0x%X\n",
131ecaafb7bSJinzhou Su securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret);
132ecaafb7bSJinzhou Su else
133ecaafb7bSJinzhou Su psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
134ecaafb7bSJinzhou Su }
1357117007eSAlan Liu mutex_unlock(&psp->securedisplay_context.mutex);
136ecaafb7bSJinzhou Su break;
137ecaafb7bSJinzhou Su case 2:
138*f71ef2bbSMa Jun if (size < 3 || phy_id >= TA_SECUREDISPLAY_MAX_PHY) {
139*f71ef2bbSMa Jun dev_err(adev->dev, "Invalid input: %s\n", str);
140*f71ef2bbSMa Jun return -EINVAL;
141*f71ef2bbSMa Jun }
1427117007eSAlan Liu mutex_lock(&psp->securedisplay_context.mutex);
143ecaafb7bSJinzhou Su psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
144ecaafb7bSJinzhou Su TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
145ecaafb7bSJinzhou Su securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id;
146ecaafb7bSJinzhou Su ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
147ecaafb7bSJinzhou Su if (!ret) {
148ecaafb7bSJinzhou Su if (securedisplay_cmd->status == TA_SECUREDISPLAY_STATUS__SUCCESS) {
1499e76e7b2SArnd Bergmann dev_info(adev->dev, "SECUREDISPLAY: I2C buffer out put is: %*ph\n",
1509e76e7b2SArnd Bergmann TA_SECUREDISPLAY_I2C_BUFFER_SIZE,
1519e76e7b2SArnd Bergmann securedisplay_cmd->securedisplay_out_message.send_roi_crc.i2c_buf);
152ecaafb7bSJinzhou Su } else {
153ecaafb7bSJinzhou Su psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
154ecaafb7bSJinzhou Su }
155ecaafb7bSJinzhou Su }
1567117007eSAlan Liu mutex_unlock(&psp->securedisplay_context.mutex);
157ecaafb7bSJinzhou Su break;
158ecaafb7bSJinzhou Su default:
159ecaafb7bSJinzhou Su dev_err(adev->dev, "Invalid input: %s\n", str);
160ecaafb7bSJinzhou Su }
161ecaafb7bSJinzhou Su
162ecaafb7bSJinzhou Su pm_runtime_mark_last_busy(dev->dev);
163ecaafb7bSJinzhou Su pm_runtime_put_autosuspend(dev->dev);
164ecaafb7bSJinzhou Su
165ecaafb7bSJinzhou Su return size;
166ecaafb7bSJinzhou Su }
167ecaafb7bSJinzhou Su
168ecaafb7bSJinzhou Su static const struct file_operations amdgpu_securedisplay_debugfs_ops = {
169ecaafb7bSJinzhou Su .owner = THIS_MODULE,
170ecaafb7bSJinzhou Su .read = NULL,
171ecaafb7bSJinzhou Su .write = amdgpu_securedisplay_debugfs_write,
172ecaafb7bSJinzhou Su .llseek = default_llseek
173ecaafb7bSJinzhou Su };
174ecaafb7bSJinzhou Su
175195c41fbSJinzhou Su #endif
176195c41fbSJinzhou Su
amdgpu_securedisplay_debugfs_init(struct amdgpu_device * adev)177ecaafb7bSJinzhou Su void amdgpu_securedisplay_debugfs_init(struct amdgpu_device *adev)
178ecaafb7bSJinzhou Su {
179ecaafb7bSJinzhou Su #if defined(CONFIG_DEBUG_FS)
180ecaafb7bSJinzhou Su
181ce97f37bSCandice Li if (!adev->psp.securedisplay_context.context.initialized)
182ecaafb7bSJinzhou Su return;
183ecaafb7bSJinzhou Su
184ecaafb7bSJinzhou Su debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root,
185ecaafb7bSJinzhou Su adev, &amdgpu_securedisplay_debugfs_ops);
186ecaafb7bSJinzhou Su #endif
187ecaafb7bSJinzhou Su }
188