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