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-A cores */
76 const struct csu_sa_setting csu_sa_imx6 = { 0x15554554, 0x2aaa8aaa };
77 const struct csu_sa_setting csu_sa_imx6ul = { 0x10554550, 0x20aa8aa2 };
78 const struct csu_sa_setting csu_sa_imx7ds = { 0x15554554, 0x2aaa8aaa };
79 
80 const struct csu_config csu_imx6 = { &csu_sa_imx6, csu_setting_imx6 };
81 const struct csu_config csu_imx6ul = { &csu_sa_imx6ul, csu_setting_imx6ul };
82 const struct csu_config csu_imx6ull = { NULL, csu_setting_imx6ull };
83 const struct csu_config csu_imx6sl = { NULL, csu_setting_imx6sl };
84 const struct csu_config csu_imx6sx = { NULL, csu_setting_imx6sx };
85 const struct csu_config csu_imx7ds = { &csu_sa_imx7ds, csu_setting_imx7ds };
86 
rngb_configure(vaddr_t csu_base)87 static void rngb_configure(vaddr_t csu_base)
88 {
89 	int csu_index = 0;
90 
91 	if (soc_is_imx6sl() || soc_is_imx6sll())
92 		csu_index = 16;
93 	else if (soc_is_imx6ull())
94 		csu_index = 34;
95 	else
96 		return;
97 
98 	/* Protect RNGB */
99 	io_mask32(csu_base + csu_index * 4, 0x330000, 0xFF0000);
100 }
101 
csu_configure(void)102 static TEE_Result csu_configure(void)
103 {
104 	vaddr_t csu_base;
105 	vaddr_t offset;
106 	const struct csu_config *csu_config = NULL;
107 	const struct csu_setting *csu_setting = NULL;
108 
109 	csu_base = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, 1);
110 	if (!csu_base)
111 		panic();
112 
113 	if (soc_is_imx6sx())
114 		csu_config = &csu_imx6sx;
115 	else if (soc_is_imx6ul())
116 		csu_config = &csu_imx6ul;
117 	else if (soc_is_imx6ull())
118 		csu_config = &csu_imx6ull;
119 	else if (soc_is_imx6sll() || soc_is_imx6sl())
120 		csu_config = &csu_imx6sl;
121 	else if (soc_is_imx6())
122 		csu_config = &csu_imx6;
123 	else if (soc_is_imx7ds())
124 		csu_config = &csu_imx7ds;
125 	else
126 		return TEE_SUCCESS;
127 
128 	/* first grant all peripherals */
129 	for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4)
130 		io_write32(csu_base + offset, CSU_ACCESS_ALL);
131 
132 	csu_setting = csu_config->csl;
133 
134 	while (csu_setting->csu_index >= 0) {
135 		io_write32(csu_base + (csu_setting->csu_index * 4),
136 				csu_setting->value);
137 
138 		csu_setting++;
139 	}
140 
141 	if (IS_ENABLED(CFG_IMX_RNGB))
142 		rngb_configure(csu_base);
143 
144 	/* lock the settings */
145 	for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) {
146 		io_write32(csu_base + offset,
147 			io_read32(csu_base + offset) | CSU_SETTING_LOCK);
148 	}
149 
150 	if (csu_config->sa) {
151 		io_write32(csu_base + CSU_SA, csu_config->sa->access_value);
152 		io_setbits32(csu_base + CSU_SA, csu_config->sa->lock_value);
153 	}
154 
155 	return TEE_SUCCESS;
156 }
157 
158 static TEE_Result
pm_enter_resume(enum pm_op op,uint32_t pm_hint __unused,const struct pm_callback_handle * pm_handle __unused)159 pm_enter_resume(enum pm_op op, uint32_t pm_hint __unused,
160 		const struct pm_callback_handle *pm_handle __unused)
161 {
162 	if (op == PM_OP_RESUME)
163 		csu_configure();
164 
165 	return TEE_SUCCESS;
166 }
167 
csu_init(void)168 static TEE_Result csu_init(void)
169 {
170 	csu_configure();
171 	register_pm_driver_cb(pm_enter_resume, NULL, "imx-csu");
172 
173 	return TEE_SUCCESS;
174 }
175 
176 driver_init(csu_init);
177