1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2022-2023 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_PAR 0x004
14 #define MU_TCR 0x120
15 #define MU_TSR 0x124
16 #define MU_RCR 0x128
17 #define MU_RSR 0x12C
18 #define MU_TR(n) (0x200 + 0x4 * (n))
19 #define MU_RR(n) (0x280 + 0x4 * (n))
20 #define MU_TSR_TE(n) BIT32(n)
21 #define MU_RSR_RF(n) BIT32(n)
22
23 #define RR_NUM_MASK GENMASK_32(15, 8)
24 #define RR_NUM_SHIFT 8
25 #define TR_NUM_MASK GENMASK_32(7, 0)
26
mu_wait_for(vaddr_t addr,uint32_t mask)27 static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask)
28 {
29 uint64_t timeout = timeout_init_us(1000);
30
31 while (!(io_read32(addr) & mask))
32 if (timeout_elapsed(timeout))
33 break;
34
35 if (io_read32(addr) & mask)
36 return TEE_SUCCESS;
37 else
38 return TEE_ERROR_BUSY;
39
40 return TEE_SUCCESS;
41 }
42
imx_mu_plat_get_rx_channel(vaddr_t base)43 unsigned int imx_mu_plat_get_rx_channel(vaddr_t base)
44 {
45 return (io_read32(base + MU_PAR) & RR_NUM_MASK) >> RR_NUM_SHIFT;
46 }
47
imx_mu_plat_get_tx_channel(vaddr_t base)48 unsigned int imx_mu_plat_get_tx_channel(vaddr_t base)
49 {
50 return io_read32(base + MU_PAR) & TR_NUM_MASK;
51 }
52
imx_mu_plat_send(vaddr_t base,unsigned int index,uint32_t msg)53 TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg)
54 {
55 assert(index < imx_mu_plat_get_tx_channel(base));
56
57 /* Wait TX register to be empty */
58 if (mu_wait_for(base + MU_TSR, MU_TSR_TE(index)))
59 return TEE_ERROR_BUSY;
60
61 io_write32(base + MU_TR(index), msg);
62
63 return TEE_SUCCESS;
64 }
65
imx_mu_plat_receive(vaddr_t base,unsigned int index,uint32_t * msg)66 TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg)
67 {
68 assert(index < imx_mu_plat_get_rx_channel(base));
69
70 /* Wait RX register to be full */
71 if (mu_wait_for(base + MU_RSR, MU_RSR_RF(index)))
72 return TEE_ERROR_NO_DATA;
73
74 *msg = io_read32(base + MU_RR(index));
75
76 return TEE_SUCCESS;
77 }
78
imx_mu_plat_init(vaddr_t base)79 void imx_mu_plat_init(vaddr_t base)
80 {
81 /* Reset status registers */
82 io_write32(base + MU_TCR, 0x0);
83 io_write32(base + MU_RCR, 0x0);
84 }
85