1 /*
2 * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <errno.h>
9
10 #include <common/debug.h>
11 #include <drivers/clk.h>
12 #include <drivers/delay_timer.h>
13 #include <drivers/st/stpmic1.h>
14 #include <lib/mmio.h>
15 #include <lib/utils_def.h>
16 #include <libfdt.h>
17
18 #include <platform_def.h>
19 #include <stm32mp_common.h>
20 #include <stm32mp_dt.h>
21 #include <stm32mp1_private.h>
22
23 /*
24 * SYSCFG REGISTER OFFSET (base relative)
25 */
26 #define SYSCFG_BOOTR 0x00U
27 #define SYSCFG_BOOTCR 0x0CU
28 #if STM32MP15
29 #define SYSCFG_IOCTRLSETR 0x18U
30 #define SYSCFG_ICNR 0x1CU
31 #endif
32 #define SYSCFG_CMPCR 0x20U
33 #define SYSCFG_CMPENSETR 0x24U
34 #define SYSCFG_CMPENCLRR 0x28U
35 #if STM32MP13
36 #define SYSCFG_CMPSD1CR 0x30U
37 #define SYSCFG_CMPSD1ENSETR 0x34U
38 #define SYSCFG_CMPSD1ENCLRR 0x38U
39 #define SYSCFG_CMPSD2CR 0x40U
40 #define SYSCFG_CMPSD2ENSETR 0x44U
41 #define SYSCFG_CMPSD2ENCLRR 0x48U
42 #define SYSCFG_HSLVEN0R 0x50U
43 #endif
44 #define SYSCFG_IDC 0x380U
45
46 #define CMPCR_CMPENSETR_OFFSET 0x4U
47 #define CMPCR_CMPENCLRR_OFFSET 0x8U
48
49 /*
50 * SYSCFG_BOOTR Register
51 */
52 #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
53 #if STM32MP15
54 #define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
55 #define SYSCFG_BOOTR_BOOTPD_SHIFT 4
56 #endif
57
58 /*
59 * SYSCFG_BOOTCR Register
60 */
61 #define SYSCFG_BOOTCR_BMEN BIT(0)
62
63 /*
64 * SYSCFG_IOCTRLSETR Register
65 */
66 #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
67 #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
68 #define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
69 #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
70 #define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
71
72 /*
73 * SYSCFG_ICNR Register
74 */
75 #define SYSCFG_ICNR_AXI_M9 BIT(9)
76
77 /*
78 * SYSCFG_CMPCR Register
79 */
80 #define SYSCFG_CMPCR_SW_CTRL BIT(1)
81 #define SYSCFG_CMPCR_READY BIT(8)
82 #define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
83 #define SYSCFG_CMPCR_RANSRC_SHIFT 16
84 #define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
85 #define SYSCFG_CMPCR_ANSRC_SHIFT 24
86
87 #define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
88
89 /*
90 * SYSCFG_CMPENSETR Register
91 */
92 #define SYSCFG_CMPENSETR_MPU_EN BIT(0)
93
94 /*
95 * HSLV definitions
96 */
97 #define HSLV_IDX_TPIU 0U
98 #define HSLV_IDX_QSPI 1U
99 #define HSLV_IDX_ETH1 2U
100 #define HSLV_IDX_ETH2 3U
101 #define HSLV_IDX_SDMMC1 4U
102 #define HSLV_IDX_SDMMC2 5U
103 #define HSLV_IDX_SPI1 6U
104 #define HSLV_IDX_SPI2 7U
105 #define HSLV_IDX_SPI3 8U
106 #define HSLV_IDX_SPI4 9U
107 #define HSLV_IDX_SPI5 10U
108 #define HSLV_IDX_LTDC 11U
109 #define HSLV_NB_IDX 12U
110
111 #define HSLV_KEY 0x1018U
112
113 /*
114 * SYSCFG_IDC Register
115 */
116 #define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
117 #define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
118 #define SYSCFG_IDC_REV_ID_SHIFT 16
119
enable_io_comp_cell_finish(uintptr_t cmpcr_off)120 static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
121 {
122 uint64_t start;
123
124 start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
125
126 while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
127 if (timeout_elapsed(start)) {
128 /* Failure on IO compensation enable is not a issue: warn only. */
129 WARN("IO compensation cell not ready\n");
130 break;
131 }
132 }
133
134 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
135 }
136
disable_io_comp_cell(uintptr_t cmpcr_off)137 static void disable_io_comp_cell(uintptr_t cmpcr_off)
138 {
139 uint32_t value;
140
141 if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
142 ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
143 SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
144 return;
145 }
146
147 value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
148
149 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
150
151 value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
152 value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
153
154 mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
155
156 mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
157 }
158
159 #if STM32MP13
get_regu_max_voltage(void * fdt,int sdmmc_node,const char * regu_name,uint32_t * regu_val)160 static int get_regu_max_voltage(void *fdt, int sdmmc_node,
161 const char *regu_name, uint32_t *regu_val)
162 {
163 int node;
164 const fdt32_t *cuint;
165
166 cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL);
167 if (cuint == NULL) {
168 return -ENODEV;
169 }
170
171 node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
172 if (node < 0) {
173 return -ENODEV;
174 }
175
176 cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
177 if (cuint == NULL) {
178 return -ENODEV;
179 }
180
181 *regu_val = fdt32_to_cpu(*cuint);
182
183 return 0;
184 }
185
sdmmc_is_low_voltage(uintptr_t sdmmc_base)186 static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base)
187 {
188 int ret;
189 int node;
190 void *fdt = NULL;
191 uint32_t regu_max_val;
192
193 if (fdt_get_address(&fdt) == 0) {
194 return false;
195 }
196
197 if (fdt == NULL) {
198 return false;
199 }
200
201 node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base);
202 if (node < 0) {
203 /* No SD or eMMC device on this instance, enable HSLV */
204 return true;
205 }
206
207 ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", ®u_max_val);
208 if ((ret < 0) || (regu_max_val > 1800000U)) {
209 /*
210 * The vqmmc-supply property should always be present for eMMC.
211 * For SD-card, if it is not, then the card only supports 3.3V.
212 */
213 return false;
214 }
215
216 return true;
217 }
218
enable_hslv_by_index(uint32_t index)219 static void enable_hslv_by_index(uint32_t index)
220 {
221 bool apply_hslv;
222
223 assert(index < HSLV_NB_IDX);
224
225 switch (index) {
226 case HSLV_IDX_SDMMC1:
227 apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE);
228 break;
229 case HSLV_IDX_SDMMC2:
230 apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE);
231 break;
232 default:
233 apply_hslv = true;
234 break;
235 }
236
237 if (apply_hslv) {
238 uint32_t reg_offset = index * sizeof(uint32_t);
239
240 mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + reg_offset, HSLV_KEY);
241 }
242 }
243 #endif
244
enable_high_speed_mode_low_voltage(void)245 static void enable_high_speed_mode_low_voltage(void)
246 {
247 #if STM32MP13
248 uint32_t idx;
249
250 for (idx = 0U; idx < HSLV_NB_IDX; idx++) {
251 enable_hslv_by_index(idx);
252 }
253 #endif
254 #if STM32MP15
255 mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
256 SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
257 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
258 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
259 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
260 SYSCFG_IOCTRLSETR_HSLVEN_SPI);
261 #endif
262 }
263
stm32mp1_syscfg_set_hslv(void)264 static void stm32mp1_syscfg_set_hslv(void)
265 {
266 uint32_t otp_value;
267 uint32_t vdd_voltage;
268 bool product_below_2v5;
269
270 /*
271 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
272 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
273 * It could be disabled for low frequencies or if AFMUX is selected
274 * but the function is not used, typically for TRACE.
275 * If high speed low voltage pad mode is node enable, platform will
276 * over consume.
277 *
278 * WARNING:
279 * Enabling High Speed mode while VDD > 2.7V
280 * with the OTP product_below_2v5 (OTP 18, BIT 13)
281 * erroneously set to 1 can damage the SoC!
282 * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
283 * but this value needs to be consistent with board design.
284 */
285 if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
286 panic();
287 }
288
289 product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
290
291 /* Get VDD supply */
292 vdd_voltage = dt_get_pwr_vdd_voltage();
293
294 /* Check if VDD is Low Voltage */
295 if (vdd_voltage == 0U) {
296 WARN("VDD unknown\n");
297 } else if (vdd_voltage < 2700000U) {
298 enable_high_speed_mode_low_voltage();
299
300 if (!product_below_2v5) {
301 INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
302 }
303 } else {
304 if (product_below_2v5) {
305 ERROR("Product_below_2v5=1:\n");
306 ERROR("\tHSLVEN update is destructive,\n");
307 ERROR("\tno update as VDD > 2.7V\n");
308 panic();
309 }
310 }
311 }
312
stm32mp1_syscfg_init(void)313 void stm32mp1_syscfg_init(void)
314 {
315 #if STM32MP15
316 uint32_t bootr;
317
318 /*
319 * Interconnect update : select master using the port 1.
320 * LTDC = AXI_M9.
321 */
322 mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
323
324 /* Disable Pull-Down for boot pin connected to VDD */
325 bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
326 SYSCFG_BOOTR_BOOT_MASK;
327 mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
328 bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
329 #endif
330
331 stm32mp1_syscfg_set_hslv();
332
333 stm32mp1_syscfg_enable_io_compensation_start();
334 }
335
stm32mp1_syscfg_enable_io_compensation_start(void)336 void stm32mp1_syscfg_enable_io_compensation_start(void)
337 {
338 /*
339 * Activate automatic I/O compensation.
340 * Warning: need to ensure CSI enabled and ready in clock driver.
341 * Enable non-secure clock, we assume non-secure is suspended.
342 */
343 clk_enable(SYSCFG);
344
345 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
346 SYSCFG_CMPENSETR_MPU_EN);
347 #if STM32MP13
348 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
349 SYSCFG_CMPENSETR_MPU_EN);
350 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
351 SYSCFG_CMPENSETR_MPU_EN);
352
353 #endif
354 }
355
stm32mp1_syscfg_enable_io_compensation_finish(void)356 void stm32mp1_syscfg_enable_io_compensation_finish(void)
357 {
358 enable_io_comp_cell_finish(SYSCFG_CMPCR);
359 #if STM32MP13
360 enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
361 enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
362 #endif
363 }
364
stm32mp1_syscfg_disable_io_compensation(void)365 void stm32mp1_syscfg_disable_io_compensation(void)
366 {
367 clk_enable(SYSCFG);
368
369 /*
370 * Deactivate automatic I/O compensation.
371 * Warning: CSI is disabled automatically in STOP if not
372 * requested for other usages and always OFF in STANDBY.
373 * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
374 */
375 disable_io_comp_cell(SYSCFG_CMPCR);
376 #if STM32MP13
377 disable_io_comp_cell(SYSCFG_CMPSD1CR);
378 disable_io_comp_cell(SYSCFG_CMPSD2CR);
379 #endif
380
381 clk_disable(SYSCFG);
382 }
383
384 /*
385 * @brief Get silicon revision from SYSCFG registers.
386 * @retval chip version (REV_ID).
387 */
stm32mp1_syscfg_get_chip_version(void)388 uint32_t stm32mp1_syscfg_get_chip_version(void)
389 {
390 return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
391 SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
392 }
393
394 /*
395 * @brief Get device ID from SYSCFG registers.
396 * @retval device ID (DEV_ID).
397 */
stm32mp1_syscfg_get_chip_dev_id(void)398 uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
399 {
400 return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
401 }
402
403 #if STM32MP13
stm32mp1_syscfg_boot_mode_enable(void)404 void stm32mp1_syscfg_boot_mode_enable(void)
405 {
406 mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
407 }
408
stm32mp1_syscfg_boot_mode_disable(void)409 void stm32mp1_syscfg_boot_mode_disable(void)
410 {
411 mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
412 }
413 #endif
414