15ca02815Sjsg /* 25ca02815Sjsg * Copyright 2021 Advanced Micro Devices, Inc. 35ca02815Sjsg * 45ca02815Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 55ca02815Sjsg * copy of this software and associated documentation files (the "Software"), 65ca02815Sjsg * to deal in the Software without restriction, including without limitation 75ca02815Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85ca02815Sjsg * and/or sell copies of the Software, and to permit persons to whom the 95ca02815Sjsg * Software is furnished to do so, subject to the following conditions: 105ca02815Sjsg * 115ca02815Sjsg * The above copyright notice and this permission notice shall be included in 125ca02815Sjsg * all copies or substantial portions of the Software. 135ca02815Sjsg * 145ca02815Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155ca02815Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165ca02815Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175ca02815Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 185ca02815Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 195ca02815Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 205ca02815Sjsg * OTHER DEALINGS IN THE SOFTWARE. 215ca02815Sjsg * 225ca02815Sjsg * 235ca02815Sjsg */ 245ca02815Sjsg #include <linux/debugfs.h> 255ca02815Sjsg #include <linux/pm_runtime.h> 265ca02815Sjsg 275ca02815Sjsg #include "amdgpu.h" 285ca02815Sjsg #include "amdgpu_securedisplay.h" 295ca02815Sjsg 305ca02815Sjsg /** 315ca02815Sjsg * DOC: AMDGPU SECUREDISPLAY debugfs test interface 325ca02815Sjsg * 335ca02815Sjsg * how to use? 345ca02815Sjsg * echo opcode <value> > <debugfs_dir>/dri/xxx/securedisplay_test 355ca02815Sjsg * eg. echo 1 > <debugfs_dir>/dri/xxx/securedisplay_test 365ca02815Sjsg * eg. echo 2 phy_id > <debugfs_dir>/dri/xxx/securedisplay_test 375ca02815Sjsg * 385ca02815Sjsg * opcode: 395ca02815Sjsg * 1:Query whether TA is responding used only for validation pupose 405ca02815Sjsg * 2: Send region of Interest and CRC value to I2C. (uint32)phy_id is 415ca02815Sjsg * send to determine which DIO scratch register should be used to get 425ca02815Sjsg * ROI and receive i2c_buf as the output. 435ca02815Sjsg * 445ca02815Sjsg * You can refer more detail from header file ta_securedisplay_if.h 455ca02815Sjsg * 465ca02815Sjsg */ 475ca02815Sjsg 485ca02815Sjsg void psp_securedisplay_parse_resp_status(struct psp_context *psp, 495ca02815Sjsg enum ta_securedisplay_status status) 505ca02815Sjsg { 515ca02815Sjsg switch (status) { 525ca02815Sjsg case TA_SECUREDISPLAY_STATUS__SUCCESS: 535ca02815Sjsg break; 545ca02815Sjsg case TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE: 555ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Generic Failure."); 565ca02815Sjsg break; 575ca02815Sjsg case TA_SECUREDISPLAY_STATUS__INVALID_PARAMETER: 585ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Invalid Parameter."); 595ca02815Sjsg break; 605ca02815Sjsg case TA_SECUREDISPLAY_STATUS__NULL_POINTER: 615ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Null Pointer."); 625ca02815Sjsg break; 635ca02815Sjsg case TA_SECUREDISPLAY_STATUS__I2C_WRITE_ERROR: 645ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Failed to write to I2C."); 655ca02815Sjsg break; 665ca02815Sjsg case TA_SECUREDISPLAY_STATUS__READ_DIO_SCRATCH_ERROR: 675ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Failed to Read DIO Scratch Register."); 685ca02815Sjsg break; 695ca02815Sjsg case TA_SECUREDISPLAY_STATUS__READ_CRC_ERROR: 705ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Failed to Read CRC"); 715ca02815Sjsg break; 725ca02815Sjsg case TA_SECUREDISPLAY_STATUS__I2C_INIT_ERROR: 735ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Failed to initialize I2C."); 745ca02815Sjsg break; 755ca02815Sjsg default: 765ca02815Sjsg dev_err(psp->adev->dev, "Secure display: Failed to parse status: %d\n", status); 775ca02815Sjsg } 785ca02815Sjsg } 795ca02815Sjsg 80f005ef32Sjsg void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct ta_securedisplay_cmd **cmd, 815ca02815Sjsg enum ta_securedisplay_command command_id) 825ca02815Sjsg { 83f005ef32Sjsg *cmd = (struct ta_securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf; 84f005ef32Sjsg memset(*cmd, 0, sizeof(struct ta_securedisplay_cmd)); 855ca02815Sjsg (*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE; 865ca02815Sjsg (*cmd)->cmd_id = command_id; 875ca02815Sjsg } 885ca02815Sjsg 895ca02815Sjsg #if defined(CONFIG_DEBUG_FS) 905ca02815Sjsg 915ca02815Sjsg static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __user *buf, 925ca02815Sjsg size_t size, loff_t *pos) 935ca02815Sjsg { 945ca02815Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 955ca02815Sjsg struct psp_context *psp = &adev->psp; 96f005ef32Sjsg struct ta_securedisplay_cmd *securedisplay_cmd; 975ca02815Sjsg struct drm_device *dev = adev_to_drm(adev); 985ca02815Sjsg uint32_t phy_id; 995ca02815Sjsg uint32_t op; 1005ca02815Sjsg char str[64]; 1015ca02815Sjsg int ret; 1025ca02815Sjsg 1035ca02815Sjsg if (*pos || size > sizeof(str) - 1) 1045ca02815Sjsg return -EINVAL; 1055ca02815Sjsg 1065ca02815Sjsg memset(str, 0, sizeof(str)); 1075ca02815Sjsg ret = copy_from_user(str, buf, size); 1085ca02815Sjsg if (ret) 1095ca02815Sjsg return -EFAULT; 1105ca02815Sjsg 1115ca02815Sjsg ret = pm_runtime_get_sync(dev->dev); 1125ca02815Sjsg if (ret < 0) { 1135ca02815Sjsg pm_runtime_put_autosuspend(dev->dev); 1145ca02815Sjsg return ret; 1155ca02815Sjsg } 1165ca02815Sjsg 1175ca02815Sjsg if (size < 3) 1185ca02815Sjsg sscanf(str, "%u ", &op); 1195ca02815Sjsg else 1205ca02815Sjsg sscanf(str, "%u %u", &op, &phy_id); 1215ca02815Sjsg 1225ca02815Sjsg switch (op) { 1235ca02815Sjsg case 1: 124f005ef32Sjsg mutex_lock(&psp->securedisplay_context.mutex); 1255ca02815Sjsg psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, 1265ca02815Sjsg TA_SECUREDISPLAY_COMMAND__QUERY_TA); 1275ca02815Sjsg ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); 1285ca02815Sjsg if (!ret) { 1295ca02815Sjsg if (securedisplay_cmd->status == TA_SECUREDISPLAY_STATUS__SUCCESS) 1305ca02815Sjsg dev_info(adev->dev, "SECUREDISPLAY: query securedisplay TA ret is 0x%X\n", 1315ca02815Sjsg securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret); 1325ca02815Sjsg else 1335ca02815Sjsg psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); 1345ca02815Sjsg } 135f005ef32Sjsg mutex_unlock(&psp->securedisplay_context.mutex); 1365ca02815Sjsg break; 1375ca02815Sjsg case 2: 138*6d3905f3Sjsg if (size < 3 || phy_id >= TA_SECUREDISPLAY_MAX_PHY) { 139*6d3905f3Sjsg dev_err(adev->dev, "Invalid input: %s\n", str); 140*6d3905f3Sjsg return -EINVAL; 141*6d3905f3Sjsg } 142f005ef32Sjsg mutex_lock(&psp->securedisplay_context.mutex); 1435ca02815Sjsg psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, 1445ca02815Sjsg TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); 1455ca02815Sjsg securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id; 1465ca02815Sjsg ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC); 1475ca02815Sjsg if (!ret) { 1485ca02815Sjsg if (securedisplay_cmd->status == TA_SECUREDISPLAY_STATUS__SUCCESS) { 1495ca02815Sjsg dev_info(adev->dev, "SECUREDISPLAY: I2C buffer out put is: %*ph\n", 1505ca02815Sjsg TA_SECUREDISPLAY_I2C_BUFFER_SIZE, 1515ca02815Sjsg securedisplay_cmd->securedisplay_out_message.send_roi_crc.i2c_buf); 1525ca02815Sjsg } else { 1535ca02815Sjsg psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); 1545ca02815Sjsg } 1555ca02815Sjsg } 156f005ef32Sjsg mutex_unlock(&psp->securedisplay_context.mutex); 1575ca02815Sjsg break; 1585ca02815Sjsg default: 1595ca02815Sjsg dev_err(adev->dev, "Invalid input: %s\n", str); 1605ca02815Sjsg } 1615ca02815Sjsg 1625ca02815Sjsg pm_runtime_mark_last_busy(dev->dev); 1635ca02815Sjsg pm_runtime_put_autosuspend(dev->dev); 1645ca02815Sjsg 1655ca02815Sjsg return size; 1665ca02815Sjsg } 1675ca02815Sjsg 1685ca02815Sjsg static const struct file_operations amdgpu_securedisplay_debugfs_ops = { 1695ca02815Sjsg .owner = THIS_MODULE, 1705ca02815Sjsg .read = NULL, 1715ca02815Sjsg .write = amdgpu_securedisplay_debugfs_write, 1725ca02815Sjsg .llseek = default_llseek 1735ca02815Sjsg }; 1745ca02815Sjsg 1755ca02815Sjsg #endif 1765ca02815Sjsg 1775ca02815Sjsg void amdgpu_securedisplay_debugfs_init(struct amdgpu_device *adev) 1785ca02815Sjsg { 1795ca02815Sjsg #if defined(CONFIG_DEBUG_FS) 1805ca02815Sjsg 1815ca02815Sjsg if (!adev->psp.securedisplay_context.context.initialized) 1825ca02815Sjsg return; 1835ca02815Sjsg 1845ca02815Sjsg debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root, 1855ca02815Sjsg adev, &amdgpu_securedisplay_debugfs_ops); 1865ca02815Sjsg #endif 1875ca02815Sjsg } 188