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