xref: /rk3399_ARM-atf/plat/st/stm32mp1/stm32mp1_syscfg.c (revision 1b8898eb32c3872a34fc59f4216736f23af0c6ea)
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 #define SYSCFG_IDC				0x380U
31 
32 #define CMPCR_CMPENSETR_OFFSET			0x4U
33 #define CMPCR_CMPENCLRR_OFFSET			0x8U
34 
35 /*
36  * SYSCFG_BOOTR Register
37  */
38 #define SYSCFG_BOOTR_BOOT_MASK			GENMASK(2, 0)
39 #if STM32MP15
40 #define SYSCFG_BOOTR_BOOTPD_MASK		GENMASK(6, 4)
41 #define SYSCFG_BOOTR_BOOTPD_SHIFT		4
42 #endif
43 
44 /*
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 
68 #define SYSCFG_CMPCR_READY_TIMEOUT_US		10000U
69 
70 /*
71  * SYSCFG_CMPENSETR Register
72  */
73 #define SYSCFG_CMPENSETR_MPU_EN			BIT(0)
74 
75 /*
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 
82 static 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 
99 static 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 
121 static void enable_high_speed_mode_low_voltage(void)
122 {
123 #if STM32MP15
124 	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);
130 #endif
131 }
132 
133 static void stm32mp1_syscfg_set_hslv(void)
134 {
135 	uint32_t otp_value;
136 	uint32_t vdd_voltage;
137 	bool product_below_2v5;
138 
139 	/*
140 	 * 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 	 */
154 	if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
155 		panic();
156 	}
157 
158 	product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
159 
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) {
165 		WARN("VDD unknown\n");
166 	} else if (vdd_voltage < 2700000U) {
167 		enable_high_speed_mode_low_voltage();
168 
169 		if (!product_below_2v5) {
170 			INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
171 		}
172 	} else {
173 		if (product_below_2v5) {
174 			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 	}
180 }
181 
182 void stm32mp1_syscfg_init(void)
183 {
184 #if STM32MP15
185 	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);
198 #endif
199 
200 	stm32mp1_syscfg_set_hslv();
201 
202 	stm32mp1_syscfg_enable_io_compensation_start();
203 }
204 
205 void stm32mp1_syscfg_enable_io_compensation_start(void)
206 {
207 	/*
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 	 */
212 	clk_enable(SYSCFG);
213 
214 	mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
215 			SYSCFG_CMPENSETR_MPU_EN);
216 }
217 
218 void stm32mp1_syscfg_enable_io_compensation_finish(void)
219 {
220 	enable_io_comp_cell_finish(SYSCFG_CMPCR);
221 }
222 
223 void stm32mp1_syscfg_disable_io_compensation(void)
224 {
225 	clk_enable(SYSCFG);
226 
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 	 */
233 	disable_io_comp_cell(SYSCFG_CMPCR);
234 
235 	clk_disable(SYSCFG);
236 }
237 
238 /*
239  * @brief  Get silicon revision from SYSCFG registers.
240  * @retval chip version (REV_ID).
241  */
242 uint32_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  */
252 uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
253 {
254 	return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
255 }
256