return fdt32_to_cpu(*cuint);
}
+/*******************************************************************************
+ * This function gets PWR VDD regulator voltage information from the DT.
+ * Returns value in microvolts on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t dt_get_pwr_vdd_voltage(void)
+{
+ int node, pwr_regulators_node;
+ const fdt32_t *cuint;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read PWR node in DT\n", __func__);
+ return 0;
+ }
+
+ pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
+ if (node < 0) {
+ INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (node < 0) {
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets SYSCFG base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_syscfg_base(void)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read SYSCFG node in DT\n", __func__);
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
/*******************************************************************************
* This function retrieves board model from DT
* Returns string taken from model node, NULL otherwise
--- /dev/null
+/*
+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stpmic1.h>
+#include <lib/mmio.h>
+
+#include <stm32mp_dt.h>
+#include <stm32mp1_private.h>
+
+/*
+ * SYSCFG REGISTER OFFSET (base relative)
+ */
+#define SYSCFG_BOOTR 0x00U
+#define SYSCFG_IOCTRLSETR 0x18U
+#define SYSCFG_ICNR 0x1CU
+#define SYSCFG_CMPCR 0x20U
+#define SYSCFG_CMPENSETR 0x24U
+
+/*
+ * SYSCFG_BOOTR Register
+ */
+#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
+#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
+/*
+ * SYSCFG_IOCTRLSETR Register
+ */
+#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)
+
+/*
+ * SYSCFG_ICNR Register
+ */
+#define SYSCFG_ICNR_AXI_M9 BIT(9)
+
+/*
+ * SYSCFG_CMPCR Register
+ */
+#define SYSCFG_CMPCR_SW_CTRL BIT(1)
+#define SYSCFG_CMPCR_READY BIT(8)
+#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
+#define SYSCFG_CMPCR_RANSRC_SHIFT 16
+#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
+#define SYSCFG_CMPCR_ANSRC_SHIFT 24
+
+/*
+ * SYSCFG_CMPENSETR Register
+ */
+#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
+
+void stm32mp1_syscfg_init(void)
+{
+ uint32_t bootr;
+ uint32_t otp = 0;
+ uint32_t vdd_voltage;
+ uintptr_t syscfg_base = dt_get_syscfg_base();
+
+ /*
+ * Interconnect update : select master using the port 1.
+ * LTDC = AXI_M9.
+ */
+ mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
+
+ /* Disable Pull-Down for boot pin connected to VDD */
+ bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR) &
+ SYSCFG_BOOTR_BOOT_MASK;
+ mmio_clrsetbits_32(syscfg_base + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
+ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
+
+ /*
+ * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+ * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+ * It could be disabled for low frequencies or if AFMUX is selected
+ * but the function is not used, typically for TRACE.
+ * If high speed low voltage pad mode is node enable, platform will
+ * over consume.
+ *
+ * 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 SoC!
+ * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
+ * but this value needs to be consistent with board design.
+ */
+ if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) {
+ panic();
+ }
+
+ otp = otp & HW2_OTP_PRODUCT_BELOW_2V5;
+
+ /* Get VDD supply */
+ vdd_voltage = dt_get_pwr_vdd_voltage();
+
+ /* Check if VDD is Low Voltage */
+ if (vdd_voltage == 0U) {
+ WARN("VDD unknown");
+ } else if (vdd_voltage < 2700000U) {
+ mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR,
+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+ SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+ SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+
+ if (otp == 0U) {
+ INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
+ }
+ } else {
+ if (otp != 0U) {
+ ERROR("Product_below_2v5=1:\n");
+ ERROR("\tHSLVEN update is destructive,\n");
+ ERROR("\tno update as VDD > 2.7V\n");
+ panic();
+ }
+ }
+
+ stm32mp1_syscfg_enable_io_compensation();
+}
+
+void stm32mp1_syscfg_enable_io_compensation(void)
+{
+ uintptr_t syscfg_base = dt_get_syscfg_base();
+
+ /*
+ * Activate automatic I/O compensation.
+ * Warning: need to ensure CSI enabled and ready in clock driver.
+ * Enable non-secure clock, we assume non-secure is suspended.
+ */
+ stm32mp1_clk_enable_non_secure(SYSCFG);
+
+ mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR,
+ SYSCFG_CMPENSETR_MPU_EN);
+
+ while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) &
+ SYSCFG_CMPCR_READY) == 0U) {
+ ;
+ }
+
+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
+}
+
+void stm32mp1_syscfg_disable_io_compensation(void)
+{
+ uintptr_t syscfg_base = dt_get_syscfg_base();
+ uint32_t value;
+
+ /*
+ * Deactivate automatic I/O compensation.
+ * Warning: CSI is disabled automatically in STOP if not
+ * requested for other usages and always OFF in STANDBY.
+ * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
+ */
+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >>
+ SYSCFG_CMPCR_ANSRC_SHIFT;
+
+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR,
+ SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+
+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) |
+ (value << SYSCFG_CMPCR_RANSRC_SHIFT);
+
+ mmio_write_32(syscfg_base + SYSCFG_CMPCR, value);
+
+ mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
+
+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR,
+ SYSCFG_CMPENSETR_MPU_EN);
+
+ stm32mp1_clk_disable_non_secure(SYSCFG);
+}