blob: 1aabe65ba343ecc01eb7b70116e74f40a30a05f0 [file] [log] [blame]
Yann Gautier3edc7c32019-05-20 19:17:08 +02001/*
Nicolas Le Bayon36898692019-11-18 17:18:06 +01002 * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
Yann Gautier3edc7c32019-05-20 19:17:08 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautier3edc7c32019-05-20 19:17:08 +02007#include <common/debug.h>
Etienne Carriere1de46d02020-02-07 13:38:30 +01008#include <drivers/clk.h>
Nicolas Le Bayon36898692019-11-18 17:18:06 +01009#include <drivers/delay_timer.h>
Yann Gautier3edc7c32019-05-20 19:17:08 +020010#include <drivers/st/stpmic1.h>
11#include <lib/mmio.h>
Yann Gautierf36a1d32020-04-21 15:03:59 +020012#include <lib/utils_def.h>
Yann Gautier3edc7c32019-05-20 19:17:08 +020013
Nicolas Le Bayon36898692019-11-18 17:18:06 +010014#include <platform_def.h>
Lionel Debievebc2d88d2019-11-04 14:31:38 +010015#include <stm32mp_common.h>
Yann Gautier3edc7c32019-05-20 19:17:08 +020016#include <stm32mp_dt.h>
17#include <stm32mp1_private.h>
18
19/*
20 * SYSCFG REGISTER OFFSET (base relative)
21 */
22#define SYSCFG_BOOTR 0x00U
Yann Gautiercc5f89a2020-02-12 09:36:23 +010023#if STM32MP15
Yann Gautier3edc7c32019-05-20 19:17:08 +020024#define SYSCFG_IOCTRLSETR 0x18U
25#define SYSCFG_ICNR 0x1CU
Yann Gautiercc5f89a2020-02-12 09:36:23 +010026#endif
Yann Gautier3edc7c32019-05-20 19:17:08 +020027#define SYSCFG_CMPCR 0x20U
28#define SYSCFG_CMPENSETR 0x24U
Yann Gautier0315fa02020-10-26 15:21:25 +010029#define SYSCFG_CMPENCLRR 0x28U
Yann Gautierf36a1d32020-04-21 15:03:59 +020030#define SYSCFG_IDC 0x380U
Yann Gautier3edc7c32019-05-20 19:17:08 +020031
Yann Gautierb76c61a2020-12-16 10:17:35 +010032#define CMPCR_CMPENSETR_OFFSET 0x4U
33#define CMPCR_CMPENCLRR_OFFSET 0x8U
34
Yann Gautier3edc7c32019-05-20 19:17:08 +020035/*
36 * SYSCFG_BOOTR Register
37 */
38#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
Yann Gautiercc5f89a2020-02-12 09:36:23 +010039#if STM32MP15
Yann Gautier3edc7c32019-05-20 19:17:08 +020040#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
41#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
Yann Gautiercc5f89a2020-02-12 09:36:23 +010042#endif
43
Yann Gautier3edc7c32019-05-20 19:17:08 +020044/*
45 * SYSCFG_IOCTRLSETR Register
46 */
47#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
48#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
49#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
50#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
51#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
52
53/*
54 * SYSCFG_ICNR Register
55 */
56#define SYSCFG_ICNR_AXI_M9 BIT(9)
57
58/*
59 * SYSCFG_CMPCR Register
60 */
61#define SYSCFG_CMPCR_SW_CTRL BIT(1)
62#define SYSCFG_CMPCR_READY BIT(8)
63#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
64#define SYSCFG_CMPCR_RANSRC_SHIFT 16
65#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
66#define SYSCFG_CMPCR_ANSRC_SHIFT 24
67
Nicolas Le Bayon36898692019-11-18 17:18:06 +010068#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
69
Yann Gautier3edc7c32019-05-20 19:17:08 +020070/*
71 * SYSCFG_CMPENSETR Register
72 */
73#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
74
Yann Gautierf36a1d32020-04-21 15:03:59 +020075/*
76 * SYSCFG_IDC Register
77 */
78#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
79#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
80#define SYSCFG_IDC_REV_ID_SHIFT 16
81
Yann Gautierb76c61a2020-12-16 10:17:35 +010082static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
83{
84 uint64_t start;
85
86 start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
87
88 while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
89 if (timeout_elapsed(start)) {
90 /* Failure on IO compensation enable is not a issue: warn only. */
91 WARN("IO compensation cell not ready\n");
92 break;
93 }
94 }
95
96 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
97}
98
99static void disable_io_comp_cell(uintptr_t cmpcr_off)
100{
101 uint32_t value;
102
103 if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
104 ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
105 SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
106 return;
107 }
108
109 value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
110
111 mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
112
113 value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
114 value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
115
116 mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
117
118 mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
119}
120
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100121static void enable_high_speed_mode_low_voltage(void)
Yann Gautier3edc7c32019-05-20 19:17:08 +0200122{
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100123#if STM32MP15
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100124 mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
125 SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
126 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
127 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
128 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
129 SYSCFG_IOCTRLSETR_HSLVEN_SPI);
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100130#endif
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100131}
132
133static void stm32mp1_syscfg_set_hslv(void)
134{
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100135 uint32_t otp_value;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200136 uint32_t vdd_voltage;
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100137 bool product_below_2v5;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200138
139 /*
Yann Gautier3edc7c32019-05-20 19:17:08 +0200140 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
141 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
142 * It could be disabled for low frequencies or if AFMUX is selected
143 * but the function is not used, typically for TRACE.
144 * If high speed low voltage pad mode is node enable, platform will
145 * over consume.
146 *
147 * WARNING:
148 * Enabling High Speed mode while VDD > 2.7V
149 * with the OTP product_below_2v5 (OTP 18, BIT 13)
150 * erroneously set to 1 can damage the SoC!
151 * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
152 * but this value needs to be consistent with board design.
153 */
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100154 if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200155 panic();
156 }
157
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100158 product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
Yann Gautier3edc7c32019-05-20 19:17:08 +0200159
160 /* Get VDD supply */
161 vdd_voltage = dt_get_pwr_vdd_voltage();
162
163 /* Check if VDD is Low Voltage */
164 if (vdd_voltage == 0U) {
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100165 WARN("VDD unknown\n");
Yann Gautier3edc7c32019-05-20 19:17:08 +0200166 } else if (vdd_voltage < 2700000U) {
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100167 enable_high_speed_mode_low_voltage();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200168
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100169 if (!product_below_2v5) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200170 INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
171 }
172 } else {
Lionel Debievebc2d88d2019-11-04 14:31:38 +0100173 if (product_below_2v5) {
Yann Gautier3edc7c32019-05-20 19:17:08 +0200174 ERROR("Product_below_2v5=1:\n");
175 ERROR("\tHSLVEN update is destructive,\n");
176 ERROR("\tno update as VDD > 2.7V\n");
177 panic();
178 }
179 }
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100180}
181
182void stm32mp1_syscfg_init(void)
183{
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100184#if STM32MP15
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100185 uint32_t bootr;
186
187 /*
188 * Interconnect update : select master using the port 1.
189 * LTDC = AXI_M9.
190 */
191 mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
192
193 /* Disable Pull-Down for boot pin connected to VDD */
194 bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
195 SYSCFG_BOOTR_BOOT_MASK;
196 mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
197 bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
Yann Gautiercc5f89a2020-02-12 09:36:23 +0100198#endif
Yann Gautiere0a60cb2021-01-12 14:45:02 +0100199
200 stm32mp1_syscfg_set_hslv();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200201
Yann Gautierb76c61a2020-12-16 10:17:35 +0100202 stm32mp1_syscfg_enable_io_compensation_start();
Yann Gautier3edc7c32019-05-20 19:17:08 +0200203}
204
Yann Gautierb76c61a2020-12-16 10:17:35 +0100205void stm32mp1_syscfg_enable_io_compensation_start(void)
Yann Gautier3edc7c32019-05-20 19:17:08 +0200206{
Yann Gautier3edc7c32019-05-20 19:17:08 +0200207 /*
208 * Activate automatic I/O compensation.
209 * Warning: need to ensure CSI enabled and ready in clock driver.
210 * Enable non-secure clock, we assume non-secure is suspended.
211 */
Etienne Carriere1de46d02020-02-07 13:38:30 +0100212 clk_enable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200213
Yann Gautierb76c61a2020-12-16 10:17:35 +0100214 mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
Yann Gautier3edc7c32019-05-20 19:17:08 +0200215 SYSCFG_CMPENSETR_MPU_EN);
Yann Gautierb76c61a2020-12-16 10:17:35 +0100216}
Yann Gautier3edc7c32019-05-20 19:17:08 +0200217
Yann Gautierb76c61a2020-12-16 10:17:35 +0100218void stm32mp1_syscfg_enable_io_compensation_finish(void)
219{
220 enable_io_comp_cell_finish(SYSCFG_CMPCR);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200221}
222
223void stm32mp1_syscfg_disable_io_compensation(void)
224{
Yann Gautierb76c61a2020-12-16 10:17:35 +0100225 clk_enable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200226
227 /*
228 * Deactivate automatic I/O compensation.
229 * Warning: CSI is disabled automatically in STOP if not
230 * requested for other usages and always OFF in STANDBY.
231 * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
232 */
Yann Gautierb76c61a2020-12-16 10:17:35 +0100233 disable_io_comp_cell(SYSCFG_CMPCR);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200234
Etienne Carriere1de46d02020-02-07 13:38:30 +0100235 clk_disable(SYSCFG);
Yann Gautier3edc7c32019-05-20 19:17:08 +0200236}
Yann Gautierf36a1d32020-04-21 15:03:59 +0200237
238/*
239 * @brief Get silicon revision from SYSCFG registers.
240 * @retval chip version (REV_ID).
241 */
242uint32_t stm32mp1_syscfg_get_chip_version(void)
243{
244 return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
245 SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
246}
247
248/*
249 * @brief Get device ID from SYSCFG registers.
250 * @retval device ID (DEV_ID).
251 */
252uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
253{
254 return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
255}