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