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