stm32mp1: add syscfg initialization
authorPatrick Delaunay <patrick.delaunay@st.com>
Wed, 27 Feb 2019 16:01:24 +0000 (17:01 +0100)
committerPatrick Delaunay <patrick.delaunay@st.com>
Fri, 12 Apr 2019 14:09:13 +0000 (16:09 +0200)
Initialize the system configuration for basic boot
- update interconnect setting
- disable pull-down for boot pin
- enable High Speed Low Voltage Pad mode for SPI, SDMMC, ETH, QSPI
- activate I/O compensation

Done by SSBL = TF-A for trusted boot

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
board/st/stm32mp1/stm32mp1.c

index d13793ed6a945492af4998ab9ef7fc2a354476b2..282918089b508cf325c117d29102e7ad6b76266e 100644 (file)
 #include <misc.h>
 #include <phy.h>
 #include <reset.h>
+#include <syscon.h>
 #include <usb.h>
-#include <asm/arch/stm32.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
+#include <asm/arch/stm32.h>
 #include <power/regulator.h>
 #include <usb/dwc2_udc.h>
 
+/* SYSCFG registers */
+#define SYSCFG_BOOTR           0x00
+#define SYSCFG_PMCSETR         0x04
+#define SYSCFG_IOCTRLSETR      0x18
+#define SYSCFG_ICNR            0x1C
+#define SYSCFG_CMPCR           0x20
+#define SYSCFG_CMPENSETR       0x24
+#define SYSCFG_PMCCLRR         0x44
+
+#define SYSCFG_BOOTR_BOOT_MASK         GENMASK(2, 0)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT      4
+
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE         BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI       BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH           BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC         BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI           BIT(4)
+
+#define SYSCFG_CMPCR_SW_CTRL           BIT(1)
+#define SYSCFG_CMPCR_READY             BIT(8)
+
+#define SYSCFG_CMPENSETR_MPU_EN                BIT(0)
+
+#define SYSCFG_PMCSETR_ETH_CLK_SEL     BIT(16)
+#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
+
+#define SYSCFG_PMCSETR_ETH_SELMII      BIT(20)
+
+#define SYSCFG_PMCSETR_ETH_SEL_MASK    GENMASK(23, 21)
+#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII        (0 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_RGMII   (1 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_RMII    (4 << 21)
+
 /*
  * Get a global data pointer
  */
@@ -270,6 +304,98 @@ int board_usb_cleanup(int index, enum usb_init_type init)
        return 0;
 }
 
+static void sysconf_init(void)
+{
+#ifndef CONFIG_STM32MP1_TRUSTED
+       u8 *syscfg;
+#ifdef CONFIG_DM_REGULATOR
+       struct udevice *pwr_dev;
+       struct udevice *pwr_reg;
+       struct udevice *dev;
+       int ret;
+       u32 otp = 0;
+#endif
+       u32 bootr;
+
+       syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+       /* interconnect update : select master using the port 1 */
+       /* LTDC = AXI_M9 */
+       /* GPU  = AXI_M8 */
+       /* today information is hardcoded in U-Boot */
+       writel(BIT(9), syscfg + SYSCFG_ICNR);
+
+       /* disable Pull-Down for boot pin connected to VDD */
+       bootr = readl(syscfg + SYSCFG_BOOTR);
+       bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
+       bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
+       writel(bootr, syscfg + SYSCFG_BOOTR);
+
+#ifdef CONFIG_DM_REGULATOR
+       /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+        * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+        * The customer will have to disable this for low frequencies
+        * or if AFMUX is selected but the function not used, typically for
+        * TRACE. Otherwise, impact on power consumption.
+        *
+        * WARNING:
+        *   enabling High Speed mode while VDD>2.7V
+        *   with the OTP product_below_2v5 (OTP 18, BIT 13)
+        *   erroneously set to 1 can damage the IC!
+        *   => U-Boot set the register only if VDD < 2.7V (in DT)
+        *      but this value need to be consistent with board design
+        */
+       ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev);
+       if (!ret) {
+               ret = uclass_get_device_by_driver(UCLASS_MISC,
+                                                 DM_GET_DRIVER(stm32mp_bsec),
+                                                 &dev);
+               if (ret) {
+                       pr_err("Can't find stm32mp_bsec driver\n");
+                       return;
+               }
+
+               ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
+               if (!ret)
+                       otp = otp & BIT(13);
+
+               /* get VDD = pwr-supply */
+               ret = device_get_supply_regulator(pwr_dev, "pwr-supply",
+                                                 &pwr_reg);
+
+               /* check if VDD is Low Voltage */
+               if (!ret) {
+                       if (regulator_get_value(pwr_reg) < 2700000) {
+                               writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+                                      SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+                                      SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+                                      SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+                                      SYSCFG_IOCTRLSETR_HSLVEN_SPI,
+                                      syscfg + SYSCFG_IOCTRLSETR);
+
+                               if (!otp)
+                                       pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
+                       } else {
+                               if (otp)
+                                       pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
+                       }
+               } else {
+                       debug("VDD unknown");
+               }
+       }
+#endif
+
+       /* activate automatic I/O compensation
+        * warning: need to ensure CSI enabled and ready in clock driver
+        */
+       writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
+
+       while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
+               ;
+       clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
+#endif
+}
+
 /* board dependent setup after realloc */
 int board_init(void)
 {
@@ -278,6 +404,8 @@ int board_init(void)
 
        board_key_check();
 
+       sysconf_init();
+
        if (IS_ENABLED(CONFIG_LED))
                led_default_state();