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