1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2020-2022 NXP
4  */
5 #include <drivers/imx_mu.h>
6 #include <initcall.h>
7 #include <io.h>
8 #include <kernel/delay.h>
9 #include <mm/core_memprot.h>
10 
11 #include "imx_mu_platform.h"
12 
13 #define MU_ATR(n)     (0x0 + (n) * (4))
14 #define MU_ARR(n)     (0x10 + (n) * (4))
15 #define MU_ASR_OFFSET 0x20
16 #define MU_ACR_OFFSET 0x24
17 
18 #define MU_SR_RF(n) SHIFT_U32(1, 27 - (n))
19 #define MU_SR_TE(n) SHIFT_U32(1, 23 - (n))
20 
21 #define MU_CR_GIE_MASK GENMASK_32(31, 28)
22 #define MU_CR_RIE_MASK GENMASK_32(27, 24)
23 #define MU_CR_TIE_MASK GENMASK_32(23, 20)
24 #define MU_CR_GIR_MASK GENMASK_32(19, 16)
25 #define MU_CR_F_MASK   GENMASK_32(2, 0)
26 
27 #define MU_MAX_CHANNEL 4
28 
mu_wait_for(vaddr_t addr,uint32_t mask)29 static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask)
30 {
31 	uint64_t timeout = timeout_init_us(1000);
32 
33 	while (!(io_read32(addr) & mask))
34 		if (timeout_elapsed(timeout))
35 			break;
36 
37 	if (io_read32(addr) & mask)
38 		return TEE_SUCCESS;
39 	else
40 		return TEE_ERROR_BUSY;
41 
42 	return TEE_SUCCESS;
43 }
44 
imx_mu_plat_get_rx_channel(void)45 unsigned int imx_mu_plat_get_rx_channel(void)
46 {
47 	return MU_MAX_CHANNEL;
48 }
49 
imx_mu_plat_get_tx_channel(void)50 unsigned int imx_mu_plat_get_tx_channel(void)
51 {
52 	return MU_MAX_CHANNEL;
53 }
54 
imx_mu_plat_init(vaddr_t base)55 void imx_mu_plat_init(vaddr_t base)
56 {
57 	io_clrbits32(base + MU_ACR_OFFSET,
58 		     MU_CR_GIE_MASK | MU_CR_RIE_MASK | MU_CR_TIE_MASK |
59 		     MU_CR_GIR_MASK | MU_CR_F_MASK);
60 }
61 
imx_mu_plat_send(vaddr_t base,unsigned int index,uint32_t msg)62 TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg)
63 {
64 	assert(index < MU_MAX_CHANNEL);
65 
66 	/* Wait TX register to be empty */
67 	if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_TE(index)))
68 		return TEE_ERROR_BUSY;
69 
70 	/* Write message in TX register */
71 	io_write32(base + MU_ATR(index), msg);
72 
73 	return TEE_SUCCESS;
74 }
75 
imx_mu_plat_receive(vaddr_t base,unsigned int index,uint32_t * msg)76 TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg)
77 {
78 	assert(index < MU_MAX_CHANNEL);
79 
80 	/* Wait RX register to be full */
81 	if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_RF(index)))
82 		return TEE_ERROR_NO_DATA;
83 
84 	/* Read message in RX register */
85 	*msg = io_read32(base + MU_ARR(index));
86 
87 	return TEE_SUCCESS;
88 }
89