xref: /optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c (revision faaa17350a63b639d82b80b08c5512e87a80f33c)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019-2023, STMicroelectronics
4  */
5 
6 #include <config.h>
7 #include <drivers/clk.h>
8 #include <drivers/stm32mp_dt_bindings.h>
9 #include <drivers/stm32mp1_syscfg.h>
10 #include <initcall.h>
11 #include <kernel/delay.h>
12 #include <mm/core_memprot.h>
13 #include <stm32_util.h>
14 #include <io.h>
15 #include <trace.h>
16 #include <types_ext.h>
17 
18 /*
19  * SYSCFG register offsets (base relative)
20  */
21 #define SYSCFG_SRAM3ERASER			U(0x10)
22 #define SYSCFG_SRAM3KR				U(0x14)
23 #define SYSCFG_IOCTRLSETR			U(0x18)
24 #define SYSCFG_CMPCR				U(0x20)
25 #define SYSCFG_CMPENSETR			U(0x24)
26 #define SYSCFG_CMPSD1CR				U(0x30)
27 #define SYSCFG_CMPSD2CR				U(0x40)
28 #define SYSCFG_HSLVEN0R				U(0x50)
29 #define SYSCFG_IDC				U(0x380)
30 #define SYSCFG_IOSIZE				U(0x400)
31 
32 /*
33  * SYSCFG_IOCTRLSETR Register for STM32MP15 variants
34  */
35 #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE		BIT(0)
36 #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI	BIT(1)
37 #define SYSCFG_IOCTRLSETR_HSLVEN_ETH		BIT(2)
38 #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC		BIT(3)
39 #define SYSCFG_IOCTRLSETR_HSLVEN_SPI		BIT(4)
40 
41 /*
42  * SYSCFG_SRAM3ERASE Register
43  */
44 #define SYSCFG_SRAM3KR_KEY1			U(0xCA)
45 #define SYSCFG_SRAM3KR_KEY2			U(0x53)
46 
47 #define SYSCFG_SRAM3ERASER_SRAM3EO		BIT(1)
48 #define SYSCFG_SRAM3ERASER_SRAM3ER		BIT(0)
49 
50 #define SYSCFG_SRAM3ERASE_TIMEOUT_US		U(1000)
51 
52 /*
53  * SYSCFG_CMPCR Register
54  */
55 #define SYSCFG_CMPCR_SW_CTRL			BIT(1)
56 #define SYSCFG_CMPCR_READY			BIT(8)
57 #define SYSCFG_CMPCR_RANSRC			GENMASK_32(19, 16)
58 #define SYSCFG_CMPCR_RANSRC_SHIFT		U(16)
59 #define SYSCFG_CMPCR_RAPSRC			GENMASK_32(23, 20)
60 #define SYSCFG_CMPCR_ANSRC_SHIFT		U(24)
61 
62 #define SYSCFG_CMPCR_READY_TIMEOUT_US		U(10000)
63 
64 #define CMPENSETR_OFFSET			U(0x4)
65 #define CMPENCLRR_OFFSET			U(0x8)
66 
67 /*
68  * SYSCFG_CMPENSETR Register
69  */
70 #define SYSCFG_CMPENSETR_MPU_EN			BIT(0)
71 
72 /*
73  * HSLV definitions
74  */
75 #define SYSCFG_HSLV_MASK			GENMASK_32(15, 0)
76 #define SYSCFG_HSLV_KEY				U(0x1018)
77 
78 /*
79  * SYSCFG_IDC Register
80  */
81 #define SYSCFG_IDC_DEV_ID_MASK			GENMASK_32(11, 0)
82 #define SYSCFG_IDC_REV_ID_MASK			GENMASK_32(31, 16)
83 #define SYSCFG_IDC_REV_ID_SHIFT			U(16)
84 
get_syscfg_base(void)85 static vaddr_t get_syscfg_base(void)
86 {
87 	static struct io_pa_va base = { .pa = SYSCFG_BASE };
88 
89 	return io_pa_or_va(&base, SYSCFG_IOSIZE);
90 }
91 
stm32mp_syscfg_get_chip_dev_id(void)92 uint32_t stm32mp_syscfg_get_chip_dev_id(void)
93 {
94 	if (IS_ENABLED(CFG_STM32MP13))
95 		return io_read32(get_syscfg_base() + SYSCFG_IDC) &
96 		       SYSCFG_IDC_DEV_ID_MASK;
97 
98 	return 0;
99 }
100 
enable_io_compensation(int cmpcr_offset)101 static void enable_io_compensation(int cmpcr_offset)
102 {
103 	vaddr_t cmpcr_va = get_syscfg_base() + cmpcr_offset;
104 	uint32_t value = 0;
105 
106 	if (io_read32(cmpcr_va) & SYSCFG_CMPCR_READY)
107 		return;
108 
109 	io_setbits32(cmpcr_va + CMPENSETR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
110 
111 	if (IO_READ32_POLL_TIMEOUT(cmpcr_va, value, value & SYSCFG_CMPCR_READY,
112 				   0, SYSCFG_CMPCR_READY_TIMEOUT_US)) {
113 		/* Allow an almost silent failure here */
114 		EMSG("IO compensation cell not ready");
115 	}
116 
117 	io_clrbits32(cmpcr_va, SYSCFG_CMPCR_SW_CTRL);
118 
119 	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_va));
120 }
121 
disable_io_compensation(int cmpcr_offset)122 static __maybe_unused void disable_io_compensation(int cmpcr_offset)
123 {
124 	vaddr_t cmpcr_base = get_syscfg_base() + cmpcr_offset;
125 	uint32_t value_cmpcr = 0;
126 	uint32_t apsrc_ansrc = 0;
127 	uint32_t value_cmpcr2 = 0;
128 
129 	value_cmpcr = io_read32(cmpcr_base);
130 	value_cmpcr2 = io_read32(cmpcr_base + CMPENSETR_OFFSET);
131 	if (!(value_cmpcr & SYSCFG_CMPCR_READY &&
132 	      value_cmpcr2 & SYSCFG_CMPENSETR_MPU_EN))
133 		return;
134 
135 	/* Copy APSRC (resp. ANSRC) in RAPSRC (resp. RANSRC) */
136 	apsrc_ansrc = value_cmpcr >> SYSCFG_CMPCR_ANSRC_SHIFT;
137 	value_cmpcr &= ~(SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
138 	value_cmpcr |= SHIFT_U32(apsrc_ansrc, SYSCFG_CMPCR_RANSRC_SHIFT);
139 
140 	io_write32(cmpcr_base, value_cmpcr | SYSCFG_CMPCR_SW_CTRL);
141 
142 	io_setbits32(cmpcr_base + CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
143 
144 	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_base));
145 }
146 
stm32mp1_iocomp(void)147 static TEE_Result stm32mp1_iocomp(void)
148 {
149 	if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) ||
150 	    clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG)))
151 		panic();
152 
153 	enable_io_compensation(SYSCFG_CMPCR);
154 
155 	/* Make sure the write above is visible */
156 	dsb();
157 
158 	return TEE_SUCCESS;
159 }
160 
161 driver_init(stm32mp1_iocomp);
162 
163 #ifdef CFG_STM32MP13
stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id,bool enable)164 void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable)
165 {
166 	int cmpcr_offset = 0;
167 
168 	/* Make sure the previous operations are visible */
169 	dsb();
170 
171 	switch (id) {
172 	case SYSCFG_IO_COMP_IDX_SD1:
173 		cmpcr_offset = SYSCFG_CMPSD1CR;
174 		break;
175 	case SYSCFG_IO_COMP_IDX_SD2:
176 		cmpcr_offset = SYSCFG_CMPSD2CR;
177 		break;
178 	default:
179 		panic();
180 	}
181 
182 	if (enable)
183 		enable_io_compensation(cmpcr_offset);
184 	else
185 		disable_io_compensation(cmpcr_offset);
186 
187 	/* Make sure the write above is visible */
188 	dsb();
189 }
190 
stm32mp_set_hslv_state(enum stm32mp13_hslv_id id,bool enable)191 void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable)
192 {
193 	size_t hslvenxr_offset = 0;
194 	uint32_t hlvs_value = 0;
195 
196 	/* Make sure the previous operations are visible */
197 	dsb();
198 
199 	assert(id < SYSCFG_HSLV_COUNT);
200 
201 	if (enable)
202 		hlvs_value = SYSCFG_HSLV_KEY;
203 
204 	/* IDs are indices of SYSCFG_HSLVENxR registers */
205 	hslvenxr_offset = SYSCFG_HSLVEN0R + id * sizeof(uint32_t);
206 
207 	io_write32(get_syscfg_base() + hslvenxr_offset, hlvs_value);
208 
209 	/* Value read shall be 1 on enable and 0 on disable */
210 	hlvs_value = io_read32(get_syscfg_base() + hslvenxr_offset) &
211 		     SYSCFG_HSLV_MASK;
212 	if (enable != hlvs_value)
213 		panic();
214 }
215 
stm32mp_enable_fixed_vdd_hslv(void)216 void stm32mp_enable_fixed_vdd_hslv(void)
217 {
218 	enum stm32mp13_hslv_id id = SYSCFG_HSLV_COUNT;
219 
220 	for (id = SYSCFG_HSLV_IDX_TPIU; id < SYSCFG_HSLV_COUNT; id++) {
221 		/* SDMMCs domains may not be supplied by VDD */
222 		if (id == SYSCFG_HSLV_IDX_SDMMC1 ||
223 		    id == SYSCFG_HSLV_IDX_SDMMC2)
224 			continue;
225 
226 		stm32mp_set_hslv_state(id, true);
227 	}
228 }
229 #endif /* CFG_STM32MP13 */
230 
231 #ifdef CFG_STM32MP15
stm32mp_enable_fixed_vdd_hslv(void)232 void stm32mp_enable_fixed_vdd_hslv(void)
233 {
234 	dsb();
235 
236 	io_write32(get_syscfg_base() + SYSCFG_IOCTRLSETR,
237 		   SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
238 		   SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
239 		   SYSCFG_IOCTRLSETR_HSLVEN_ETH |
240 		   SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
241 		   SYSCFG_IOCTRLSETR_HSLVEN_SPI);
242 
243 	dsb();
244 }
245 #endif
246 
stm32mp_syscfg_erase_sram3(void)247 TEE_Result stm32mp_syscfg_erase_sram3(void)
248 {
249 	vaddr_t base = get_syscfg_base();
250 	uint32_t value = 0;
251 
252 	if (!IS_ENABLED(CFG_STM32MP13))
253 		return TEE_ERROR_NOT_SUPPORTED;
254 
255 	/* Unlock SYSCFG_SRAM3ERASER_SRAM3ER */
256 	io_write32(base + SYSCFG_SRAM3KR, SYSCFG_SRAM3KR_KEY1);
257 	io_write32(base + SYSCFG_SRAM3KR, SYSCFG_SRAM3KR_KEY2);
258 
259 	/* Request SRAM3 erase */
260 	io_setbits32(base + SYSCFG_SRAM3ERASER, SYSCFG_SRAM3ERASER_SRAM3ER);
261 
262 	/* Lock SYSCFG_SRAM3ERASER_SRAM3ER */
263 	io_write32(base + SYSCFG_SRAM3KR, 0);
264 
265 	/* Wait end of SRAM3 erase */
266 	if (IO_READ32_POLL_TIMEOUT(base + SYSCFG_SRAM3ERASER, value,
267 				   !(value & SYSCFG_SRAM3ERASER_SRAM3EO), 0,
268 				   SYSCFG_SRAM3ERASE_TIMEOUT_US))
269 		return TEE_ERROR_BUSY;
270 
271 	return TEE_SUCCESS;
272 }
273