162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD Trusted Execution Environment (TEE) interface 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Rijo Thomas <Rijo-john.Thomas@amd.com> 662306a36Sopenharmony_ci * Author: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2019,2021 Advanced Micro Devices, Inc. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/bitfield.h> 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <linux/mutex.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/gfp.h> 1762306a36Sopenharmony_ci#include <linux/psp.h> 1862306a36Sopenharmony_ci#include <linux/psp-tee.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "psp-dev.h" 2162306a36Sopenharmony_ci#include "tee-dev.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic bool psp_dead; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int tee_alloc_ring(struct psp_tee_device *tee, int ring_size) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct ring_buf_manager *rb_mgr = &tee->rb_mgr; 2862306a36Sopenharmony_ci void *start_addr; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if (!ring_size) 3162306a36Sopenharmony_ci return -EINVAL; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci /* We need actual physical address instead of DMA address, since 3462306a36Sopenharmony_ci * Trusted OS running on AMD Secure Processor will map this region 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size)); 3762306a36Sopenharmony_ci if (!start_addr) 3862306a36Sopenharmony_ci return -ENOMEM; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci memset(start_addr, 0x0, ring_size); 4162306a36Sopenharmony_ci rb_mgr->ring_start = start_addr; 4262306a36Sopenharmony_ci rb_mgr->ring_size = ring_size; 4362306a36Sopenharmony_ci rb_mgr->ring_pa = __psp_pa(start_addr); 4462306a36Sopenharmony_ci mutex_init(&rb_mgr->mutex); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void tee_free_ring(struct psp_tee_device *tee) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct ring_buf_manager *rb_mgr = &tee->rb_mgr; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (!rb_mgr->ring_start) 5462306a36Sopenharmony_ci return; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci free_pages((unsigned long)rb_mgr->ring_start, 5762306a36Sopenharmony_ci get_order(rb_mgr->ring_size)); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci rb_mgr->ring_start = NULL; 6062306a36Sopenharmony_ci rb_mgr->ring_size = 0; 6162306a36Sopenharmony_ci rb_mgr->ring_pa = 0; 6262306a36Sopenharmony_ci mutex_destroy(&rb_mgr->mutex); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout, 6662306a36Sopenharmony_ci unsigned int *reg) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci /* ~10ms sleep per loop => nloop = timeout * 100 */ 6962306a36Sopenharmony_ci int nloop = timeout * 100; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci while (--nloop) { 7262306a36Sopenharmony_ci *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg); 7362306a36Sopenharmony_ci if (FIELD_GET(PSP_CMDRESP_RESP, *reg)) 7462306a36Sopenharmony_ci return 0; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci usleep_range(10000, 10100); 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci dev_err(tee->dev, "tee: command timed out, disabling PSP\n"); 8062306a36Sopenharmony_ci psp_dead = true; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return -ETIMEDOUT; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic 8662306a36Sopenharmony_cistruct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct tee_init_ring_cmd *cmd; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 9162306a36Sopenharmony_ci if (!cmd) 9262306a36Sopenharmony_ci return NULL; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa); 9562306a36Sopenharmony_ci cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa); 9662306a36Sopenharmony_ci cmd->size = tee->rb_mgr.ring_size; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n", 9962306a36Sopenharmony_ci cmd->hi_addr, cmd->low_addr, cmd->size); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return cmd; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci kfree(cmd); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int tee_init_ring(struct psp_tee_device *tee) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd); 11262306a36Sopenharmony_ci struct tee_init_ring_cmd *cmd; 11362306a36Sopenharmony_ci phys_addr_t cmd_buffer; 11462306a36Sopenharmony_ci unsigned int reg; 11562306a36Sopenharmony_ci int ret; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci ret = tee_alloc_ring(tee, ring_size); 12062306a36Sopenharmony_ci if (ret) { 12162306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring allocation failed %d\n", ret); 12262306a36Sopenharmony_ci return ret; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci tee->rb_mgr.wptr = 0; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci cmd = tee_alloc_cmd_buffer(tee); 12862306a36Sopenharmony_ci if (!cmd) { 12962306a36Sopenharmony_ci tee_free_ring(tee); 13062306a36Sopenharmony_ci return -ENOMEM; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci cmd_buffer = __psp_pa((void *)cmd); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* Send command buffer details to Trusted OS by writing to 13662306a36Sopenharmony_ci * CPU-PSP message registers 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci iowrite32(lower_32_bits(cmd_buffer), 14062306a36Sopenharmony_ci tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg); 14162306a36Sopenharmony_ci iowrite32(upper_32_bits(cmd_buffer), 14262306a36Sopenharmony_ci tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg); 14362306a36Sopenharmony_ci iowrite32(TEE_RING_INIT_CMD, 14462306a36Sopenharmony_ci tee->io_regs + tee->vdata->cmdresp_reg); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); 14762306a36Sopenharmony_ci if (ret) { 14862306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring init command timed out\n"); 14962306a36Sopenharmony_ci tee_free_ring(tee); 15062306a36Sopenharmony_ci goto free_buf; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (FIELD_GET(PSP_CMDRESP_STS, reg)) { 15462306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n", 15562306a36Sopenharmony_ci FIELD_GET(PSP_CMDRESP_STS, reg)); 15662306a36Sopenharmony_ci tee_free_ring(tee); 15762306a36Sopenharmony_ci ret = -EIO; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cifree_buf: 16162306a36Sopenharmony_ci tee_free_cmd_buffer(cmd); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return ret; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic void tee_destroy_ring(struct psp_tee_device *tee) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci unsigned int reg; 16962306a36Sopenharmony_ci int ret; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (!tee->rb_mgr.ring_start) 17262306a36Sopenharmony_ci return; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (psp_dead) 17562306a36Sopenharmony_ci goto free_ring; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci iowrite32(TEE_RING_DESTROY_CMD, 17862306a36Sopenharmony_ci tee->io_regs + tee->vdata->cmdresp_reg); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); 18162306a36Sopenharmony_ci if (ret) { 18262306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring destroy command timed out\n"); 18362306a36Sopenharmony_ci } else if (FIELD_GET(PSP_CMDRESP_STS, reg)) { 18462306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", 18562306a36Sopenharmony_ci FIELD_GET(PSP_CMDRESP_STS, reg)); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cifree_ring: 18962306a36Sopenharmony_ci tee_free_ring(tee); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciint tee_dev_init(struct psp_device *psp) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct device *dev = psp->dev; 19562306a36Sopenharmony_ci struct psp_tee_device *tee; 19662306a36Sopenharmony_ci int ret; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci ret = -ENOMEM; 19962306a36Sopenharmony_ci tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL); 20062306a36Sopenharmony_ci if (!tee) 20162306a36Sopenharmony_ci goto e_err; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci psp->tee_data = tee; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci tee->dev = dev; 20662306a36Sopenharmony_ci tee->psp = psp; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci tee->io_regs = psp->io_regs; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci tee->vdata = (struct tee_vdata *)psp->vdata->tee; 21162306a36Sopenharmony_ci if (!tee->vdata) { 21262306a36Sopenharmony_ci ret = -ENODEV; 21362306a36Sopenharmony_ci dev_err(dev, "tee: missing driver data\n"); 21462306a36Sopenharmony_ci goto e_err; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ret = tee_init_ring(tee); 21862306a36Sopenharmony_ci if (ret) { 21962306a36Sopenharmony_ci dev_err(dev, "tee: failed to init ring buffer\n"); 22062306a36Sopenharmony_ci goto e_err; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci dev_notice(dev, "tee enabled\n"); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cie_err: 22862306a36Sopenharmony_ci psp->tee_data = NULL; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci dev_notice(dev, "tee initialization failed\n"); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return ret; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_civoid tee_dev_destroy(struct psp_device *psp) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct psp_tee_device *tee = psp->tee_data; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (!tee) 24062306a36Sopenharmony_ci return; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci tee_destroy_ring(tee); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id, 24662306a36Sopenharmony_ci void *buf, size_t len, struct tee_ring_cmd **resp) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct tee_ring_cmd *cmd; 24962306a36Sopenharmony_ci int nloop = 1000, ret = 0; 25062306a36Sopenharmony_ci u32 rptr; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci *resp = NULL; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci mutex_lock(&tee->rb_mgr.mutex); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Loop until empty entry found in ring buffer */ 25762306a36Sopenharmony_ci do { 25862306a36Sopenharmony_ci /* Get pointer to ring buffer command entry */ 25962306a36Sopenharmony_ci cmd = (struct tee_ring_cmd *) 26062306a36Sopenharmony_ci (tee->rb_mgr.ring_start + tee->rb_mgr.wptr); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci /* Check if ring buffer is full or command entry is waiting 26562306a36Sopenharmony_ci * for response from TEE 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ci if (!(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr || 26862306a36Sopenharmony_ci cmd->flag == CMD_WAITING_FOR_RESPONSE)) 26962306a36Sopenharmony_ci break; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci dev_dbg(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n", 27262306a36Sopenharmony_ci rptr, tee->rb_mgr.wptr); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* Wait if ring buffer is full or TEE is processing data */ 27562306a36Sopenharmony_ci mutex_unlock(&tee->rb_mgr.mutex); 27662306a36Sopenharmony_ci schedule_timeout_interruptible(msecs_to_jiffies(10)); 27762306a36Sopenharmony_ci mutex_lock(&tee->rb_mgr.mutex); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci } while (--nloop); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (!nloop && 28262306a36Sopenharmony_ci (tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr || 28362306a36Sopenharmony_ci cmd->flag == CMD_WAITING_FOR_RESPONSE)) { 28462306a36Sopenharmony_ci dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u response flag %u\n", 28562306a36Sopenharmony_ci rptr, tee->rb_mgr.wptr, cmd->flag); 28662306a36Sopenharmony_ci ret = -EBUSY; 28762306a36Sopenharmony_ci goto unlock; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* Do not submit command if PSP got disabled while processing any 29162306a36Sopenharmony_ci * command in another thread 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci if (psp_dead) { 29462306a36Sopenharmony_ci ret = -EBUSY; 29562306a36Sopenharmony_ci goto unlock; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* Write command data into ring buffer */ 29962306a36Sopenharmony_ci cmd->cmd_id = cmd_id; 30062306a36Sopenharmony_ci cmd->cmd_state = TEE_CMD_STATE_INIT; 30162306a36Sopenharmony_ci memset(&cmd->buf[0], 0, sizeof(cmd->buf)); 30262306a36Sopenharmony_ci memcpy(&cmd->buf[0], buf, len); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* Indicate driver is waiting for response */ 30562306a36Sopenharmony_ci cmd->flag = CMD_WAITING_FOR_RESPONSE; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* Update local copy of write pointer */ 30862306a36Sopenharmony_ci tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd); 30962306a36Sopenharmony_ci if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size) 31062306a36Sopenharmony_ci tee->rb_mgr.wptr = 0; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* Trigger interrupt to Trusted OS */ 31362306a36Sopenharmony_ci iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* The response is provided by Trusted OS in same 31662306a36Sopenharmony_ci * location as submitted data entry within ring buffer. 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_ci *resp = cmd; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciunlock: 32162306a36Sopenharmony_ci mutex_unlock(&tee->rb_mgr.mutex); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci return ret; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic int tee_wait_cmd_completion(struct psp_tee_device *tee, 32762306a36Sopenharmony_ci struct tee_ring_cmd *resp, 32862306a36Sopenharmony_ci unsigned int timeout) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci /* ~1ms sleep per loop => nloop = timeout * 1000 */ 33162306a36Sopenharmony_ci int nloop = timeout * 1000; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci while (--nloop) { 33462306a36Sopenharmony_ci if (resp->cmd_state == TEE_CMD_STATE_COMPLETED) 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci usleep_range(1000, 1100); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n", 34162306a36Sopenharmony_ci resp->cmd_id); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci psp_dead = true; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return -ETIMEDOUT; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ciint psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len, 34962306a36Sopenharmony_ci u32 *status) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci struct psp_device *psp = psp_get_master_device(); 35262306a36Sopenharmony_ci struct psp_tee_device *tee; 35362306a36Sopenharmony_ci struct tee_ring_cmd *resp; 35462306a36Sopenharmony_ci int ret; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (!buf || !status || !len || len > sizeof(resp->buf)) 35762306a36Sopenharmony_ci return -EINVAL; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci *status = 0; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (!psp || !psp->tee_data) 36262306a36Sopenharmony_ci return -ENODEV; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (psp_dead) 36562306a36Sopenharmony_ci return -EBUSY; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci tee = psp->tee_data; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp); 37062306a36Sopenharmony_ci if (ret) 37162306a36Sopenharmony_ci return ret; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT); 37462306a36Sopenharmony_ci if (ret) { 37562306a36Sopenharmony_ci resp->flag = CMD_RESPONSE_TIMEDOUT; 37662306a36Sopenharmony_ci return ret; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci memcpy(buf, &resp->buf[0], len); 38062306a36Sopenharmony_ci *status = resp->status; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci resp->flag = CMD_RESPONSE_COPIED; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci return 0; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ciEXPORT_SYMBOL(psp_tee_process_cmd); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ciint psp_check_tee_status(void) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct psp_device *psp = psp_get_master_device(); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (!psp || !psp->tee_data) 39362306a36Sopenharmony_ci return -ENODEV; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci return 0; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ciEXPORT_SYMBOL(psp_check_tee_status); 398