1*4882a593Smuzhiyun // SPDX-License-Identifier: MIT
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AMD Trusted Execution Environment (TEE) interface
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Author: Rijo Thomas <Rijo-john.Thomas@amd.com>
6*4882a593Smuzhiyun * Author: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright 2019 Advanced Micro Devices, Inc.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/types.h>
12*4882a593Smuzhiyun #include <linux/mutex.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/slab.h>
15*4882a593Smuzhiyun #include <linux/gfp.h>
16*4882a593Smuzhiyun #include <linux/psp-sev.h>
17*4882a593Smuzhiyun #include <linux/psp-tee.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "psp-dev.h"
20*4882a593Smuzhiyun #include "tee-dev.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static bool psp_dead;
23*4882a593Smuzhiyun
tee_alloc_ring(struct psp_tee_device * tee,int ring_size)24*4882a593Smuzhiyun static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
27*4882a593Smuzhiyun void *start_addr;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun if (!ring_size)
30*4882a593Smuzhiyun return -EINVAL;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* We need actual physical address instead of DMA address, since
33*4882a593Smuzhiyun * Trusted OS running on AMD Secure Processor will map this region
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));
36*4882a593Smuzhiyun if (!start_addr)
37*4882a593Smuzhiyun return -ENOMEM;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun memset(start_addr, 0x0, ring_size);
40*4882a593Smuzhiyun rb_mgr->ring_start = start_addr;
41*4882a593Smuzhiyun rb_mgr->ring_size = ring_size;
42*4882a593Smuzhiyun rb_mgr->ring_pa = __psp_pa(start_addr);
43*4882a593Smuzhiyun mutex_init(&rb_mgr->mutex);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun return 0;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
tee_free_ring(struct psp_tee_device * tee)48*4882a593Smuzhiyun static void tee_free_ring(struct psp_tee_device *tee)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (!rb_mgr->ring_start)
53*4882a593Smuzhiyun return;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun free_pages((unsigned long)rb_mgr->ring_start,
56*4882a593Smuzhiyun get_order(rb_mgr->ring_size));
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun rb_mgr->ring_start = NULL;
59*4882a593Smuzhiyun rb_mgr->ring_size = 0;
60*4882a593Smuzhiyun rb_mgr->ring_pa = 0;
61*4882a593Smuzhiyun mutex_destroy(&rb_mgr->mutex);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
tee_wait_cmd_poll(struct psp_tee_device * tee,unsigned int timeout,unsigned int * reg)64*4882a593Smuzhiyun static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
65*4882a593Smuzhiyun unsigned int *reg)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun /* ~10ms sleep per loop => nloop = timeout * 100 */
68*4882a593Smuzhiyun int nloop = timeout * 100;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun while (--nloop) {
71*4882a593Smuzhiyun *reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
72*4882a593Smuzhiyun if (*reg & PSP_CMDRESP_RESP)
73*4882a593Smuzhiyun return 0;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun usleep_range(10000, 10100);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
79*4882a593Smuzhiyun psp_dead = true;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun return -ETIMEDOUT;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun static
tee_alloc_cmd_buffer(struct psp_tee_device * tee)85*4882a593Smuzhiyun struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct tee_init_ring_cmd *cmd;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
90*4882a593Smuzhiyun if (!cmd)
91*4882a593Smuzhiyun return NULL;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);
94*4882a593Smuzhiyun cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);
95*4882a593Smuzhiyun cmd->size = tee->rb_mgr.ring_size;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",
98*4882a593Smuzhiyun cmd->hi_addr, cmd->low_addr, cmd->size);
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun return cmd;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
tee_free_cmd_buffer(struct tee_init_ring_cmd * cmd)103*4882a593Smuzhiyun static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun kfree(cmd);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
tee_init_ring(struct psp_tee_device * tee)108*4882a593Smuzhiyun static int tee_init_ring(struct psp_tee_device *tee)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
111*4882a593Smuzhiyun struct tee_init_ring_cmd *cmd;
112*4882a593Smuzhiyun phys_addr_t cmd_buffer;
113*4882a593Smuzhiyun unsigned int reg;
114*4882a593Smuzhiyun int ret;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun ret = tee_alloc_ring(tee, ring_size);
119*4882a593Smuzhiyun if (ret) {
120*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);
121*4882a593Smuzhiyun return ret;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun tee->rb_mgr.wptr = 0;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun cmd = tee_alloc_cmd_buffer(tee);
127*4882a593Smuzhiyun if (!cmd) {
128*4882a593Smuzhiyun tee_free_ring(tee);
129*4882a593Smuzhiyun return -ENOMEM;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun cmd_buffer = __psp_pa((void *)cmd);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* Send command buffer details to Trusted OS by writing to
135*4882a593Smuzhiyun * CPU-PSP message registers
136*4882a593Smuzhiyun */
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun iowrite32(lower_32_bits(cmd_buffer),
139*4882a593Smuzhiyun tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
140*4882a593Smuzhiyun iowrite32(upper_32_bits(cmd_buffer),
141*4882a593Smuzhiyun tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
142*4882a593Smuzhiyun iowrite32(TEE_RING_INIT_CMD,
143*4882a593Smuzhiyun tee->io_regs + tee->vdata->cmdresp_reg);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
146*4882a593Smuzhiyun if (ret) {
147*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring init command timed out\n");
148*4882a593Smuzhiyun tee_free_ring(tee);
149*4882a593Smuzhiyun goto free_buf;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (reg & PSP_CMDRESP_ERR_MASK) {
153*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring init command failed (%#010x)\n",
154*4882a593Smuzhiyun reg & PSP_CMDRESP_ERR_MASK);
155*4882a593Smuzhiyun tee_free_ring(tee);
156*4882a593Smuzhiyun ret = -EIO;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun free_buf:
160*4882a593Smuzhiyun tee_free_cmd_buffer(cmd);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun return ret;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
tee_destroy_ring(struct psp_tee_device * tee)165*4882a593Smuzhiyun static void tee_destroy_ring(struct psp_tee_device *tee)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun unsigned int reg;
168*4882a593Smuzhiyun int ret;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun if (!tee->rb_mgr.ring_start)
171*4882a593Smuzhiyun return;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (psp_dead)
174*4882a593Smuzhiyun goto free_ring;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun iowrite32(TEE_RING_DESTROY_CMD,
177*4882a593Smuzhiyun tee->io_regs + tee->vdata->cmdresp_reg);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®);
180*4882a593Smuzhiyun if (ret) {
181*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring destroy command timed out\n");
182*4882a593Smuzhiyun } else if (reg & PSP_CMDRESP_ERR_MASK) {
183*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring destroy command failed (%#010x)\n",
184*4882a593Smuzhiyun reg & PSP_CMDRESP_ERR_MASK);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun free_ring:
188*4882a593Smuzhiyun tee_free_ring(tee);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
tee_dev_init(struct psp_device * psp)191*4882a593Smuzhiyun int tee_dev_init(struct psp_device *psp)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun struct device *dev = psp->dev;
194*4882a593Smuzhiyun struct psp_tee_device *tee;
195*4882a593Smuzhiyun int ret;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun ret = -ENOMEM;
198*4882a593Smuzhiyun tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);
199*4882a593Smuzhiyun if (!tee)
200*4882a593Smuzhiyun goto e_err;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun psp->tee_data = tee;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun tee->dev = dev;
205*4882a593Smuzhiyun tee->psp = psp;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun tee->io_regs = psp->io_regs;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun tee->vdata = (struct tee_vdata *)psp->vdata->tee;
210*4882a593Smuzhiyun if (!tee->vdata) {
211*4882a593Smuzhiyun ret = -ENODEV;
212*4882a593Smuzhiyun dev_err(dev, "tee: missing driver data\n");
213*4882a593Smuzhiyun goto e_err;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun ret = tee_init_ring(tee);
217*4882a593Smuzhiyun if (ret) {
218*4882a593Smuzhiyun dev_err(dev, "tee: failed to init ring buffer\n");
219*4882a593Smuzhiyun goto e_err;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun dev_notice(dev, "tee enabled\n");
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun return 0;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun e_err:
227*4882a593Smuzhiyun psp->tee_data = NULL;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun dev_notice(dev, "tee initialization failed\n");
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
tee_dev_destroy(struct psp_device * psp)234*4882a593Smuzhiyun void tee_dev_destroy(struct psp_device *psp)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct psp_tee_device *tee = psp->tee_data;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (!tee)
239*4882a593Smuzhiyun return;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun tee_destroy_ring(tee);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
tee_submit_cmd(struct psp_tee_device * tee,enum tee_cmd_id cmd_id,void * buf,size_t len,struct tee_ring_cmd ** resp)244*4882a593Smuzhiyun static int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id,
245*4882a593Smuzhiyun void *buf, size_t len, struct tee_ring_cmd **resp)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun struct tee_ring_cmd *cmd;
248*4882a593Smuzhiyun int nloop = 1000, ret = 0;
249*4882a593Smuzhiyun u32 rptr;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun *resp = NULL;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun mutex_lock(&tee->rb_mgr.mutex);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* Loop until empty entry found in ring buffer */
256*4882a593Smuzhiyun do {
257*4882a593Smuzhiyun /* Get pointer to ring buffer command entry */
258*4882a593Smuzhiyun cmd = (struct tee_ring_cmd *)
259*4882a593Smuzhiyun (tee->rb_mgr.ring_start + tee->rb_mgr.wptr);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg);
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /* Check if ring buffer is full or command entry is waiting
264*4882a593Smuzhiyun * for response from TEE
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun if (!(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
267*4882a593Smuzhiyun cmd->flag == CMD_WAITING_FOR_RESPONSE))
268*4882a593Smuzhiyun break;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun dev_dbg(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n",
271*4882a593Smuzhiyun rptr, tee->rb_mgr.wptr);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /* Wait if ring buffer is full or TEE is processing data */
274*4882a593Smuzhiyun mutex_unlock(&tee->rb_mgr.mutex);
275*4882a593Smuzhiyun schedule_timeout_interruptible(msecs_to_jiffies(10));
276*4882a593Smuzhiyun mutex_lock(&tee->rb_mgr.mutex);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun } while (--nloop);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (!nloop &&
281*4882a593Smuzhiyun (tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
282*4882a593Smuzhiyun cmd->flag == CMD_WAITING_FOR_RESPONSE)) {
283*4882a593Smuzhiyun dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u response flag %u\n",
284*4882a593Smuzhiyun rptr, tee->rb_mgr.wptr, cmd->flag);
285*4882a593Smuzhiyun ret = -EBUSY;
286*4882a593Smuzhiyun goto unlock;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Do not submit command if PSP got disabled while processing any
290*4882a593Smuzhiyun * command in another thread
291*4882a593Smuzhiyun */
292*4882a593Smuzhiyun if (psp_dead) {
293*4882a593Smuzhiyun ret = -EBUSY;
294*4882a593Smuzhiyun goto unlock;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun /* Write command data into ring buffer */
298*4882a593Smuzhiyun cmd->cmd_id = cmd_id;
299*4882a593Smuzhiyun cmd->cmd_state = TEE_CMD_STATE_INIT;
300*4882a593Smuzhiyun memset(&cmd->buf[0], 0, sizeof(cmd->buf));
301*4882a593Smuzhiyun memcpy(&cmd->buf[0], buf, len);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Indicate driver is waiting for response */
304*4882a593Smuzhiyun cmd->flag = CMD_WAITING_FOR_RESPONSE;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* Update local copy of write pointer */
307*4882a593Smuzhiyun tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd);
308*4882a593Smuzhiyun if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size)
309*4882a593Smuzhiyun tee->rb_mgr.wptr = 0;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun /* Trigger interrupt to Trusted OS */
312*4882a593Smuzhiyun iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* The response is provided by Trusted OS in same
315*4882a593Smuzhiyun * location as submitted data entry within ring buffer.
316*4882a593Smuzhiyun */
317*4882a593Smuzhiyun *resp = cmd;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun unlock:
320*4882a593Smuzhiyun mutex_unlock(&tee->rb_mgr.mutex);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun return ret;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
tee_wait_cmd_completion(struct psp_tee_device * tee,struct tee_ring_cmd * resp,unsigned int timeout)325*4882a593Smuzhiyun static int tee_wait_cmd_completion(struct psp_tee_device *tee,
326*4882a593Smuzhiyun struct tee_ring_cmd *resp,
327*4882a593Smuzhiyun unsigned int timeout)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun /* ~5ms sleep per loop => nloop = timeout * 200 */
330*4882a593Smuzhiyun int nloop = timeout * 200;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun while (--nloop) {
333*4882a593Smuzhiyun if (resp->cmd_state == TEE_CMD_STATE_COMPLETED)
334*4882a593Smuzhiyun return 0;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun usleep_range(5000, 5100);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n",
340*4882a593Smuzhiyun resp->cmd_id);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun psp_dead = true;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun return -ETIMEDOUT;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
psp_tee_process_cmd(enum tee_cmd_id cmd_id,void * buf,size_t len,u32 * status)347*4882a593Smuzhiyun int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,
348*4882a593Smuzhiyun u32 *status)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun struct psp_device *psp = psp_get_master_device();
351*4882a593Smuzhiyun struct psp_tee_device *tee;
352*4882a593Smuzhiyun struct tee_ring_cmd *resp;
353*4882a593Smuzhiyun int ret;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (!buf || !status || !len || len > sizeof(resp->buf))
356*4882a593Smuzhiyun return -EINVAL;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun *status = 0;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun if (!psp || !psp->tee_data)
361*4882a593Smuzhiyun return -ENODEV;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (psp_dead)
364*4882a593Smuzhiyun return -EBUSY;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun tee = psp->tee_data;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp);
369*4882a593Smuzhiyun if (ret)
370*4882a593Smuzhiyun return ret;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT);
373*4882a593Smuzhiyun if (ret) {
374*4882a593Smuzhiyun resp->flag = CMD_RESPONSE_TIMEDOUT;
375*4882a593Smuzhiyun return ret;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun memcpy(buf, &resp->buf[0], len);
379*4882a593Smuzhiyun *status = resp->status;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun resp->flag = CMD_RESPONSE_COPIED;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun return 0;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun EXPORT_SYMBOL(psp_tee_process_cmd);
386*4882a593Smuzhiyun
psp_check_tee_status(void)387*4882a593Smuzhiyun int psp_check_tee_status(void)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun struct psp_device *psp = psp_get_master_device();
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun if (!psp || !psp->tee_data)
392*4882a593Smuzhiyun return -ENODEV;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun return 0;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun EXPORT_SYMBOL(psp_check_tee_status);
397