xref: /optee_os/core/drivers/imx_csu.c (revision 731185b11620a6de1f824278ab3c166c7853ef66)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2017-2023 NXP
4  *
5  */
6 
7 #include <config.h>
8 #include <imx.h>
9 #include <initcall.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <kernel/pm.h>
13 #include <mm/core_memprot.h>
14 
15 struct csu_setting {
16 	int csu_index;
17 	uint32_t value;
18 };
19 
20 const struct csu_setting csu_setting_imx6[] = {
21 	{13, 0xFF0033},		/* Protect ROMCP */
22 	{16, 0x330033},		/* Protect TZASC */
23 	{26, 0xFF0033},		/* Protect OCRAM */
24 	{(-1), 0},
25 };
26 
27 struct csu_sa_setting {
28 	uint32_t access_value;
29 	uint32_t lock_value;
30 };
31 
32 struct csu_config {
33 	const struct csu_sa_setting * const sa;
34 	const struct csu_setting * const csl;
35 };
36 
37 const struct csu_setting csu_setting_imx6ul[] = {
38 	{13, 0xFF0033},		/* Protect ROMCP */
39 	{16, 0x3300FF},		/* Protect TZASC */
40 	{39, 0x3300FF},		/* Protect OCRAM */
41 	{(-1), 0},
42 };
43 
44 const struct csu_setting csu_setting_imx6ull[] = {
45 	{ 13, 0xFF0033 },	/* Protect ROMCP */
46 	{ 16, 0x3300FF },	/* Protect TZASC */
47 	{ 34, 0xFF0033 },	/* Protect DCP */
48 	{ 39, 0x3300FF },	/* Protect OCRAM */
49 	{ (-1), 0 },
50 };
51 
52 const struct csu_setting csu_setting_imx6sl[] = {
53 	{ 13, 0x3F0033 },	/* Protect DCP/ROMCP */
54 	{ 16, 0xFF0033 },	/* Protect TZASC */
55 	{ 26, 0xFF0033 },	/* Protect OCRAM */
56 	{ (-1), 0 },
57 };
58 
59 const struct csu_setting csu_setting_imx6sx[] = {
60 	{13, 0xFF0033},		/* Protect ROMCP */
61 	{15, 0xFF0033},		/* Protect RDC   */
62 	{16, 0x3300FF},		/* Protect TZASC */
63 	{34, 0x3300FF},		/* Protect OCRAM */
64 	{(-1), 0},
65 };
66 
67 const struct csu_setting csu_setting_imx7ds[] = {
68 	{14, 0x3300FF},		/* Protect RDC     */
69 	{15, 0xFF0033},		/* Protect CSU     */
70 	{28, 0xFF0033},		/* Protect TZASC   */
71 	{59, 0x3300FF},		/* Protect OCRAM_S */
72 	{(-1), 0},
73 };
74 
75 /* Set all masters to non-secure except the Cortex-A7 */
76 const struct csu_sa_setting csu_sa_imx6ul = { 0x10554550, 0x20aa8aa2 };
77 const struct csu_sa_setting csu_sa_imx7ds = { 0x15554554, 0x2aaa8aaa };
78 
79 const struct csu_config csu_imx6 = { NULL, csu_setting_imx6 };
80 const struct csu_config csu_imx6ul = { &csu_sa_imx6ul, csu_setting_imx6ul };
81 const struct csu_config csu_imx6ull = { NULL, csu_setting_imx6ull };
82 const struct csu_config csu_imx6sl = { NULL, csu_setting_imx6sl };
83 const struct csu_config csu_imx6sx = { NULL, csu_setting_imx6sx };
84 const struct csu_config csu_imx7ds = { &csu_sa_imx7ds, csu_setting_imx7ds };
85 
86 static void rngb_configure(vaddr_t csu_base)
87 {
88 	int csu_index = 0;
89 
90 	if (soc_is_imx6sl() || soc_is_imx6sll())
91 		csu_index = 16;
92 	else if (soc_is_imx6ull())
93 		csu_index = 34;
94 	else
95 		return;
96 
97 	/* Protect RNGB */
98 	io_mask32(csu_base + csu_index * 4, 0x330000, 0xFF0000);
99 }
100 
101 static TEE_Result csu_configure(void)
102 {
103 	vaddr_t csu_base;
104 	vaddr_t offset;
105 	const struct csu_config *csu_config = NULL;
106 	const struct csu_setting *csu_setting = NULL;
107 
108 	csu_base = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, 1);
109 	if (!csu_base)
110 		panic();
111 
112 	if (soc_is_imx6sx())
113 		csu_config = &csu_imx6sx;
114 	else if (soc_is_imx6ul())
115 		csu_config = &csu_imx6ul;
116 	else if (soc_is_imx6ull())
117 		csu_config = &csu_imx6ull;
118 	else if (soc_is_imx6sll() || soc_is_imx6sl())
119 		csu_config = &csu_imx6sl;
120 	else if (soc_is_imx6())
121 		csu_config = &csu_imx6;
122 	else if (soc_is_imx7ds())
123 		csu_config = &csu_imx7ds;
124 	else
125 		return TEE_SUCCESS;
126 
127 	/* first grant all peripherals */
128 	for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4)
129 		io_write32(csu_base + offset, CSU_ACCESS_ALL);
130 
131 	csu_setting = csu_config->csl;
132 
133 	while (csu_setting->csu_index >= 0) {
134 		io_write32(csu_base + (csu_setting->csu_index * 4),
135 				csu_setting->value);
136 
137 		csu_setting++;
138 	}
139 
140 	if (IS_ENABLED(CFG_IMX_RNGB))
141 		rngb_configure(csu_base);
142 
143 	/* lock the settings */
144 	for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) {
145 		io_write32(csu_base + offset,
146 			io_read32(csu_base + offset) | CSU_SETTING_LOCK);
147 	}
148 
149 	if (csu_config->sa) {
150 		io_write32(csu_base + CSU_SA, csu_config->sa->access_value);
151 		io_setbits32(csu_base + CSU_SA, csu_config->sa->lock_value);
152 	}
153 
154 	return TEE_SUCCESS;
155 }
156 
157 static TEE_Result
158 pm_enter_resume(enum pm_op op, uint32_t pm_hint __unused,
159 		const struct pm_callback_handle *pm_handle __unused)
160 {
161 	if (op == PM_OP_RESUME)
162 		csu_configure();
163 
164 	return TEE_SUCCESS;
165 }
166 
167 static TEE_Result csu_init(void)
168 {
169 	csu_configure();
170 	register_pm_driver_cb(pm_enter_resume, NULL, "imx-csu");
171 
172 	return TEE_SUCCESS;
173 }
174 
175 driver_init(csu_init);
176