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