xref: /openbmc/linux/drivers/crypto/ccp/tee-dev.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
133960accSRijo Thomas // SPDX-License-Identifier: MIT
233960accSRijo Thomas /*
333960accSRijo Thomas  * AMD Trusted Execution Environment (TEE) interface
433960accSRijo Thomas  *
533960accSRijo Thomas  * Author: Rijo Thomas <Rijo-john.Thomas@amd.com>
633960accSRijo Thomas  * Author: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>
733960accSRijo Thomas  *
84a5eed17SRijo Thomas  * Copyright (C) 2019,2021 Advanced Micro Devices, Inc.
933960accSRijo Thomas  */
1033960accSRijo Thomas 
11*1c5c1dafSMario Limonciello #include <linux/bitfield.h>
1233960accSRijo Thomas #include <linux/types.h>
1333960accSRijo Thomas #include <linux/mutex.h>
1433960accSRijo Thomas #include <linux/delay.h>
1533960accSRijo Thomas #include <linux/slab.h>
1633960accSRijo Thomas #include <linux/gfp.h>
17ae7d45fbSMario Limonciello #include <linux/psp.h>
18632b0b53SRijo Thomas #include <linux/psp-tee.h>
1933960accSRijo Thomas 
2033960accSRijo Thomas #include "psp-dev.h"
2133960accSRijo Thomas #include "tee-dev.h"
2233960accSRijo Thomas 
2333960accSRijo Thomas static bool psp_dead;
2433960accSRijo Thomas 
tee_alloc_ring(struct psp_tee_device * tee,int ring_size)2533960accSRijo Thomas static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
2633960accSRijo Thomas {
2733960accSRijo Thomas 	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
2833960accSRijo Thomas 	void *start_addr;
2933960accSRijo Thomas 
3033960accSRijo Thomas 	if (!ring_size)
3133960accSRijo Thomas 		return -EINVAL;
3233960accSRijo Thomas 
3333960accSRijo Thomas 	/* We need actual physical address instead of DMA address, since
3433960accSRijo Thomas 	 * Trusted OS running on AMD Secure Processor will map this region
3533960accSRijo Thomas 	 */
3633960accSRijo Thomas 	start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));
3733960accSRijo Thomas 	if (!start_addr)
3833960accSRijo Thomas 		return -ENOMEM;
3933960accSRijo Thomas 
4000aa6e65SRijo Thomas 	memset(start_addr, 0x0, ring_size);
4133960accSRijo Thomas 	rb_mgr->ring_start = start_addr;
4233960accSRijo Thomas 	rb_mgr->ring_size = ring_size;
4333960accSRijo Thomas 	rb_mgr->ring_pa = __psp_pa(start_addr);
44632b0b53SRijo Thomas 	mutex_init(&rb_mgr->mutex);
4533960accSRijo Thomas 
4633960accSRijo Thomas 	return 0;
4733960accSRijo Thomas }
4833960accSRijo Thomas 
tee_free_ring(struct psp_tee_device * tee)4933960accSRijo Thomas static void tee_free_ring(struct psp_tee_device *tee)
5033960accSRijo Thomas {
5133960accSRijo Thomas 	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
5233960accSRijo Thomas 
5333960accSRijo Thomas 	if (!rb_mgr->ring_start)
5433960accSRijo Thomas 		return;
5533960accSRijo Thomas 
5633960accSRijo Thomas 	free_pages((unsigned long)rb_mgr->ring_start,
5733960accSRijo Thomas 		   get_order(rb_mgr->ring_size));
5833960accSRijo Thomas 
5933960accSRijo Thomas 	rb_mgr->ring_start = NULL;
6033960accSRijo Thomas 	rb_mgr->ring_size = 0;
6133960accSRijo Thomas 	rb_mgr->ring_pa = 0;
62632b0b53SRijo Thomas 	mutex_destroy(&rb_mgr->mutex);
6333960accSRijo Thomas }
6433960accSRijo Thomas 
tee_wait_cmd_poll(struct psp_tee_device * tee,unsigned int timeout,unsigned int * reg)6533960accSRijo Thomas static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
6633960accSRijo Thomas 			     unsigned int *reg)
6733960accSRijo Thomas {
6833960accSRijo Thomas 	/* ~10ms sleep per loop => nloop = timeout * 100 */
6933960accSRijo Thomas 	int nloop = timeout * 100;
7033960accSRijo Thomas 
7133960accSRijo Thomas 	while (--nloop) {
7233960accSRijo Thomas 		*reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
73*1c5c1dafSMario Limonciello 		if (FIELD_GET(PSP_CMDRESP_RESP, *reg))
7433960accSRijo Thomas 			return 0;
7533960accSRijo Thomas 
7633960accSRijo Thomas 		usleep_range(10000, 10100);
7733960accSRijo Thomas 	}
7833960accSRijo Thomas 
7933960accSRijo Thomas 	dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
8033960accSRijo Thomas 	psp_dead = true;
8133960accSRijo Thomas 
8233960accSRijo Thomas 	return -ETIMEDOUT;
8333960accSRijo Thomas }
8433960accSRijo Thomas 
8533960accSRijo Thomas static
tee_alloc_cmd_buffer(struct psp_tee_device * tee)8633960accSRijo Thomas struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
8733960accSRijo Thomas {
8833960accSRijo Thomas 	struct tee_init_ring_cmd *cmd;
8933960accSRijo Thomas 
9033960accSRijo Thomas 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
9133960accSRijo Thomas 	if (!cmd)
9233960accSRijo Thomas 		return NULL;
9333960accSRijo Thomas 
9433960accSRijo Thomas 	cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);
9533960accSRijo Thomas 	cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);
9633960accSRijo Thomas 	cmd->size = tee->rb_mgr.ring_size;
9733960accSRijo Thomas 
9833960accSRijo Thomas 	dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",
9933960accSRijo Thomas 		cmd->hi_addr, cmd->low_addr, cmd->size);
10033960accSRijo Thomas 
10133960accSRijo Thomas 	return cmd;
10233960accSRijo Thomas }
10333960accSRijo Thomas 
tee_free_cmd_buffer(struct tee_init_ring_cmd * cmd)10433960accSRijo Thomas static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)
10533960accSRijo Thomas {
10633960accSRijo Thomas 	kfree(cmd);
10733960accSRijo Thomas }
10833960accSRijo Thomas 
tee_init_ring(struct psp_tee_device * tee)10933960accSRijo Thomas static int tee_init_ring(struct psp_tee_device *tee)
11033960accSRijo Thomas {
11133960accSRijo Thomas 	int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
11233960accSRijo Thomas 	struct tee_init_ring_cmd *cmd;
11333960accSRijo Thomas 	phys_addr_t cmd_buffer;
11433960accSRijo Thomas 	unsigned int reg;
11533960accSRijo Thomas 	int ret;
11633960accSRijo Thomas 
11733960accSRijo Thomas 	BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);
11833960accSRijo Thomas 
11933960accSRijo Thomas 	ret = tee_alloc_ring(tee, ring_size);
12033960accSRijo Thomas 	if (ret) {
12133960accSRijo Thomas 		dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);
12233960accSRijo Thomas 		return ret;
12333960accSRijo Thomas 	}
12433960accSRijo Thomas 
12533960accSRijo Thomas 	tee->rb_mgr.wptr = 0;
12633960accSRijo Thomas 
12733960accSRijo Thomas 	cmd = tee_alloc_cmd_buffer(tee);
12833960accSRijo Thomas 	if (!cmd) {
12933960accSRijo Thomas 		tee_free_ring(tee);
13033960accSRijo Thomas 		return -ENOMEM;
13133960accSRijo Thomas 	}
13233960accSRijo Thomas 
13333960accSRijo Thomas 	cmd_buffer = __psp_pa((void *)cmd);
13433960accSRijo Thomas 
13533960accSRijo Thomas 	/* Send command buffer details to Trusted OS by writing to
13633960accSRijo Thomas 	 * CPU-PSP message registers
13733960accSRijo Thomas 	 */
13833960accSRijo Thomas 
13933960accSRijo Thomas 	iowrite32(lower_32_bits(cmd_buffer),
14033960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
14133960accSRijo Thomas 	iowrite32(upper_32_bits(cmd_buffer),
14233960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
14333960accSRijo Thomas 	iowrite32(TEE_RING_INIT_CMD,
14433960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdresp_reg);
14533960accSRijo Thomas 
14633960accSRijo Thomas 	ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
14733960accSRijo Thomas 	if (ret) {
14833960accSRijo Thomas 		dev_err(tee->dev, "tee: ring init command timed out\n");
14933960accSRijo Thomas 		tee_free_ring(tee);
15033960accSRijo Thomas 		goto free_buf;
15133960accSRijo Thomas 	}
15233960accSRijo Thomas 
153*1c5c1dafSMario Limonciello 	if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
154*1c5c1dafSMario Limonciello 		dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
155*1c5c1dafSMario Limonciello 			FIELD_GET(PSP_CMDRESP_STS, reg));
15633960accSRijo Thomas 		tee_free_ring(tee);
15733960accSRijo Thomas 		ret = -EIO;
15833960accSRijo Thomas 	}
15933960accSRijo Thomas 
16033960accSRijo Thomas free_buf:
16133960accSRijo Thomas 	tee_free_cmd_buffer(cmd);
16233960accSRijo Thomas 
16333960accSRijo Thomas 	return ret;
16433960accSRijo Thomas }
16533960accSRijo Thomas 
tee_destroy_ring(struct psp_tee_device * tee)16633960accSRijo Thomas static void tee_destroy_ring(struct psp_tee_device *tee)
16733960accSRijo Thomas {
16833960accSRijo Thomas 	unsigned int reg;
16933960accSRijo Thomas 	int ret;
17033960accSRijo Thomas 
17133960accSRijo Thomas 	if (!tee->rb_mgr.ring_start)
17233960accSRijo Thomas 		return;
17333960accSRijo Thomas 
17433960accSRijo Thomas 	if (psp_dead)
17533960accSRijo Thomas 		goto free_ring;
17633960accSRijo Thomas 
17733960accSRijo Thomas 	iowrite32(TEE_RING_DESTROY_CMD,
17833960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdresp_reg);
17933960accSRijo Thomas 
18033960accSRijo Thomas 	ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
18133960accSRijo Thomas 	if (ret) {
18233960accSRijo Thomas 		dev_err(tee->dev, "tee: ring destroy command timed out\n");
183*1c5c1dafSMario Limonciello 	} else if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
184*1c5c1dafSMario Limonciello 		dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n",
185*1c5c1dafSMario Limonciello 			FIELD_GET(PSP_CMDRESP_STS, reg));
18633960accSRijo Thomas 	}
18733960accSRijo Thomas 
18833960accSRijo Thomas free_ring:
18933960accSRijo Thomas 	tee_free_ring(tee);
19033960accSRijo Thomas }
19133960accSRijo Thomas 
tee_dev_init(struct psp_device * psp)19233960accSRijo Thomas int tee_dev_init(struct psp_device *psp)
19333960accSRijo Thomas {
19433960accSRijo Thomas 	struct device *dev = psp->dev;
19533960accSRijo Thomas 	struct psp_tee_device *tee;
19633960accSRijo Thomas 	int ret;
19733960accSRijo Thomas 
19833960accSRijo Thomas 	ret = -ENOMEM;
19933960accSRijo Thomas 	tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);
20033960accSRijo Thomas 	if (!tee)
20133960accSRijo Thomas 		goto e_err;
20233960accSRijo Thomas 
20333960accSRijo Thomas 	psp->tee_data = tee;
20433960accSRijo Thomas 
20533960accSRijo Thomas 	tee->dev = dev;
20633960accSRijo Thomas 	tee->psp = psp;
20733960accSRijo Thomas 
20833960accSRijo Thomas 	tee->io_regs = psp->io_regs;
20933960accSRijo Thomas 
21033960accSRijo Thomas 	tee->vdata = (struct tee_vdata *)psp->vdata->tee;
21133960accSRijo Thomas 	if (!tee->vdata) {
21233960accSRijo Thomas 		ret = -ENODEV;
21333960accSRijo Thomas 		dev_err(dev, "tee: missing driver data\n");
21433960accSRijo Thomas 		goto e_err;
21533960accSRijo Thomas 	}
21633960accSRijo Thomas 
21733960accSRijo Thomas 	ret = tee_init_ring(tee);
21833960accSRijo Thomas 	if (ret) {
21933960accSRijo Thomas 		dev_err(dev, "tee: failed to init ring buffer\n");
22033960accSRijo Thomas 		goto e_err;
22133960accSRijo Thomas 	}
22233960accSRijo Thomas 
22333960accSRijo Thomas 	dev_notice(dev, "tee enabled\n");
22433960accSRijo Thomas 
22533960accSRijo Thomas 	return 0;
22633960accSRijo Thomas 
22733960accSRijo Thomas e_err:
22833960accSRijo Thomas 	psp->tee_data = NULL;
22933960accSRijo Thomas 
23033960accSRijo Thomas 	dev_notice(dev, "tee initialization failed\n");
23133960accSRijo Thomas 
23233960accSRijo Thomas 	return ret;
23333960accSRijo Thomas }
23433960accSRijo Thomas 
tee_dev_destroy(struct psp_device * psp)23533960accSRijo Thomas void tee_dev_destroy(struct psp_device *psp)
23633960accSRijo Thomas {
23733960accSRijo Thomas 	struct psp_tee_device *tee = psp->tee_data;
23833960accSRijo Thomas 
23933960accSRijo Thomas 	if (!tee)
24033960accSRijo Thomas 		return;
24133960accSRijo Thomas 
24233960accSRijo Thomas 	tee_destroy_ring(tee);
24333960accSRijo Thomas }
244632b0b53SRijo Thomas 
tee_submit_cmd(struct psp_tee_device * tee,enum tee_cmd_id cmd_id,void * buf,size_t len,struct tee_ring_cmd ** resp)245632b0b53SRijo Thomas static int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id,
246632b0b53SRijo Thomas 			  void *buf, size_t len, struct tee_ring_cmd **resp)
247632b0b53SRijo Thomas {
248632b0b53SRijo Thomas 	struct tee_ring_cmd *cmd;
249632b0b53SRijo Thomas 	int nloop = 1000, ret = 0;
25000aa6e65SRijo Thomas 	u32 rptr;
251632b0b53SRijo Thomas 
252632b0b53SRijo Thomas 	*resp = NULL;
253632b0b53SRijo Thomas 
254632b0b53SRijo Thomas 	mutex_lock(&tee->rb_mgr.mutex);
255632b0b53SRijo Thomas 
25600aa6e65SRijo Thomas 	/* Loop until empty entry found in ring buffer */
257632b0b53SRijo Thomas 	do {
25800aa6e65SRijo Thomas 		/* Get pointer to ring buffer command entry */
25900aa6e65SRijo Thomas 		cmd = (struct tee_ring_cmd *)
26000aa6e65SRijo Thomas 			(tee->rb_mgr.ring_start + tee->rb_mgr.wptr);
26100aa6e65SRijo Thomas 
262632b0b53SRijo Thomas 		rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg);
263632b0b53SRijo Thomas 
26400aa6e65SRijo Thomas 		/* Check if ring buffer is full or command entry is waiting
26500aa6e65SRijo Thomas 		 * for response from TEE
26600aa6e65SRijo Thomas 		 */
26700aa6e65SRijo Thomas 		if (!(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
26800aa6e65SRijo Thomas 		      cmd->flag == CMD_WAITING_FOR_RESPONSE))
269632b0b53SRijo Thomas 			break;
270632b0b53SRijo Thomas 
27100aa6e65SRijo Thomas 		dev_dbg(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n",
27200aa6e65SRijo Thomas 			rptr, tee->rb_mgr.wptr);
273632b0b53SRijo Thomas 
27400aa6e65SRijo Thomas 		/* Wait if ring buffer is full or TEE is processing data */
275632b0b53SRijo Thomas 		mutex_unlock(&tee->rb_mgr.mutex);
276632b0b53SRijo Thomas 		schedule_timeout_interruptible(msecs_to_jiffies(10));
277632b0b53SRijo Thomas 		mutex_lock(&tee->rb_mgr.mutex);
278632b0b53SRijo Thomas 
279632b0b53SRijo Thomas 	} while (--nloop);
280632b0b53SRijo Thomas 
28100aa6e65SRijo Thomas 	if (!nloop &&
28200aa6e65SRijo Thomas 	    (tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
28300aa6e65SRijo Thomas 	     cmd->flag == CMD_WAITING_FOR_RESPONSE)) {
28400aa6e65SRijo Thomas 		dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u response flag %u\n",
28500aa6e65SRijo Thomas 			rptr, tee->rb_mgr.wptr, cmd->flag);
286632b0b53SRijo Thomas 		ret = -EBUSY;
287632b0b53SRijo Thomas 		goto unlock;
288632b0b53SRijo Thomas 	}
289632b0b53SRijo Thomas 
29000aa6e65SRijo Thomas 	/* Do not submit command if PSP got disabled while processing any
29100aa6e65SRijo Thomas 	 * command in another thread
29200aa6e65SRijo Thomas 	 */
29300aa6e65SRijo Thomas 	if (psp_dead) {
29400aa6e65SRijo Thomas 		ret = -EBUSY;
29500aa6e65SRijo Thomas 		goto unlock;
29600aa6e65SRijo Thomas 	}
297632b0b53SRijo Thomas 
298632b0b53SRijo Thomas 	/* Write command data into ring buffer */
299632b0b53SRijo Thomas 	cmd->cmd_id = cmd_id;
300632b0b53SRijo Thomas 	cmd->cmd_state = TEE_CMD_STATE_INIT;
301632b0b53SRijo Thomas 	memset(&cmd->buf[0], 0, sizeof(cmd->buf));
302632b0b53SRijo Thomas 	memcpy(&cmd->buf[0], buf, len);
303632b0b53SRijo Thomas 
30400aa6e65SRijo Thomas 	/* Indicate driver is waiting for response */
30500aa6e65SRijo Thomas 	cmd->flag = CMD_WAITING_FOR_RESPONSE;
30600aa6e65SRijo Thomas 
307632b0b53SRijo Thomas 	/* Update local copy of write pointer */
308632b0b53SRijo Thomas 	tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd);
309632b0b53SRijo Thomas 	if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size)
310632b0b53SRijo Thomas 		tee->rb_mgr.wptr = 0;
311632b0b53SRijo Thomas 
312632b0b53SRijo Thomas 	/* Trigger interrupt to Trusted OS */
313632b0b53SRijo Thomas 	iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg);
314632b0b53SRijo Thomas 
315632b0b53SRijo Thomas 	/* The response is provided by Trusted OS in same
316632b0b53SRijo Thomas 	 * location as submitted data entry within ring buffer.
317632b0b53SRijo Thomas 	 */
318632b0b53SRijo Thomas 	*resp = cmd;
319632b0b53SRijo Thomas 
320632b0b53SRijo Thomas unlock:
321632b0b53SRijo Thomas 	mutex_unlock(&tee->rb_mgr.mutex);
322632b0b53SRijo Thomas 
323632b0b53SRijo Thomas 	return ret;
324632b0b53SRijo Thomas }
325632b0b53SRijo Thomas 
tee_wait_cmd_completion(struct psp_tee_device * tee,struct tee_ring_cmd * resp,unsigned int timeout)326632b0b53SRijo Thomas static int tee_wait_cmd_completion(struct psp_tee_device *tee,
327632b0b53SRijo Thomas 				   struct tee_ring_cmd *resp,
328632b0b53SRijo Thomas 				   unsigned int timeout)
329632b0b53SRijo Thomas {
3304a5eed17SRijo Thomas 	/* ~1ms sleep per loop => nloop = timeout * 1000 */
3314a5eed17SRijo Thomas 	int nloop = timeout * 1000;
332632b0b53SRijo Thomas 
333632b0b53SRijo Thomas 	while (--nloop) {
334632b0b53SRijo Thomas 		if (resp->cmd_state == TEE_CMD_STATE_COMPLETED)
335632b0b53SRijo Thomas 			return 0;
336632b0b53SRijo Thomas 
3374a5eed17SRijo Thomas 		usleep_range(1000, 1100);
338632b0b53SRijo Thomas 	}
339632b0b53SRijo Thomas 
340632b0b53SRijo Thomas 	dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n",
341632b0b53SRijo Thomas 		resp->cmd_id);
342632b0b53SRijo Thomas 
343632b0b53SRijo Thomas 	psp_dead = true;
344632b0b53SRijo Thomas 
345632b0b53SRijo Thomas 	return -ETIMEDOUT;
346632b0b53SRijo Thomas }
347632b0b53SRijo Thomas 
psp_tee_process_cmd(enum tee_cmd_id cmd_id,void * buf,size_t len,u32 * status)348632b0b53SRijo Thomas int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,
349632b0b53SRijo Thomas 			u32 *status)
350632b0b53SRijo Thomas {
351632b0b53SRijo Thomas 	struct psp_device *psp = psp_get_master_device();
352632b0b53SRijo Thomas 	struct psp_tee_device *tee;
353632b0b53SRijo Thomas 	struct tee_ring_cmd *resp;
354632b0b53SRijo Thomas 	int ret;
355632b0b53SRijo Thomas 
356632b0b53SRijo Thomas 	if (!buf || !status || !len || len > sizeof(resp->buf))
357632b0b53SRijo Thomas 		return -EINVAL;
358632b0b53SRijo Thomas 
359632b0b53SRijo Thomas 	*status = 0;
360632b0b53SRijo Thomas 
361632b0b53SRijo Thomas 	if (!psp || !psp->tee_data)
362632b0b53SRijo Thomas 		return -ENODEV;
363632b0b53SRijo Thomas 
364632b0b53SRijo Thomas 	if (psp_dead)
365632b0b53SRijo Thomas 		return -EBUSY;
366632b0b53SRijo Thomas 
367632b0b53SRijo Thomas 	tee = psp->tee_data;
368632b0b53SRijo Thomas 
369632b0b53SRijo Thomas 	ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp);
370632b0b53SRijo Thomas 	if (ret)
371632b0b53SRijo Thomas 		return ret;
372632b0b53SRijo Thomas 
373632b0b53SRijo Thomas 	ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT);
37400aa6e65SRijo Thomas 	if (ret) {
37500aa6e65SRijo Thomas 		resp->flag = CMD_RESPONSE_TIMEDOUT;
376632b0b53SRijo Thomas 		return ret;
37700aa6e65SRijo Thomas 	}
378632b0b53SRijo Thomas 
379632b0b53SRijo Thomas 	memcpy(buf, &resp->buf[0], len);
380632b0b53SRijo Thomas 	*status = resp->status;
381632b0b53SRijo Thomas 
38200aa6e65SRijo Thomas 	resp->flag = CMD_RESPONSE_COPIED;
38300aa6e65SRijo Thomas 
384632b0b53SRijo Thomas 	return 0;
385632b0b53SRijo Thomas }
386632b0b53SRijo Thomas EXPORT_SYMBOL(psp_tee_process_cmd);
387bade7e1fSRijo Thomas 
psp_check_tee_status(void)388bade7e1fSRijo Thomas int psp_check_tee_status(void)
389bade7e1fSRijo Thomas {
390bade7e1fSRijo Thomas 	struct psp_device *psp = psp_get_master_device();
391bade7e1fSRijo Thomas 
392bade7e1fSRijo Thomas 	if (!psp || !psp->tee_data)
393bade7e1fSRijo Thomas 		return -ENODEV;
394bade7e1fSRijo Thomas 
395bade7e1fSRijo Thomas 	return 0;
396bade7e1fSRijo Thomas }
397bade7e1fSRijo Thomas EXPORT_SYMBOL(psp_check_tee_status);
398