blob: 199bdc9c337f4aa7982ad6865c670151f1fdf08a [file] [log] [blame]
Yann Gautier3edc7c32019-05-20 19:17:08 +02001/*
Maxime Méré80d9fb42024-01-16 15:40:49 +01002 * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved
Yann Gautier3edc7c32019-05-20 19:17:08 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautier07cf3f22021-01-12 15:52:19 +01007#include <assert.h>
8#include <errno.h>
9
Yann Gautier3edc7c32019-05-20 19:17:08 +020010#include <common/debug.h>
Etienne Carriere1de46d02020-02-07 13:38:30 +010011#include <drivers/clk.h>
Nicolas Le Bayon36898692019-11-18 17:18:06 +010012#include <drivers/delay_timer.h>
Yann Gautier3edc7c32019-05-20 19:17:08 +020013#include <drivers/st/stpmic1.h>
14#include <lib/mmio.h>
Yann Gautierf36a1d32020-04-21 15:03:59 +020015#include <lib/utils_def.h>
Yann Gautier07cf3f22021-01-12 15:52:19 +010016#include <libfdt.h>
Yann Gautier3edc7c32019-05-20 19:17:08 +020017
Nicolas Le Bayon36898692019-11-18 17:18:06 +010018#include <platform_def.h>
Lionel Debievebc2d88d2019-11-04 14:31:38 +010019#include <stm32mp_common.h>
Yann Gautier3edc7c32019-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
Nicolas Toromanoff1877b132021-02-03 16:52:03 +010027#define SYSCFG_BOOTCR 0x0CU
Yann Gautiercc5f89a2020-02-12 09:36:23 +010028#if STM32MP15
Yann Gautier3edc7c32019-05-20 19:17:08 +020029#define SYSCFG_IOCTRLSETR 0x18U
30#define SYSCFG_ICNR 0x1CU
Yann Gautiercc5f89a2020-02-12 09:36:23 +010031#endif
Yann Gautier3edc7c32019-05-20 19:17:08 +020032#define SYSCFG_CMPCR 0x20U
33#define SYSCFG_CMPENSETR 0x24U
Yann Gautier0315fa02020-10-26 15:21:25 +010034#define SYSCFG_CMPENCLRR 0x28U
Yann Gautier4a164842020-11-17 15:27:58 +010035#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
Yann Gautier07cf3f22021-01-12 15:52:19 +010042#define SYSCFG_HSLVEN0R 0x50U
Yann Gautier4a164842020-11-17 15:27:58 +010043#endif
Yann Gautierf36a1d32020-04-21 15:03:59 +020044#define SYSCFG_IDC 0x380U
Yann Gautier3edc7c32019-05-20 19:17:08 +020045
Yann Gautierb76c61a2020-12-16 10:17:35 +010046#define CMPCR_CMPENSETR_OFFSET 0x4U
47#define CMPCR_CMPENCLRR_OFFSET 0x8U
48
Yann Gautier3edc7c32019-05-20 19:17:08 +020049/*
50 * SYSCFG_BOOTR Register
51 */
52#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
Yann Gautiercc5f89a2020-02-12 09:36:23 +010053#if STM32MP15
Yann Gautier3edc7c32019-05-20 19:17:08 +020054#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
55#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
Yann Gautiercc5f89a2020-02-12 09:36:23 +010056#endif
57
Yann Gautier3edc7c32019-05-20 19:17:08 +020058/*
Nicolas Toromanoff1877b132021-02-03 16:52:03 +010059 * SYSCFG_BOOTCR Register
60 */
61#define SYSCFG_BOOTCR_BMEN BIT(0)
62
63/*
Yann Gautier3edc7c32019-05-20 19:17:08 +020064 * 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
Nicolas Le Bayon36898692019-11-18 17:18:06 +010087#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
88
Yann Gautier3edc7c32019-05-20 19:17:08 +020089/*
90 * SYSCFG_CMPENSETR Register
91 */
92#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
93
Yann Gautierf36a1d32020-04-21 15:03:59 +020094/*
Yann Gautier07cf3f22021-01-12 15:52:19 +010095 * 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/*
Yann Gautierf36a1d32020-04-21 15:03:59 +0200114 * 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
Yann Gautierb76c61a2020-12-16 10:17:35 +0100120static 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
137static 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
Yann Gautier07cf3f22021-01-12 15:52:19 +0100159#if STM32MP13
160static 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
186static 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", &regu_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
219static 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) {
Yann Gautier88b8f2b2022-11-18 15:03:22 +0100238 uint32_t reg_offset = index * sizeof(uint32_t);
239
240 mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + reg_offset, HSLV_KEY);
Yann Gautier07cf3f22021-01-12 15:52:19 +0100241 }
242}
243#endif
244
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100245static void enable_high_speed_mode_low_voltage(void)
Yann Gautier3edc7c32019-05-20 19:17:08 +0200246{
Yann Gautier07cf3f22021-01-12 15:52:19 +0100247#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
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100254#if STM32MP15
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100255 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);
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100261#endif
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100262}
263
Maxime Méré80d9fb42024-01-16 15:40:49 +0100264static void stm32mp_syscfg_set_hslv(void)
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100265{
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100266 uint32_t otp_value;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200267 uint32_t vdd_voltage;
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100268 bool product_below_2v5;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200269
270 /*
Yann Gautier3edc7c32019-05-20 19:17:08 +0200271 * 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 */
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100285 if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200286 panic();
287 }
288
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100289 product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200290
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) {
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100296 WARN("VDD unknown\n");
Yann Gautier3edc7c32019-05-20 19:17:08 +0200297 } else if (vdd_voltage < 2700000U) {
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100298 enable_high_speed_mode_low_voltage();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200299
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100300 if (!product_below_2v5) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200301 INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
302 }
303 } else {
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100304 if (product_below_2v5) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200305 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 }
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100311}
312
Maxime Méré80d9fb42024-01-16 15:40:49 +0100313void stm32mp_syscfg_init(void)
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100314{
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100315#if STM32MP15
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100316 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);
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100329#endif
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100330
Maxime Méré80d9fb42024-01-16 15:40:49 +0100331 stm32mp_syscfg_set_hslv();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200332
Maxime Méré80d9fb42024-01-16 15:40:49 +0100333 stm32mp_syscfg_enable_io_compensation_start();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200334}
335
Maxime Méré80d9fb42024-01-16 15:40:49 +0100336void stm32mp_syscfg_enable_io_compensation_start(void)
Yann Gautier3edc7c32019-05-20 19:17:08 +0200337{
Yann Gautier3edc7c32019-05-20 19:17:08 +0200338 /*
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 */
Etienne Carriere1de46d02020-02-07 13:38:30 +0100343 clk_enable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200344
Yann Gautierb76c61a2020-12-16 10:17:35 +0100345 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
Yann Gautier3edc7c32019-05-20 19:17:08 +0200346 SYSCFG_CMPENSETR_MPU_EN);
Yann Gautier4a164842020-11-17 15:27:58 +0100347#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
Yann Gautierb76c61a2020-12-16 10:17:35 +0100354}
Yann Gautier3edc7c32019-05-20 19:17:08 +0200355
Maxime Méré80d9fb42024-01-16 15:40:49 +0100356void stm32mp_syscfg_enable_io_compensation_finish(void)
Yann Gautierb76c61a2020-12-16 10:17:35 +0100357{
358 enable_io_comp_cell_finish(SYSCFG_CMPCR);
Yann Gautier4a164842020-11-17 15:27:58 +0100359#if STM32MP13
360 enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
361 enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
362#endif
Yann Gautier3edc7c32019-05-20 19:17:08 +0200363}
364
Maxime Méré80d9fb42024-01-16 15:40:49 +0100365void stm32mp_syscfg_disable_io_compensation(void)
Yann Gautier3edc7c32019-05-20 19:17:08 +0200366{
Yann Gautierb76c61a2020-12-16 10:17:35 +0100367 clk_enable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200368
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 */
Yann Gautierb76c61a2020-12-16 10:17:35 +0100375 disable_io_comp_cell(SYSCFG_CMPCR);
Yann Gautier4a164842020-11-17 15:27:58 +0100376#if STM32MP13
377 disable_io_comp_cell(SYSCFG_CMPSD1CR);
378 disable_io_comp_cell(SYSCFG_CMPSD2CR);
379#endif
Yann Gautier3edc7c32019-05-20 19:17:08 +0200380
Etienne Carriere1de46d02020-02-07 13:38:30 +0100381 clk_disable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200382}
Yann Gautierf36a1d32020-04-21 15:03:59 +0200383
384/*
385 * @brief Get silicon revision from SYSCFG registers.
386 * @retval chip version (REV_ID).
387 */
Maxime Méré80d9fb42024-01-16 15:40:49 +0100388uint32_t stm32mp_syscfg_get_chip_version(void)
Yann Gautierf36a1d32020-04-21 15:03:59 +0200389{
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 */
Maxime Méré80d9fb42024-01-16 15:40:49 +0100398uint32_t stm32mp_syscfg_get_chip_dev_id(void)
Yann Gautierf36a1d32020-04-21 15:03:59 +0200399{
400 return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
401}
Nicolas Toromanoff1877b132021-02-03 16:52:03 +0100402
403#if STM32MP13
Maxime Méré80d9fb42024-01-16 15:40:49 +0100404void stm32mp_syscfg_boot_mode_enable(void)
Nicolas Toromanoff1877b132021-02-03 16:52:03 +0100405{
406 mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
407}
408
Maxime Méré80d9fb42024-01-16 15:40:49 +0100409void stm32mp_syscfg_boot_mode_disable(void)
Nicolas Toromanoff1877b132021-02-03 16:52:03 +0100410{
411 mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
412}
413#endif