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