blob: 39ad90b7e09f1c4ac72126e9c0c9fd7738537829 [file] [log] [blame]
Yann Gautierf33b2432019-05-20 19:17:08 +02001/*
Nicolas Le Bayonde02e9b2019-11-18 17:18:06 +01002 * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
Yann Gautierf33b2432019-05-20 19:17:08 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautierfca10a82021-01-12 15:52:19 +01007#include <assert.h>
8#include <errno.h>
9
Yann Gautierf33b2432019-05-20 19:17:08 +020010#include <common/debug.h>
Etienne Carrierec7a66e72020-02-07 13:38:30 +010011#include <drivers/clk.h>
Nicolas Le Bayonde02e9b2019-11-18 17:18:06 +010012#include <drivers/delay_timer.h>
Yann Gautierf33b2432019-05-20 19:17:08 +020013#include <drivers/st/stpmic1.h>
14#include <lib/mmio.h>
Yann Gautier6512c3a2020-04-21 15:03:59 +020015#include <lib/utils_def.h>
Yann Gautierfca10a82021-01-12 15:52:19 +010016#include <libfdt.h>
Yann Gautierf33b2432019-05-20 19:17:08 +020017
Nicolas Le Bayonde02e9b2019-11-18 17:18:06 +010018#include <platform_def.h>
Lionel Debieveae3ce8b2019-11-04 14:31:38 +010019#include <stm32mp_common.h>
Yann Gautierf33b2432019-05-20 19:17:08 +020020#include <stm32mp_dt.h>
21#include <stm32mp1_private.h>
22
23/*
24 * SYSCFG REGISTER OFFSET (base relative)
25 */
26#define SYSCFG_BOOTR 0x00U
Yann Gautier111a3842020-02-12 09:36:23 +010027#if STM32MP15
Yann Gautierf33b2432019-05-20 19:17:08 +020028#define SYSCFG_IOCTRLSETR 0x18U
29#define SYSCFG_ICNR 0x1CU
Yann Gautier111a3842020-02-12 09:36:23 +010030#endif
Yann Gautierf33b2432019-05-20 19:17:08 +020031#define SYSCFG_CMPCR 0x20U
32#define SYSCFG_CMPENSETR 0x24U
Yann Gautierc2d18ca2020-10-26 15:21:25 +010033#define SYSCFG_CMPENCLRR 0x28U
Yann Gautier8e07ab52020-11-17 15:27:58 +010034#if STM32MP13
35#define SYSCFG_CMPSD1CR 0x30U
36#define SYSCFG_CMPSD1ENSETR 0x34U
37#define SYSCFG_CMPSD1ENCLRR 0x38U
38#define SYSCFG_CMPSD2CR 0x40U
39#define SYSCFG_CMPSD2ENSETR 0x44U
40#define SYSCFG_CMPSD2ENCLRR 0x48U
Yann Gautierfca10a82021-01-12 15:52:19 +010041#define SYSCFG_HSLVEN0R 0x50U
Yann Gautier8e07ab52020-11-17 15:27:58 +010042#endif
Yann Gautier6512c3a2020-04-21 15:03:59 +020043#define SYSCFG_IDC 0x380U
Yann Gautierf33b2432019-05-20 19:17:08 +020044
Yann Gautier1f4513c2020-12-16 10:17:35 +010045#define CMPCR_CMPENSETR_OFFSET 0x4U
46#define CMPCR_CMPENCLRR_OFFSET 0x8U
47
Yann Gautierf33b2432019-05-20 19:17:08 +020048/*
49 * SYSCFG_BOOTR Register
50 */
51#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
Yann Gautier111a3842020-02-12 09:36:23 +010052#if STM32MP15
Yann Gautierf33b2432019-05-20 19:17:08 +020053#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
54#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
Yann Gautier111a3842020-02-12 09:36:23 +010055#endif
56
Yann Gautierf33b2432019-05-20 19:17:08 +020057/*
58 * SYSCFG_IOCTRLSETR Register
59 */
60#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
61#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
62#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
63#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
64#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
65
66/*
67 * SYSCFG_ICNR Register
68 */
69#define SYSCFG_ICNR_AXI_M9 BIT(9)
70
71/*
72 * SYSCFG_CMPCR Register
73 */
74#define SYSCFG_CMPCR_SW_CTRL BIT(1)
75#define SYSCFG_CMPCR_READY BIT(8)
76#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
77#define SYSCFG_CMPCR_RANSRC_SHIFT 16
78#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
79#define SYSCFG_CMPCR_ANSRC_SHIFT 24
80
Nicolas Le Bayonde02e9b2019-11-18 17:18:06 +010081#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
82
Yann Gautierf33b2432019-05-20 19:17:08 +020083/*
84 * SYSCFG_CMPENSETR Register
85 */
86#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
87
Yann Gautier6512c3a2020-04-21 15:03:59 +020088/*
Yann Gautierfca10a82021-01-12 15:52:19 +010089 * HSLV definitions
90 */
91#define HSLV_IDX_TPIU 0U
92#define HSLV_IDX_QSPI 1U
93#define HSLV_IDX_ETH1 2U
94#define HSLV_IDX_ETH2 3U
95#define HSLV_IDX_SDMMC1 4U
96#define HSLV_IDX_SDMMC2 5U
97#define HSLV_IDX_SPI1 6U
98#define HSLV_IDX_SPI2 7U
99#define HSLV_IDX_SPI3 8U
100#define HSLV_IDX_SPI4 9U
101#define HSLV_IDX_SPI5 10U
102#define HSLV_IDX_LTDC 11U
103#define HSLV_NB_IDX 12U
104
105#define HSLV_KEY 0x1018U
106
107/*
Yann Gautier6512c3a2020-04-21 15:03:59 +0200108 * SYSCFG_IDC Register
109 */
110#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
111#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
112#define SYSCFG_IDC_REV_ID_SHIFT 16
113
Yann Gautier1f4513c2020-12-16 10:17:35 +0100114static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
115{
116 uint64_t start;
117
118 start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
119
120 while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
121 if (timeout_elapsed(start)) {
122 /* Failure on IO compensation enable is not a issue: warn only. */
123 WARN("IO compensation cell not ready\n");
124 break;
125 }
126 }
127
128 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
129}
130
131static void disable_io_comp_cell(uintptr_t cmpcr_off)
132{
133 uint32_t value;
134
135 if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
136 ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
137 SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
138 return;
139 }
140
141 value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
142
143 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
144
145 value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
146 value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
147
148 mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
149
150 mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
151}
152
Yann Gautierfca10a82021-01-12 15:52:19 +0100153#if STM32MP13
154static int get_regu_max_voltage(void *fdt, int sdmmc_node,
155 const char *regu_name, uint32_t *regu_val)
156{
157 int node;
158 const fdt32_t *cuint;
159
160 cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL);
161 if (cuint == NULL) {
162 return -ENODEV;
163 }
164
165 node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
166 if (node < 0) {
167 return -ENODEV;
168 }
169
170 cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
171 if (cuint == NULL) {
172 return -ENODEV;
173 }
174
175 *regu_val = fdt32_to_cpu(*cuint);
176
177 return 0;
178}
179
180static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base)
181{
182 int ret;
183 int node;
184 void *fdt = NULL;
185 uint32_t regu_max_val;
186
187 if (fdt_get_address(&fdt) == 0) {
188 return false;
189 }
190
191 if (fdt == NULL) {
192 return false;
193 }
194
195 node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base);
196 if (node < 0) {
197 /* No SD or eMMC device on this instance, enable HSLV */
198 return true;
199 }
200
201 ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", &regu_max_val);
202 if ((ret < 0) || (regu_max_val > 1800000U)) {
203 /*
204 * The vqmmc-supply property should always be present for eMMC.
205 * For SD-card, if it is not, then the card only supports 3.3V.
206 */
207 return false;
208 }
209
210 return true;
211}
212
213static void enable_hslv_by_index(uint32_t index)
214{
215 bool apply_hslv;
216
217 assert(index < HSLV_NB_IDX);
218
219 switch (index) {
220 case HSLV_IDX_SDMMC1:
221 apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE);
222 break;
223 case HSLV_IDX_SDMMC2:
224 apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE);
225 break;
226 default:
227 apply_hslv = true;
228 break;
229 }
230
231 if (apply_hslv) {
232 mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY);
233 }
234}
235#endif
236
Yann Gautierdea02f42021-01-12 14:45:02 +0100237static void enable_high_speed_mode_low_voltage(void)
Yann Gautierf33b2432019-05-20 19:17:08 +0200238{
Yann Gautierfca10a82021-01-12 15:52:19 +0100239#if STM32MP13
240 uint32_t idx;
241
242 for (idx = 0U; idx < HSLV_NB_IDX; idx++) {
243 enable_hslv_by_index(idx);
244 }
245#endif
Yann Gautier111a3842020-02-12 09:36:23 +0100246#if STM32MP15
Yann Gautierdea02f42021-01-12 14:45:02 +0100247 mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
248 SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
249 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
250 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
251 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
252 SYSCFG_IOCTRLSETR_HSLVEN_SPI);
Yann Gautier111a3842020-02-12 09:36:23 +0100253#endif
Yann Gautierdea02f42021-01-12 14:45:02 +0100254}
255
256static void stm32mp1_syscfg_set_hslv(void)
257{
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100258 uint32_t otp_value;
Yann Gautierf33b2432019-05-20 19:17:08 +0200259 uint32_t vdd_voltage;
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100260 bool product_below_2v5;
Yann Gautierf33b2432019-05-20 19:17:08 +0200261
262 /*
Yann Gautierf33b2432019-05-20 19:17:08 +0200263 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
264 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
265 * It could be disabled for low frequencies or if AFMUX is selected
266 * but the function is not used, typically for TRACE.
267 * If high speed low voltage pad mode is node enable, platform will
268 * over consume.
269 *
270 * WARNING:
271 * Enabling High Speed mode while VDD > 2.7V
272 * with the OTP product_below_2v5 (OTP 18, BIT 13)
273 * erroneously set to 1 can damage the SoC!
274 * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
275 * but this value needs to be consistent with board design.
276 */
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100277 if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
Yann Gautierf33b2432019-05-20 19:17:08 +0200278 panic();
279 }
280
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100281 product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
Yann Gautierf33b2432019-05-20 19:17:08 +0200282
283 /* Get VDD supply */
284 vdd_voltage = dt_get_pwr_vdd_voltage();
285
286 /* Check if VDD is Low Voltage */
287 if (vdd_voltage == 0U) {
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100288 WARN("VDD unknown\n");
Yann Gautierf33b2432019-05-20 19:17:08 +0200289 } else if (vdd_voltage < 2700000U) {
Yann Gautierdea02f42021-01-12 14:45:02 +0100290 enable_high_speed_mode_low_voltage();
Yann Gautierf33b2432019-05-20 19:17:08 +0200291
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100292 if (!product_below_2v5) {
Yann Gautierf33b2432019-05-20 19:17:08 +0200293 INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
294 }
295 } else {
Lionel Debieveae3ce8b2019-11-04 14:31:38 +0100296 if (product_below_2v5) {
Yann Gautierf33b2432019-05-20 19:17:08 +0200297 ERROR("Product_below_2v5=1:\n");
298 ERROR("\tHSLVEN update is destructive,\n");
299 ERROR("\tno update as VDD > 2.7V\n");
300 panic();
301 }
302 }
Yann Gautierdea02f42021-01-12 14:45:02 +0100303}
304
305void stm32mp1_syscfg_init(void)
306{
Yann Gautier111a3842020-02-12 09:36:23 +0100307#if STM32MP15
Yann Gautierdea02f42021-01-12 14:45:02 +0100308 uint32_t bootr;
309
310 /*
311 * Interconnect update : select master using the port 1.
312 * LTDC = AXI_M9.
313 */
314 mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
315
316 /* Disable Pull-Down for boot pin connected to VDD */
317 bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
318 SYSCFG_BOOTR_BOOT_MASK;
319 mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
320 bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
Yann Gautier111a3842020-02-12 09:36:23 +0100321#endif
Yann Gautierdea02f42021-01-12 14:45:02 +0100322
323 stm32mp1_syscfg_set_hslv();
Yann Gautierf33b2432019-05-20 19:17:08 +0200324
Yann Gautier1f4513c2020-12-16 10:17:35 +0100325 stm32mp1_syscfg_enable_io_compensation_start();
Yann Gautierf33b2432019-05-20 19:17:08 +0200326}
327
Yann Gautier1f4513c2020-12-16 10:17:35 +0100328void stm32mp1_syscfg_enable_io_compensation_start(void)
Yann Gautierf33b2432019-05-20 19:17:08 +0200329{
Yann Gautierf33b2432019-05-20 19:17:08 +0200330 /*
331 * Activate automatic I/O compensation.
332 * Warning: need to ensure CSI enabled and ready in clock driver.
333 * Enable non-secure clock, we assume non-secure is suspended.
334 */
Etienne Carrierec7a66e72020-02-07 13:38:30 +0100335 clk_enable(SYSCFG);
Yann Gautierf33b2432019-05-20 19:17:08 +0200336
Yann Gautier1f4513c2020-12-16 10:17:35 +0100337 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
Yann Gautierf33b2432019-05-20 19:17:08 +0200338 SYSCFG_CMPENSETR_MPU_EN);
Yann Gautier8e07ab52020-11-17 15:27:58 +0100339#if STM32MP13
340 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
341 SYSCFG_CMPENSETR_MPU_EN);
342 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
343 SYSCFG_CMPENSETR_MPU_EN);
344
345#endif
Yann Gautier1f4513c2020-12-16 10:17:35 +0100346}
Yann Gautierf33b2432019-05-20 19:17:08 +0200347
Yann Gautier1f4513c2020-12-16 10:17:35 +0100348void stm32mp1_syscfg_enable_io_compensation_finish(void)
349{
350 enable_io_comp_cell_finish(SYSCFG_CMPCR);
Yann Gautier8e07ab52020-11-17 15:27:58 +0100351#if STM32MP13
352 enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
353 enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
354#endif
Yann Gautierf33b2432019-05-20 19:17:08 +0200355}
356
357void stm32mp1_syscfg_disable_io_compensation(void)
358{
Yann Gautier1f4513c2020-12-16 10:17:35 +0100359 clk_enable(SYSCFG);
Yann Gautierf33b2432019-05-20 19:17:08 +0200360
361 /*
362 * Deactivate automatic I/O compensation.
363 * Warning: CSI is disabled automatically in STOP if not
364 * requested for other usages and always OFF in STANDBY.
365 * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
366 */
Yann Gautier1f4513c2020-12-16 10:17:35 +0100367 disable_io_comp_cell(SYSCFG_CMPCR);
Yann Gautier8e07ab52020-11-17 15:27:58 +0100368#if STM32MP13
369 disable_io_comp_cell(SYSCFG_CMPSD1CR);
370 disable_io_comp_cell(SYSCFG_CMPSD2CR);
371#endif
Yann Gautierf33b2432019-05-20 19:17:08 +0200372
Etienne Carrierec7a66e72020-02-07 13:38:30 +0100373 clk_disable(SYSCFG);
Yann Gautierf33b2432019-05-20 19:17:08 +0200374}
Yann Gautier6512c3a2020-04-21 15:03:59 +0200375
376/*
377 * @brief Get silicon revision from SYSCFG registers.
378 * @retval chip version (REV_ID).
379 */
380uint32_t stm32mp1_syscfg_get_chip_version(void)
381{
382 return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
383 SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
384}
385
386/*
387 * @brief Get device ID from SYSCFG registers.
388 * @retval device ID (DEV_ID).
389 */
390uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
391{
392 return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
393}