xref: /rk3399_ARM-atf/plat/st/stm32mp1/stm32mp1_syscfg.c (revision 8e07ab5f705b213af28831f7c3e9878154e07df0)
1 /*
2  * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <common/debug.h>
8 #include <drivers/clk.h>
9 #include <drivers/delay_timer.h>
10 #include <drivers/st/stpmic1.h>
11 #include <lib/mmio.h>
12 #include <lib/utils_def.h>
13 
14 #include <platform_def.h>
15 #include <stm32mp_common.h>
16 #include <stm32mp_dt.h>
17 #include <stm32mp1_private.h>
18 
19 /*
20  * SYSCFG REGISTER OFFSET (base relative)
21  */
22 #define SYSCFG_BOOTR				0x00U
23 #if STM32MP15
24 #define SYSCFG_IOCTRLSETR			0x18U
25 #define SYSCFG_ICNR				0x1CU
26 #endif
27 #define SYSCFG_CMPCR				0x20U
28 #define SYSCFG_CMPENSETR			0x24U
29 #define SYSCFG_CMPENCLRR			0x28U
30 #if STM32MP13
31 #define SYSCFG_CMPSD1CR				0x30U
32 #define SYSCFG_CMPSD1ENSETR			0x34U
33 #define SYSCFG_CMPSD1ENCLRR			0x38U
34 #define SYSCFG_CMPSD2CR				0x40U
35 #define SYSCFG_CMPSD2ENSETR			0x44U
36 #define SYSCFG_CMPSD2ENCLRR			0x48U
37 #endif
38 #define SYSCFG_IDC				0x380U
39 
40 #define CMPCR_CMPENSETR_OFFSET			0x4U
41 #define CMPCR_CMPENCLRR_OFFSET			0x8U
42 
43 /*
44  * SYSCFG_BOOTR Register
45  */
46 #define SYSCFG_BOOTR_BOOT_MASK			GENMASK(2, 0)
47 #if STM32MP15
48 #define SYSCFG_BOOTR_BOOTPD_MASK		GENMASK(6, 4)
49 #define SYSCFG_BOOTR_BOOTPD_SHIFT		4
50 #endif
51 
52 /*
53  * SYSCFG_IOCTRLSETR Register
54  */
55 #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE		BIT(0)
56 #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI	BIT(1)
57 #define SYSCFG_IOCTRLSETR_HSLVEN_ETH		BIT(2)
58 #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC		BIT(3)
59 #define SYSCFG_IOCTRLSETR_HSLVEN_SPI		BIT(4)
60 
61 /*
62  * SYSCFG_ICNR Register
63  */
64 #define SYSCFG_ICNR_AXI_M9			BIT(9)
65 
66 /*
67  * SYSCFG_CMPCR Register
68  */
69 #define SYSCFG_CMPCR_SW_CTRL			BIT(1)
70 #define SYSCFG_CMPCR_READY			BIT(8)
71 #define SYSCFG_CMPCR_RANSRC			GENMASK(19, 16)
72 #define SYSCFG_CMPCR_RANSRC_SHIFT		16
73 #define SYSCFG_CMPCR_RAPSRC			GENMASK(23, 20)
74 #define SYSCFG_CMPCR_ANSRC_SHIFT		24
75 
76 #define SYSCFG_CMPCR_READY_TIMEOUT_US		10000U
77 
78 /*
79  * SYSCFG_CMPENSETR Register
80  */
81 #define SYSCFG_CMPENSETR_MPU_EN			BIT(0)
82 
83 /*
84  * SYSCFG_IDC Register
85  */
86 #define SYSCFG_IDC_DEV_ID_MASK			GENMASK(11, 0)
87 #define SYSCFG_IDC_REV_ID_MASK			GENMASK(31, 16)
88 #define SYSCFG_IDC_REV_ID_SHIFT			16
89 
90 static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
91 {
92 	uint64_t start;
93 
94 	start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
95 
96 	while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
97 		if (timeout_elapsed(start)) {
98 			/* Failure on IO compensation enable is not a issue: warn only. */
99 			WARN("IO compensation cell not ready\n");
100 			break;
101 		}
102 	}
103 
104 	mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
105 }
106 
107 static void disable_io_comp_cell(uintptr_t cmpcr_off)
108 {
109 	uint32_t value;
110 
111 	if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
112 	    ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
113 	     SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
114 		return;
115 	}
116 
117 	value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
118 
119 	mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
120 
121 	value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
122 	value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
123 
124 	mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
125 
126 	mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
127 }
128 
129 static void enable_high_speed_mode_low_voltage(void)
130 {
131 #if STM32MP15
132 	mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
133 		      SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
134 		      SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
135 		      SYSCFG_IOCTRLSETR_HSLVEN_ETH |
136 		      SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
137 		      SYSCFG_IOCTRLSETR_HSLVEN_SPI);
138 #endif
139 }
140 
141 static void stm32mp1_syscfg_set_hslv(void)
142 {
143 	uint32_t otp_value;
144 	uint32_t vdd_voltage;
145 	bool product_below_2v5;
146 
147 	/*
148 	 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
149 	 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
150 	 * It could be disabled for low frequencies or if AFMUX is selected
151 	 * but the function is not used, typically for TRACE.
152 	 * If high speed low voltage pad mode is node enable, platform will
153 	 * over consume.
154 	 *
155 	 * WARNING:
156 	 *   Enabling High Speed mode while VDD > 2.7V
157 	 *   with the OTP product_below_2v5 (OTP 18, BIT 13)
158 	 *   erroneously set to 1 can damage the SoC!
159 	 *   => TF-A enables the low power mode only if VDD < 2.7V (in DT)
160 	 *      but this value needs to be consistent with board design.
161 	 */
162 	if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
163 		panic();
164 	}
165 
166 	product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
167 
168 	/* Get VDD supply */
169 	vdd_voltage = dt_get_pwr_vdd_voltage();
170 
171 	/* Check if VDD is Low Voltage */
172 	if (vdd_voltage == 0U) {
173 		WARN("VDD unknown\n");
174 	} else if (vdd_voltage < 2700000U) {
175 		enable_high_speed_mode_low_voltage();
176 
177 		if (!product_below_2v5) {
178 			INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
179 		}
180 	} else {
181 		if (product_below_2v5) {
182 			ERROR("Product_below_2v5=1:\n");
183 			ERROR("\tHSLVEN update is destructive,\n");
184 			ERROR("\tno update as VDD > 2.7V\n");
185 			panic();
186 		}
187 	}
188 }
189 
190 void stm32mp1_syscfg_init(void)
191 {
192 #if STM32MP15
193 	uint32_t bootr;
194 
195 	/*
196 	 * Interconnect update : select master using the port 1.
197 	 * LTDC = AXI_M9.
198 	 */
199 	mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
200 
201 	/* Disable Pull-Down for boot pin connected to VDD */
202 	bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
203 		SYSCFG_BOOTR_BOOT_MASK;
204 	mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
205 			   bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
206 #endif
207 
208 	stm32mp1_syscfg_set_hslv();
209 
210 	stm32mp1_syscfg_enable_io_compensation_start();
211 }
212 
213 void stm32mp1_syscfg_enable_io_compensation_start(void)
214 {
215 	/*
216 	 * Activate automatic I/O compensation.
217 	 * Warning: need to ensure CSI enabled and ready in clock driver.
218 	 * Enable non-secure clock, we assume non-secure is suspended.
219 	 */
220 	clk_enable(SYSCFG);
221 
222 	mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
223 			SYSCFG_CMPENSETR_MPU_EN);
224 #if STM32MP13
225 	mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
226 			SYSCFG_CMPENSETR_MPU_EN);
227 	mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
228 			SYSCFG_CMPENSETR_MPU_EN);
229 
230 #endif
231 }
232 
233 void stm32mp1_syscfg_enable_io_compensation_finish(void)
234 {
235 	enable_io_comp_cell_finish(SYSCFG_CMPCR);
236 #if STM32MP13
237 	enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
238 	enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
239 #endif
240 }
241 
242 void stm32mp1_syscfg_disable_io_compensation(void)
243 {
244 	clk_enable(SYSCFG);
245 
246 	/*
247 	 * Deactivate automatic I/O compensation.
248 	 * Warning: CSI is disabled automatically in STOP if not
249 	 * requested for other usages and always OFF in STANDBY.
250 	 * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
251 	 */
252 	disable_io_comp_cell(SYSCFG_CMPCR);
253 #if STM32MP13
254 	disable_io_comp_cell(SYSCFG_CMPSD1CR);
255 	disable_io_comp_cell(SYSCFG_CMPSD2CR);
256 #endif
257 
258 	clk_disable(SYSCFG);
259 }
260 
261 /*
262  * @brief  Get silicon revision from SYSCFG registers.
263  * @retval chip version (REV_ID).
264  */
265 uint32_t stm32mp1_syscfg_get_chip_version(void)
266 {
267 	return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
268 		SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
269 }
270 
271 /*
272  * @brief  Get device ID from SYSCFG registers.
273  * @retval device ID (DEV_ID).
274  */
275 uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
276 {
277 	return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
278 }
279