7088 lines
199 KiB
Diff
7088 lines
199 KiB
Diff
From 801e39ee5f7ecfc1cb4505d2fef5858c486571a5 Mon Sep 17 00:00:00 2001
|
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
|
Date: Wed, 29 Jan 2020 14:25:17 +0100
|
|
Subject: [PATCH] st update r1.2.0
|
|
|
|
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
|
|
---
|
|
docs/devicetree/bindings/power/st,stpmic1.txt | 38 --
|
|
docs/devicetree/bindings/soc/st,stm32-romem.txt | 43 ++
|
|
drivers/mmc/mmc.c | 69 ++-
|
|
drivers/st/bsec/bsec.c | 129 ++++-
|
|
drivers/st/clk/stm32mp1_calib.c | 4 +-
|
|
drivers/st/clk/stm32mp1_clk.c | 680 ++++++++++++++++++++++--
|
|
drivers/st/clk/stm32mp1_clkfunc.c | 19 +-
|
|
drivers/st/clk/stm32mp_clkfunc.c | 121 +----
|
|
drivers/st/ddr/stm32mp1_ddr.c | 11 +-
|
|
drivers/st/ddr/stm32mp1_ddr_helpers.c | 26 +-
|
|
drivers/st/ddr/stm32mp1_ram.c | 18 +-
|
|
drivers/st/etzpc/etzpc.c | 6 +-
|
|
drivers/st/gpio/stm32_gpio.c | 6 +-
|
|
drivers/st/i2c/stm32_i2c.c | 165 +++---
|
|
drivers/st/io/io_programmer_st_usb.c | 8 +-
|
|
drivers/st/io/io_stm32image.c | 4 +-
|
|
drivers/st/iwdg/stm32_iwdg.c | 6 +-
|
|
drivers/st/mmc/stm32_sdmmc2.c | 96 ++--
|
|
drivers/st/nand/nand.c | 15 +-
|
|
drivers/st/pmic/stm32mp_pmic.c | 472 ++++++++++------
|
|
drivers/st/pmic/stpmic1.c | 20 +-
|
|
drivers/st/qspi/io_qspi.c | 4 +-
|
|
drivers/st/regulator/stm32mp_dummy_regulator.c | 27 +
|
|
drivers/st/regulator/stm32mp_regulator.c | 38 ++
|
|
drivers/st/reset/stm32mp1_reset.c | 3 +-
|
|
drivers/st/rng/stm32_rng.c | 3 +-
|
|
drivers/st/rtc/stm32_rtc.c | 42 +-
|
|
drivers/st/tamper/stm32_tamp.c | 4 +-
|
|
drivers/st/timer/stm32_timer.c | 3 +-
|
|
drivers/st/uart/io_programmer_uart.c | 5 +-
|
|
fdts/stm32mp15-ddr.dtsi | 2 +-
|
|
fdts/stm32mp157a-dk1.dts | 33 +-
|
|
fdts/stm32mp157c-ed1.dts | 33 +-
|
|
fdts/stm32mp157c-security.dtsi | 51 +-
|
|
fdts/stm32mp157c.dtsi | 17 +
|
|
include/drivers/mmc.h | 27 +-
|
|
include/drivers/st/bsec.h | 5 +-
|
|
include/drivers/st/stm32_i2c.h | 20 +-
|
|
include/drivers/st/stm32_sdmmc2.h | 2 +
|
|
include/drivers/st/stm32mp1_clk.h | 22 +-
|
|
include/drivers/st/stm32mp1_ddr_regs.h | 4 +-
|
|
include/drivers/st/stm32mp_clkfunc.h | 7 +-
|
|
include/drivers/st/stm32mp_dummy_regulator.h | 14 +
|
|
include/drivers/st/stm32mp_pmic.h | 17 +-
|
|
include/drivers/st/stm32mp_regulator.h | 31 ++
|
|
include/drivers/st/stpmic1.h | 24 +-
|
|
lib/usb/usb_st_dfu.c | 2 +-
|
|
plat/st/common/bl2_io_storage.c | 112 +---
|
|
plat/st/common/include/stm32mp_common.h | 11 +-
|
|
plat/st/common/include/stm32mp_dt.h | 7 +
|
|
plat/st/common/stm32mp_common.c | 8 +-
|
|
plat/st/common/stm32mp_dt.c | 272 ++++++++--
|
|
plat/st/stm32mp1/bl2_plat_setup.c | 183 +++++--
|
|
plat/st/stm32mp1/include/stm32mp1_context.h | 3 +
|
|
plat/st/stm32mp1/include/stm32mp1_dbgmcu.h | 10 +-
|
|
plat/st/stm32mp1/include/stm32mp1_smc.h | 143 ++++-
|
|
plat/st/stm32mp1/plat_image_load.c | 41 +-
|
|
plat/st/stm32mp1/platform.mk | 17 +-
|
|
plat/st/stm32mp1/services/bsec_svc.c | 20 +-
|
|
plat/st/stm32mp1/services/rcc_svc.c | 34 +-
|
|
plat/st/stm32mp1/services/rcc_svc.h | 4 +-
|
|
plat/st/stm32mp1/services/stm32mp1_svc_setup.c | 10 +-
|
|
plat/st/stm32mp1/sp_min/sp_min_setup.c | 26 +
|
|
plat/st/stm32mp1/stm32mp1_context.c | 91 +++-
|
|
plat/st/stm32mp1/stm32mp1_dbgmcu.c | 72 ++-
|
|
plat/st/stm32mp1/stm32mp1_def.h | 76 ++-
|
|
plat/st/stm32mp1/stm32mp1_helper_dbg.S | 10 +-
|
|
plat/st/stm32mp1/stm32mp1_low_power.c | 18 +-
|
|
plat/st/stm32mp1/stm32mp1_pm.c | 12 +-
|
|
plat/st/stm32mp1/stm32mp1_power_config.c | 9 +-
|
|
plat/st/stm32mp1/stm32mp1_private.c | 271 +++++++---
|
|
plat/st/stm32mp1/stm32mp1_security.c | 22 +-
|
|
plat/st/stm32mp1/stm32mp1_syscfg.c | 33 +-
|
|
plat/st/stm32mp1/stm32mp1_usb_desc.c | 22 +-
|
|
tools/stm32image/stm32image.c | 18 +-
|
|
75 files changed, 2854 insertions(+), 1097 deletions(-)
|
|
create mode 100644 drivers/st/regulator/stm32mp_dummy_regulator.c
|
|
create mode 100644 drivers/st/regulator/stm32mp_regulator.c
|
|
create mode 100644 include/drivers/st/stm32mp_dummy_regulator.h
|
|
create mode 100644 include/drivers/st/stm32mp_regulator.h
|
|
|
|
diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt
|
|
index 54b64e2..83307d2 100644
|
|
--- a/docs/devicetree/bindings/power/st,stpmic1.txt
|
|
+++ b/docs/devicetree/bindings/power/st,stpmic1.txt
|
|
@@ -45,43 +45,6 @@ Required parent device properties:
|
|
IT_TWARN_R=30
|
|
IT_TWARN_F=31
|
|
|
|
-Optional parent device properties:
|
|
-- st,main-control-register:
|
|
- -bit 1: Power cycling will be performed on turn OFF condition
|
|
- -bit 2: PWRCTRL is functional
|
|
- -bit 3: PWRCTRL active high
|
|
-- st,pads-pull-register:
|
|
- -bit 1: WAKEUP pull down is not active
|
|
- -bit 2: PWRCTRL pull up is active
|
|
- -bit 3: PWRCTRL pull down is active
|
|
- -bit 4: WAKEUP detector is disabled
|
|
-- st,vin-control-register:
|
|
- -bit 0: VINLOW monitoring is enabled
|
|
- -bit [1...3]: VINLOW rising threshold
|
|
- 000 VINOK_f + 50mV
|
|
- 001 VINOK_f + 100mV
|
|
- 010 VINOK_f + 150mV
|
|
- 011 VINOK_f + 200mV
|
|
- 100 VINOK_f + 250mV
|
|
- 101 VINOK_f + 300mV
|
|
- 110 VINOK_f + 350mV
|
|
- 111 VINOK_f + 400mV
|
|
- -bit [4...5]: VINLOW hyst
|
|
- 00 100mV
|
|
- 01 200mV
|
|
- 10 300mV
|
|
- 11 400mV
|
|
- -bit 6: SW_OUT detector is disabled
|
|
- -bit 7: SW_IN detector is enabled.
|
|
-- st,usb-control-register:
|
|
- -bit 3: SW_OUT current limit
|
|
- 0: 600mA
|
|
- 1: 1.1A
|
|
- -bit 4: VBUS_OTG discharge is enabled
|
|
- -bit 5: SW_OUT discharge is enabled
|
|
- -bit 6: VBUS_OTG detection is enabled
|
|
- -bit 7: BOOST_OVP is disabled
|
|
-
|
|
STPMIC1 consists in a varied group of sub-devices.
|
|
Each sub-device binding is be described in own documentation file.
|
|
|
|
@@ -98,7 +61,6 @@ pmic: pmic@33 {
|
|
reg = <0x33>;
|
|
interrupt-parent = <&gpioa>;
|
|
interrupts = <0 2>;
|
|
- st,main-control-register=<0x0c>;
|
|
interrupt-controller;
|
|
#interrupt-cells = <2>;
|
|
|
|
diff --git a/docs/devicetree/bindings/soc/st,stm32-romem.txt b/docs/devicetree/bindings/soc/st,stm32-romem.txt
|
|
index fbff52e..c430fb8 100644
|
|
--- a/docs/devicetree/bindings/soc/st,stm32-romem.txt
|
|
+++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt
|
|
@@ -16,6 +16,12 @@ Required properties:
|
|
Optional Data cells:
|
|
- Must be child nodes as described in nvmem.txt.
|
|
|
|
+Optional-properties:
|
|
+- "st,non-secure-otp" specifies that the OTP can be accessed by non-secure
|
|
+ world through secure world services. Only useful for upper OTPs. This
|
|
+ property mandates 32-bit granularity of the related nvmem area, that is
|
|
+ offset and length are both multiple of 4.
|
|
+
|
|
Example on stm32f4:
|
|
romem: nvmem@1fff7800 {
|
|
compatible = "st,stm32-romem";
|
|
@@ -29,3 +35,40 @@ Example on stm32f4:
|
|
};
|
|
...
|
|
};
|
|
+
|
|
+Example on stm32mp1:
|
|
+ bsec: nvmem@5c005000 {
|
|
+ ...
|
|
+ mac_addr: mac_addr@e4 {
|
|
+ reg = <0xe4 0x8>;
|
|
+ st,non-secure-otp;
|
|
+ };
|
|
+ ...
|
|
+ };
|
|
+
|
|
+The nvmem_layout node gathers all nvmem platform-dependent layout information,
|
|
+including OTP names and phandles, in order to allow easy accesses for data
|
|
+consumers, using pre-defined string in nvmem-cell-names property.
|
|
+
|
|
+Required properties:
|
|
+- compatible: "st,stm32-nvmem-layout"
|
|
+- nvmem-cells and nvmem-cell-names, as described in nvmem.txt.
|
|
+
|
|
+Example on stm32mp1:
|
|
+ nvmem_layout: nvmem_layout@0 {
|
|
+ compatible = "st,stm32-nvmem-layout";
|
|
+ nvmem-cells = <&part_number_otp>,
|
|
+ ...
|
|
+ ;
|
|
+ nvmem-cell-names = "part_number_otp",
|
|
+ ...
|
|
+ ;
|
|
+ };
|
|
+
|
|
+ bsec: nvmem@5c005000 {
|
|
+ ...
|
|
+ part_number_otp: part_number_otp@4 {
|
|
+ reg = <0x4 0x1>;
|
|
+ };
|
|
+ ...
|
|
+ };
|
|
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
|
|
index 3f9657d..baaddfe 100644
|
|
--- a/drivers/mmc/mmc.c
|
|
+++ b/drivers/mmc/mmc.c
|
|
@@ -24,6 +24,7 @@
|
|
static const struct mmc_ops *ops;
|
|
static unsigned int mmc_ocr_value;
|
|
static struct mmc_csd_emmc mmc_csd;
|
|
+static struct sd_switch_status sd_switch_func_status;
|
|
static unsigned char mmc_ext_csd[512] __aligned(16);
|
|
static unsigned int mmc_flags;
|
|
static struct mmc_device_info *mmc_dev_info;
|
|
@@ -43,6 +44,11 @@ static bool is_cmd23_enabled(void)
|
|
return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
|
|
}
|
|
|
|
+static bool is_sd_cmd6_enabled(void)
|
|
+{
|
|
+ return ((mmc_flags & MMC_FLAG_SD_CMD6) != 0U);
|
|
+}
|
|
+
|
|
static int mmc_send_cmd(unsigned int idx, unsigned int arg,
|
|
unsigned int r_type, unsigned int *r_data)
|
|
{
|
|
@@ -326,6 +332,33 @@ static int mmc_fill_device_info(void)
|
|
return 0;
|
|
}
|
|
|
|
+static int sd_switch(unsigned char mode, unsigned char group,
|
|
+ unsigned char func)
|
|
+{
|
|
+ unsigned int group_shift = (group - 1U) * 4U;
|
|
+ unsigned int group_mask = GENMASK(group_shift + 3U, group_shift);
|
|
+ unsigned int arg;
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = ops->prepare(0, (uintptr_t)&sd_switch_func_status,
|
|
+ sizeof(sd_switch_func_status));
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* MMC CMD6: SWITCH_FUNC */
|
|
+ arg = (mode << 31) | GENMASK(23, 0);
|
|
+ arg &= ~group_mask;
|
|
+ arg |= func << group_shift;
|
|
+ ret = mmc_send_cmd(MMC_CMD(6), arg, MMC_RESPONSE_R1, NULL);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return ops->read(0, (uintptr_t)&sd_switch_func_status,
|
|
+ sizeof(sd_switch_func_status));
|
|
+}
|
|
+
|
|
static int sd_send_op_cond(void)
|
|
{
|
|
int n;
|
|
@@ -360,7 +393,7 @@ static int sd_send_op_cond(void)
|
|
return 0;
|
|
}
|
|
|
|
- mdelay(1);
|
|
+ mdelay(10);
|
|
}
|
|
|
|
ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
|
|
@@ -493,7 +526,39 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
|
|
return ret;
|
|
}
|
|
|
|
- return mmc_fill_device_info();
|
|
+ ret = mmc_fill_device_info();
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (is_sd_cmd6_enabled() &&
|
|
+ (mmc_dev_info->mmc_dev_type == MMC_IS_SD_HC)) {
|
|
+ /* Try to switch to High Speed Mode */
|
|
+ ret = sd_switch(SD_SWITCH_FUNC_CHECK, 1U, 1U);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if ((sd_switch_func_status.support_g1 & BIT(9)) == 0U) {
|
|
+ /* High speed not supported, keep default speed */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ ret = sd_switch(SD_SWITCH_FUNC_SWITCH, 1U, 1U);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if ((sd_switch_func_status.sel_g2_g1 & 0x1U) == 0U) {
|
|
+ /* Cannot switch to high speed, keep default speed */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ mmc_dev_info->max_bus_freq = 50000000U;
|
|
+ ret = ops->set_ios(clk, bus_width);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size)
|
|
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
|
|
index 3dad2c2..2193a67 100644
|
|
--- a/drivers/st/bsec/bsec.c
|
|
+++ b/drivers/st/bsec/bsec.c
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -11,9 +11,9 @@
|
|
#include <debug.h>
|
|
#include <limits.h>
|
|
#include <mmio.h>
|
|
+#include <platform_def.h>
|
|
#include <spinlock.h>
|
|
#include <stdint.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define BSEC_IP_VERSION_1_0 0x10
|
|
#define BSEC_COMPAT "st,stm32mp15-bsec"
|
|
@@ -82,33 +82,59 @@ static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
|
|
|
|
fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
|
|
const fdt32_t *cuint;
|
|
- uint32_t reg;
|
|
+ uint32_t otp;
|
|
uint32_t i;
|
|
uint32_t size;
|
|
- uint8_t status;
|
|
+ uint32_t offset;
|
|
+ uint32_t length;
|
|
|
|
cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
|
|
if (cuint == NULL) {
|
|
panic();
|
|
}
|
|
|
|
- reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
|
|
- if (reg < STM32MP1_UPPER_OTP_START) {
|
|
- continue;
|
|
+ offset = fdt32_to_cpu(*cuint);
|
|
+ cuint++;
|
|
+ length = fdt32_to_cpu(*cuint);
|
|
+
|
|
+ otp = offset / sizeof(uint32_t);
|
|
+
|
|
+ if (otp < STM32MP1_UPPER_OTP_START) {
|
|
+ unsigned int otp_end = round_up(offset + length,
|
|
+ sizeof(uint32_t)) /
|
|
+ sizeof(uint32_t);
|
|
+
|
|
+ if (otp_end > STM32MP1_UPPER_OTP_START) {
|
|
+ /*
|
|
+ * OTP crosses Lower/Upper boundary, consider
|
|
+ * only the upper part.
|
|
+ */
|
|
+ otp = STM32MP1_UPPER_OTP_START;
|
|
+ length -= (STM32MP1_UPPER_OTP_START *
|
|
+ sizeof(uint32_t)) - offset;
|
|
+ offset = STM32MP1_UPPER_OTP_START *
|
|
+ sizeof(uint32_t);
|
|
+
|
|
+ WARN("OTP crosses Lower/Upper boundary\n");
|
|
+ } else {
|
|
+ continue;
|
|
+ }
|
|
}
|
|
|
|
- status = fdt_get_status(bsec_subnode);
|
|
- if ((status & DT_NON_SECURE) == 0U) {
|
|
+ if ((fdt_getprop(fdt, bsec_subnode,
|
|
+ "st,non-secure-otp", NULL)) == NULL) {
|
|
continue;
|
|
}
|
|
|
|
- size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t);
|
|
-
|
|
- if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) {
|
|
- size++;
|
|
+ if (((offset % sizeof(uint32_t)) != 0) ||
|
|
+ ((length % sizeof(uint32_t)) != 0)) {
|
|
+ ERROR("Unaligned non-secure OTP\n");
|
|
+ panic();
|
|
}
|
|
|
|
- for (i = reg; i < (reg + size); i++) {
|
|
+ size = length / sizeof(uint32_t);
|
|
+
|
|
+ for (i = otp; i < (otp + size); i++) {
|
|
enable_non_secure_access(i);
|
|
}
|
|
}
|
|
@@ -267,6 +293,79 @@ uint32_t bsec_get_config(struct bsec_config *cfg)
|
|
}
|
|
|
|
/*
|
|
+ * bsec_find_otp_name_in_dt: get OTP ID and length in DT.
|
|
+ * name: sub-node name to look up.
|
|
+ * otp: pointer to read OTP number or NULL.
|
|
+ * otp_len: pointer to read OTP length in bits or NULL.
|
|
+ * return value: BSEC_OK if no error.
|
|
+ */
|
|
+uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp,
|
|
+ uint32_t *otp_len)
|
|
+{
|
|
+ void *fdt;
|
|
+ int node;
|
|
+ int index, len;
|
|
+ const fdt32_t *cuint;
|
|
+
|
|
+ if ((name == NULL) || (otp == NULL)) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
+ }
|
|
+
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ node = dt_get_node_by_compatible(DT_NVMEM_LAYOUT_COMPAT);
|
|
+ if (node < 0) {
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ index = fdt_stringlist_search(fdt, node, "nvmem-cell-names", name);
|
|
+ if (index < 0) {
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, node, "nvmem-cells", &len);
|
|
+ if (cuint == NULL) {
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ if ((index * (int)sizeof(uint32_t)) > len) {
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ cuint += index;
|
|
+
|
|
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
|
|
+ if (node < 0) {
|
|
+ ERROR("Malformed nvmem_layout node: ignored\n");
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, node, "reg", &len);
|
|
+ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) {
|
|
+ ERROR("Malformed nvmem_layout node: ignored\n");
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) {
|
|
+ ERROR("Misaligned nvmem_layout element: ignored\n");
|
|
+ return BSEC_ERROR;
|
|
+ }
|
|
+
|
|
+ if (otp != NULL) {
|
|
+ *otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
|
|
+ }
|
|
+
|
|
+ if (otp_len != NULL) {
|
|
+ cuint++;
|
|
+ *otp_len = fdt32_to_cpu(*cuint) * CHAR_BIT;
|
|
+ }
|
|
+
|
|
+ return BSEC_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
* bsec_shadow_register: copy SAFMEM OTP to BSEC data.
|
|
* otp: OTP number.
|
|
* return value: BSEC_OK if no error.
|
|
diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c
|
|
index 030a84f..14d9d8d 100644
|
|
--- a/drivers/st/clk/stm32mp1_calib.c
|
|
+++ b/drivers/st/clk/stm32mp1_calib.c
|
|
@@ -16,13 +16,11 @@
|
|
#include <limits.h>
|
|
#include <mmio.h>
|
|
#include <platform.h>
|
|
+#include <platform_def.h>
|
|
#include <spinlock.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
-#include <stm32mp1_private.h>
|
|
#include <stm32mp1_rcc.h>
|
|
#include <stm32_timer.h>
|
|
#include <utils_def.h>
|
|
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
|
|
index 286234e..e5ffc11 100644
|
|
--- a/drivers/st/clk/stm32mp1_clk.c
|
|
+++ b/drivers/st/clk/stm32mp1_clk.c
|
|
@@ -16,18 +16,14 @@
|
|
#include <limits.h>
|
|
#include <mmio.h>
|
|
#include <platform.h>
|
|
+#include <platform_def.h>
|
|
#include <spinlock.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
-#include <stm32mp_shres_helpers.h>
|
|
#include <stm32mp1_clk.h>
|
|
#include <stm32mp1_clkfunc.h>
|
|
-#include <stm32mp1_private.h>
|
|
#include <stm32mp1_rcc.h>
|
|
-#include <stm32mp1_shared_resources.h>
|
|
#include <utils_def.h>
|
|
|
|
#define MAX_HSI_HZ 64000000
|
|
@@ -42,6 +38,19 @@
|
|
#define HSIDIV_TIMEOUT TIMEOUT_200MS
|
|
#define OSCRDY_TIMEOUT TIMEOUT_1S
|
|
|
|
+/* PLL settings computation related definitions */
|
|
+#define POST_DIVM_MIN 8000000
|
|
+#define POST_DIVM_MAX 16000000
|
|
+#define DIVM_MIN 0
|
|
+#define DIVM_MAX 63
|
|
+#define DIVN_MIN 24
|
|
+#define DIVN_MAX 99
|
|
+#define DIVP_MIN 0
|
|
+#define DIVP_MAX 127
|
|
+#define FRAC_MAX 8192
|
|
+#define VCO_MIN 800000000
|
|
+#define VCO_MAX 1600000000
|
|
+
|
|
enum stm32mp1_parent_id {
|
|
/* Oscillators are defined in enum stm32mp_osc_id */
|
|
|
|
@@ -204,6 +213,14 @@ struct stm32mp1_clk_pll {
|
|
enum stm32mp_osc_id refclk[REFCLK_SIZE];
|
|
};
|
|
|
|
+struct stm32mp1_pll_settings {
|
|
+ uint32_t valid_id;
|
|
+ uint32_t freq[PLAT_MAX_OPP_NB];
|
|
+ uint32_t volt[PLAT_MAX_OPP_NB];
|
|
+ uint32_t cfg[PLAT_MAX_OPP_NB][PLAT_MAX_PLLCFG_NB];
|
|
+ uint32_t frac[PLAT_MAX_OPP_NB];
|
|
+};
|
|
+
|
|
/* Clocks with selectable source and non set/clr register access */
|
|
#define _CLK_SELEC(off, b, idx, s) \
|
|
{ \
|
|
@@ -460,7 +477,6 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
|
};
|
|
|
|
/* Define characteristic of PLL according type */
|
|
-#define DIVN_MIN 24
|
|
static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
|
|
[PLL_800] = {
|
|
.refclk_min = 4,
|
|
@@ -585,6 +601,8 @@ static unsigned long stm32mp1_osc[NB_OSC];
|
|
static struct spinlock reg_lock;
|
|
static unsigned int gate_refcounts[NB_GATES];
|
|
static struct spinlock refcount_lock;
|
|
+static struct stm32mp1_pll_settings pll1_settings;
|
|
+static uint32_t current_opp_khz;
|
|
|
|
static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
|
|
{
|
|
@@ -1462,11 +1480,8 @@ static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
|
|
return 0;
|
|
}
|
|
|
|
-static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
|
|
- uint32_t *pllcfg)
|
|
+static uint32_t stm32mp1_pll_compute_pllxcfgr2(uint32_t *pllcfg)
|
|
{
|
|
- const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
|
|
- uintptr_t rcc_base = stm32mp_rcc_base();
|
|
uint32_t value;
|
|
|
|
value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
|
|
@@ -1475,21 +1490,33 @@ static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
|
|
RCC_PLLNCFGR2_DIVQ_MASK;
|
|
value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
|
|
RCC_PLLNCFGR2_DIVR_MASK;
|
|
- mmio_write_32(rcc_base + pll->pllxcfgr2, value);
|
|
+
|
|
+ return value;
|
|
}
|
|
|
|
-static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
|
|
- uint32_t *pllcfg, uint32_t fracv)
|
|
+static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
|
|
+ uint32_t *pllcfg)
|
|
{
|
|
const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
|
|
+ uintptr_t rcc_base = stm32mp_rcc_base();
|
|
+ uint32_t value;
|
|
+
|
|
+ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg);
|
|
+
|
|
+ mmio_write_32(rcc_base + pll->pllxcfgr2, value);
|
|
+}
|
|
+
|
|
+static int stm32mp1_pll_compute_pllxcfgr1(const struct stm32mp1_clk_pll *pll,
|
|
+ uint32_t *pllcfg, uint32_t *cfgr1)
|
|
+{
|
|
uint32_t rcc_base = stm32mp_rcc_base();
|
|
enum stm32mp1_plltype type = pll->plltype;
|
|
unsigned long refclk;
|
|
uint32_t ifrge = 0;
|
|
- uint32_t src, value;
|
|
+ uint32_t src;
|
|
|
|
src = mmio_read_32(rcc_base + pll->rckxselr) &
|
|
- RCC_SELR_REFCLK_SRC_MASK;
|
|
+ RCC_SELR_REFCLK_SRC_MASK;
|
|
|
|
refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
|
|
(pllcfg[PLLCFG_M] + 1U);
|
|
@@ -1503,23 +1530,39 @@ static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
|
|
ifrge = 1U;
|
|
}
|
|
|
|
- value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
|
|
- RCC_PLLNCFGR1_DIVN_MASK;
|
|
- value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
|
|
- RCC_PLLNCFGR1_DIVM_MASK;
|
|
- value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
|
|
- RCC_PLLNCFGR1_IFRGE_MASK;
|
|
+ *cfgr1 = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
|
|
+ RCC_PLLNCFGR1_DIVN_MASK;
|
|
+ *cfgr1 |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
|
|
+ RCC_PLLNCFGR1_DIVM_MASK;
|
|
+ *cfgr1 |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
|
|
+ RCC_PLLNCFGR1_IFRGE_MASK;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
|
|
+ uint32_t *pllcfg, uint32_t fracv)
|
|
+{
|
|
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
|
|
+ uint32_t rcc_base = stm32mp_rcc_base();
|
|
+ uint32_t value;
|
|
+ int ret;
|
|
+
|
|
+ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
mmio_write_32(rcc_base + pll->pllxcfgr1, value);
|
|
|
|
/* Fractional configuration */
|
|
value = 0;
|
|
mmio_write_32(rcc_base + pll->pllxfracr, value);
|
|
|
|
+ /* Frac must be enabled only once its configuration is loaded */
|
|
value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
|
|
mmio_write_32(rcc_base + pll->pllxfracr, value);
|
|
-
|
|
- value |= RCC_PLLNFRACR_FRACLE;
|
|
- mmio_write_32(rcc_base + pll->pllxfracr, value);
|
|
+ mmio_setbits_32(rcc_base + pll->pllxfracr, RCC_PLLNFRACR_FRACLE);
|
|
|
|
stm32mp1_pll_config_output(pll_id, pllcfg);
|
|
|
|
@@ -1684,17 +1727,24 @@ unsigned long stm32mp_clk_timer_get_rate(unsigned long id)
|
|
return parent_rate * (timpre + 1) * 2;
|
|
}
|
|
|
|
-void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
|
|
+unsigned long long stm32mp1_stgen_get_counter(void)
|
|
+{
|
|
+ uintptr_t stgen = fdt_get_stgen_base();
|
|
+
|
|
+ return (((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
|
|
+ mmio_read_32(stgen + CNTCVL_OFF));
|
|
+}
|
|
+
|
|
+void stm32mp1_stgen_restore_counter(unsigned long long value,
|
|
+ unsigned long long offset_in_ms)
|
|
{
|
|
uintptr_t stgen;
|
|
unsigned long long cnt;
|
|
|
|
stgen = fdt_get_stgen_base();
|
|
|
|
- cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
|
|
- mmio_read_32(stgen + CNTCVL_OFF);
|
|
-
|
|
- cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
|
|
+ cnt = value + ((offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) /
|
|
+ 1000U);
|
|
|
|
mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
|
|
mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt);
|
|
@@ -1753,6 +1803,187 @@ static void stm32mp1_pkcs_config(uint32_t pkcs)
|
|
mmio_clrsetbits_32(address, mask, value);
|
|
}
|
|
|
|
+static bool clk_pll1_settings_are_valid(void)
|
|
+{
|
|
+ return pll1_settings.valid_id == PLL1_SETTINGS_VALID_ID;
|
|
+}
|
|
+
|
|
+int stm32mp1_round_opp_khz(uint32_t *freq_khz)
|
|
+{
|
|
+ unsigned int i;
|
|
+ uint32_t round_opp = 0U;
|
|
+
|
|
+ if (!clk_pll1_settings_are_valid()) {
|
|
+ /*
|
|
+ * No OPP table in DT, or an error occurred during PLL1
|
|
+ * settings computation, system can only work on current
|
|
+ * operating point, so return current CPU frequency.
|
|
+ */
|
|
+ *freq_khz = current_opp_khz;
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) {
|
|
+ if ((pll1_settings.freq[i] <= *freq_khz) &&
|
|
+ (pll1_settings.freq[i] > round_opp)) {
|
|
+ round_opp = pll1_settings.freq[i];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *freq_khz = round_opp;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Check if PLL1 can be configured on the fly.
|
|
+ * @result (-1) => config on the fly is not possible.
|
|
+ * (0) => config on the fly is possible.
|
|
+ * (+1) => same parameters, no need to reconfigure.
|
|
+ * Return value is 0 if no error.
|
|
+ */
|
|
+static int stm32mp1_is_pll_config_on_the_fly(enum stm32mp1_pll_id pll_id,
|
|
+ uint32_t *pllcfg, uint32_t fracv,
|
|
+ int *result)
|
|
+{
|
|
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
|
|
+ uintptr_t rcc_base = stm32mp_rcc_base();
|
|
+ uint32_t fracr;
|
|
+ uint32_t value;
|
|
+ int ret;
|
|
+
|
|
+ ret = stm32mp1_pll_compute_pllxcfgr1(pll, pllcfg, &value);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
|
|
+ /* Different DIVN/DIVM, can't config on the fly */
|
|
+ *result = -1;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ *result = true;
|
|
+
|
|
+ fracr = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
|
|
+ fracr |= RCC_PLLNFRACR_FRACLE;
|
|
+ value = stm32mp1_pll_compute_pllxcfgr2(pllcfg);
|
|
+
|
|
+ if ((mmio_read_32(rcc_base + pll->pllxfracr) == fracr) &&
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr2) == value)) {
|
|
+ /* Same parameters, no need to config */
|
|
+ *result = 1;
|
|
+ } else {
|
|
+ *result = 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int stm32mp1_pll1_config_from_opp_khz(uint32_t freq_khz)
|
|
+{
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
+ int config_on_the_fly = -1;
|
|
+
|
|
+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) {
|
|
+ if (pll1_settings.freq[i] == freq_khz) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (i == PLAT_MAX_OPP_NB) {
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ ret = stm32mp1_is_pll_config_on_the_fly(_PLL1, &pll1_settings.cfg[i][0],
|
|
+ pll1_settings.frac[i],
|
|
+ &config_on_the_fly);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (config_on_the_fly == 1) {
|
|
+ /* No need to reconfigure, setup already OK */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (config_on_the_fly == -1) {
|
|
+ /* Switch to HSI and stop PLL1 before reconfiguration */
|
|
+ ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = stm32mp1_pll_stop(_PLL1);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ret = stm32mp1_pll_config(_PLL1, &pll1_settings.cfg[i][0],
|
|
+ pll1_settings.frac[i]);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (config_on_the_fly == -1) {
|
|
+ /* Start PLL1 and switch back to after reconfiguration */
|
|
+ stm32mp1_pll_start(_PLL1);
|
|
+
|
|
+ ret = stm32mp1_pll_output(_PLL1,
|
|
+ pll1_settings.cfg[i][PLLCFG_O]);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = stm32mp1_set_clksrc(CLK_MPU_PLL1P);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int stm32mp1_set_opp_khz(uint32_t freq_khz)
|
|
+{
|
|
+ if (freq_khz == current_opp_khz) {
|
|
+ /* OPP already set, nothing to do */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (!clk_pll1_settings_are_valid()) {
|
|
+ /*
|
|
+ * No OPP table in DT or an error occurred during PLL1
|
|
+ * settings computation, system can only work on current
|
|
+ * operating point so return error.
|
|
+ */
|
|
+ return -EACCES;
|
|
+ }
|
|
+
|
|
+ /* Check that PLL1 (without MPUDIV) is MPU clock source */
|
|
+ if (((mmio_read_32(stm32mp_rcc_base() + RCC_MPCKSELR) &
|
|
+ RCC_SELR_SRC_MASK)) != RCC_MPCKSELR_PLL) {
|
|
+ return -EPERM;
|
|
+ }
|
|
+
|
|
+ if (stm32mp1_pll1_config_from_opp_khz(freq_khz) != 0) {
|
|
+ /* Restore original value */
|
|
+ if (stm32mp1_pll1_config_from_opp_khz(current_opp_khz) != 0) {
|
|
+ ERROR("No CPU operating point can be set\n");
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ current_opp_khz = freq_khz;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
#if defined(IMAGE_BL32)
|
|
void stm32mp1_clk_mpu_suspend(void)
|
|
{
|
|
@@ -1779,15 +2010,349 @@ void stm32mp1_clk_mpu_resume(void)
|
|
}
|
|
#endif
|
|
|
|
-int stm32mp1_clk_init(void)
|
|
+static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
|
|
+ uint32_t *fracv, uint32_t *csg,
|
|
+ bool *csg_set)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = fdt_read_uint32_array(plloff, "cfg", pllcfg, (uint32_t)PLLCFG_NB);
|
|
+ if (ret < 0) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ *fracv = fdt_read_uint32_default(plloff, "frac", 0);
|
|
+
|
|
+ ret = fdt_read_uint32_array(plloff, "csg", csg, (uint32_t)PLLCSG_NB);
|
|
+
|
|
+ *csg_set = (ret == 0);
|
|
+
|
|
+ if (ret == -FDT_ERR_NOTFOUND) {
|
|
+ ret = 0;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int clk_compute_pll1_settings(unsigned long input_freq,
|
|
+ uint32_t freq_khz,
|
|
+ uint32_t *pllcfg, uint32_t *fracv)
|
|
+{
|
|
+ unsigned long post_divm;
|
|
+ unsigned long long output_freq = freq_khz * 1000U;
|
|
+ unsigned long long freq;
|
|
+ unsigned long long vco;
|
|
+ int divm;
|
|
+ int divn;
|
|
+ int divp;
|
|
+ int frac;
|
|
+ int i;
|
|
+ unsigned int diff;
|
|
+ unsigned int best_diff = UINT_MAX;
|
|
+
|
|
+ /* Following parameters have always the same value */
|
|
+ pllcfg[PLLCFG_Q] = 0;
|
|
+ pllcfg[PLLCFG_R] = 0;
|
|
+ pllcfg[PLLCFG_O] = PQR(1, 0, 0);
|
|
+
|
|
+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) {
|
|
+ post_divm = input_freq / (unsigned long)(divm + 1);
|
|
+
|
|
+ if ((post_divm < POST_DIVM_MIN) ||
|
|
+ (post_divm > POST_DIVM_MAX)) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) {
|
|
+
|
|
+ freq = output_freq * (divm + 1) * (divp + 1);
|
|
+
|
|
+ divn = (int)((freq / input_freq) - 1);
|
|
+ if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ frac = (int)(((freq * FRAC_MAX) / input_freq) -
|
|
+ ((divn + 1) * FRAC_MAX));
|
|
+
|
|
+ /* 2 loops to refine the fractional part */
|
|
+ for (i = 2; i != 0; i--) {
|
|
+ if (frac > FRAC_MAX) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ vco = (post_divm * (divn + 1)) +
|
|
+ ((post_divm * (unsigned long long)frac) /
|
|
+ FRAC_MAX);
|
|
+
|
|
+ if ((vco < (VCO_MIN / 2)) ||
|
|
+ (vco > (VCO_MAX / 2))) {
|
|
+ frac++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ freq = vco / (divp + 1);
|
|
+ if (output_freq < freq) {
|
|
+ diff = (unsigned int)(freq -
|
|
+ output_freq);
|
|
+ } else {
|
|
+ diff = (unsigned int)(output_freq -
|
|
+ freq);
|
|
+ }
|
|
+
|
|
+ if (diff < best_diff) {
|
|
+ pllcfg[PLLCFG_M] = divm;
|
|
+ pllcfg[PLLCFG_N] = divn;
|
|
+ pllcfg[PLLCFG_P] = divp;
|
|
+ *fracv = frac;
|
|
+
|
|
+ if (diff == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ best_diff = diff;
|
|
+ }
|
|
+
|
|
+ frac++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (best_diff == UINT_MAX) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int clk_get_pll1_settings(uint32_t clksrc, uint32_t freq_khz,
|
|
+ uint32_t *pllcfg, uint32_t *fracv)
|
|
+{
|
|
+ unsigned long input_freq;
|
|
+ unsigned int i;
|
|
+
|
|
+ assert(pllcfg != NULL);
|
|
+ assert(fracv != NULL);
|
|
+
|
|
+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) {
|
|
+ if (pll1_settings.freq[i] == freq_khz) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (((i == PLAT_MAX_OPP_NB) && (pll1_settings.valid_id == 0U)) ||
|
|
+ ((i < PLAT_MAX_OPP_NB) &&
|
|
+ (pll1_settings.cfg[i][PLLCFG_O] == 0U))) {
|
|
+ /*
|
|
+ * Either PLL1 settings structure is completely empty,
|
|
+ * or this frequency is not yet filled: compute settings.
|
|
+ */
|
|
+ switch (clksrc) {
|
|
+ case CLK_PLL12_HSI:
|
|
+ input_freq = stm32mp_clk_get_rate(CK_HSI);
|
|
+ break;
|
|
+ case CLK_PLL12_HSE:
|
|
+ input_freq = stm32mp_clk_get_rate(CK_HSE);
|
|
+ break;
|
|
+ default:
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ return clk_compute_pll1_settings(input_freq, freq_khz, pllcfg,
|
|
+ fracv);
|
|
+ }
|
|
+
|
|
+ if ((i < PLAT_MAX_OPP_NB) &&
|
|
+ (pll1_settings.cfg[i][PLLCFG_O] != 0U)) {
|
|
+ /*
|
|
+ * Index is in range and PLL1 settings line is filled,
|
|
+ * use content to answer to the request.
|
|
+ */
|
|
+ memcpy(pllcfg, &pll1_settings.cfg[i][0],
|
|
+ sizeof(uint32_t) * PLAT_MAX_PLLCFG_NB);
|
|
+ *fracv = pll1_settings.frac[i];
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_khz,
|
|
+ uint32_t *voltage_mv)
|
|
+{
|
|
+ unsigned int i;
|
|
+ uint32_t freq = 0U;
|
|
+ uint32_t voltage = 0U;
|
|
+
|
|
+ assert(freq_khz != NULL);
|
|
+ assert(voltage_mv != NULL);
|
|
+
|
|
+ if (!clk_pll1_settings_are_valid()) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) {
|
|
+ if (pll1_settings.freq[i] > freq) {
|
|
+ freq = pll1_settings.freq[i];
|
|
+ voltage = pll1_settings.volt[i];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((freq == 0U) || (voltage == 0U)) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ *freq_khz = freq;
|
|
+ *voltage_mv = voltage;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int clk_save_current_pll1_settings(uint32_t buck1_voltage)
|
|
+{
|
|
+ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1);
|
|
+ uint32_t rcc_base = stm32mp_rcc_base();
|
|
+ uint32_t freq;
|
|
+ unsigned int i;
|
|
+
|
|
+ freq = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000L);
|
|
+
|
|
+ for (i = 0; i < PLAT_MAX_OPP_NB; i++) {
|
|
+ if (pll1_settings.freq[i] == freq) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((i == PLAT_MAX_OPP_NB) ||
|
|
+ ((pll1_settings.volt[i] != buck1_voltage) &&
|
|
+ (buck1_voltage != 0U))) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_M] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr1) &
|
|
+ RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT;
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_N] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr1) &
|
|
+ RCC_PLLNCFGR1_DIVN_MASK) >> RCC_PLLNCFGR1_DIVN_SHIFT;
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_P] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr2) &
|
|
+ RCC_PLLNCFGR2_DIVP_MASK) >> RCC_PLLNCFGR2_DIVP_SHIFT;
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_Q] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr2) &
|
|
+ RCC_PLLNCFGR2_DIVQ_MASK) >> RCC_PLLNCFGR2_DIVQ_SHIFT;
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_R] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxcfgr2) &
|
|
+ RCC_PLLNCFGR2_DIVR_MASK) >> RCC_PLLNCFGR2_DIVR_SHIFT;
|
|
+
|
|
+ pll1_settings.cfg[i][PLLCFG_O] =
|
|
+ mmio_read_32(rcc_base + pll->pllxcr) >>
|
|
+ RCC_PLLNCR_DIVEN_SHIFT;
|
|
+
|
|
+ pll1_settings.frac[i] =
|
|
+ (mmio_read_32(rcc_base + pll->pllxfracr) &
|
|
+ RCC_PLLNFRACR_FRACV_MASK) >> RCC_PLLNFRACR_FRACV_SHIFT;
|
|
+
|
|
+ return i;
|
|
+}
|
|
+
|
|
+static uint32_t stm32mp1_clk_get_pll1_current_clksrc(void)
|
|
{
|
|
+ uint32_t value;
|
|
+ const struct stm32mp1_clk_pll *pll = pll_ref(_PLL1);
|
|
uint32_t rcc_base = stm32mp_rcc_base();
|
|
+
|
|
+ value = mmio_read_32(rcc_base + pll->rckxselr);
|
|
+
|
|
+ switch (value & RCC_SELR_REFCLK_SRC_MASK) {
|
|
+ case 0:
|
|
+ return CLK_PLL12_HSI;
|
|
+ case 1:
|
|
+ return CLK_PLL12_HSE;
|
|
+ default:
|
|
+ panic();
|
|
+ }
|
|
+}
|
|
+
|
|
+int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage)
|
|
+{
|
|
+ int i;
|
|
+ int ret;
|
|
+ int index;
|
|
+ uint32_t count = PLAT_MAX_OPP_NB;
|
|
+ uint32_t clksrc;
|
|
+
|
|
+ ret = dt_get_all_opp_freqvolt(&count, pll1_settings.freq,
|
|
+ pll1_settings.volt);
|
|
+ switch (ret) {
|
|
+ case 0:
|
|
+ break;
|
|
+ case -FDT_ERR_NOTFOUND:
|
|
+ VERBOSE("Cannot find OPP table in DT, use default settings.\n");
|
|
+ return 0;
|
|
+ default:
|
|
+ ERROR("Inconsistent OPP settings found in DT, ignored.\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ index = clk_save_current_pll1_settings(buck1_voltage);
|
|
+
|
|
+ clksrc = stm32mp1_clk_get_pll1_current_clksrc();
|
|
+
|
|
+ for (i = 0; i < (int)count; i++) {
|
|
+ if (i == index) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ ret = clk_get_pll1_settings(clksrc, pll1_settings.freq[i],
|
|
+ &pll1_settings.cfg[i][0],
|
|
+ &pll1_settings.frac[i]);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pll1_settings.valid_id = PLL1_SETTINGS_VALID_ID;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size)
|
|
+{
|
|
+ if ((size != sizeof(pll1_settings)) || !clk_pll1_settings_are_valid()) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ memcpy(data, &pll1_settings, size);
|
|
+}
|
|
+
|
|
+void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size)
|
|
+{
|
|
+ if (size != sizeof(pll1_settings)) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ memcpy(&pll1_settings, data, size);
|
|
+}
|
|
+
|
|
+int stm32mp1_clk_init(uint32_t pll1_freq_khz)
|
|
+{
|
|
+ uint32_t rcc_base = stm32mp_rcc_base();
|
|
+ uint32_t pllfracv[_PLL_NB];
|
|
+ uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
|
|
unsigned int clksrc[CLKSRC_NB];
|
|
unsigned int clkdiv[CLKDIV_NB];
|
|
unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
|
|
int plloff[_PLL_NB];
|
|
int ret, len;
|
|
enum stm32mp1_pll_id i;
|
|
+ bool pllcsg_set[_PLL_NB];
|
|
+ bool pllcfg_valid[_PLL_NB];
|
|
bool lse_css = false;
|
|
bool pll3_preserve = false;
|
|
bool pll4_preserve = false;
|
|
@@ -1819,14 +2384,27 @@ int stm32mp1_clk_init(void)
|
|
snprintf(name, sizeof(name), "st,pll@%d", i);
|
|
plloff[i] = fdt_rcc_subnode_offset(name);
|
|
|
|
- if (!fdt_check_node(plloff[i])) {
|
|
+ pllcfg_valid[i] = fdt_check_node(plloff[i]);
|
|
+ if (pllcfg_valid[i]) {
|
|
+ ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
|
|
+ &pllfracv[i], pllcsg[i],
|
|
+ &pllcsg_set[i]);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
continue;
|
|
}
|
|
|
|
- ret = fdt_read_uint32_array(plloff[i], "cfg",
|
|
- pllcfg[i], (int)PLLCFG_NB);
|
|
- if (ret < 0) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ if ((i == _PLL1) && (pll1_freq_khz != 0U)) {
|
|
+ ret = clk_get_pll1_settings(clksrc[CLKSRC_PLL12],
|
|
+ pll1_freq_khz,
|
|
+ pllcfg[i], &pllfracv[i]);
|
|
+ if (ret != 0) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ pllcfg_valid[i] = true;
|
|
}
|
|
}
|
|
|
|
@@ -1977,15 +2555,12 @@ int stm32mp1_clk_init(void)
|
|
|
|
/* Configure and start PLLs */
|
|
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
|
|
- uint32_t fracv;
|
|
- uint32_t csg[PLLCSG_NB];
|
|
-
|
|
if (((i == _PLL3) && pll3_preserve) ||
|
|
((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
|
|
continue;
|
|
}
|
|
|
|
- if (!fdt_check_node(plloff[i])) {
|
|
+ if (!pllcfg_valid[i]) {
|
|
continue;
|
|
}
|
|
|
|
@@ -1995,25 +2570,20 @@ int stm32mp1_clk_init(void)
|
|
continue;
|
|
}
|
|
|
|
- fracv = fdt_read_uint32_default(plloff[i], "frac", 0);
|
|
-
|
|
- ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
|
|
+ ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
- ret = fdt_read_uint32_array(plloff[i], "csg", csg,
|
|
- (uint32_t)PLLCSG_NB);
|
|
- if (ret == 0) {
|
|
- stm32mp1_pll_csg(i, csg);
|
|
- } else if (ret != -FDT_ERR_NOTFOUND) {
|
|
- return ret;
|
|
+
|
|
+ if (pllcsg_set[i]) {
|
|
+ stm32mp1_pll_csg(i, pllcsg[i]);
|
|
}
|
|
|
|
stm32mp1_pll_start(i);
|
|
}
|
|
/* Wait and start PLLs ouptut when ready */
|
|
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
|
|
- if (!fdt_check_node(plloff[i])) {
|
|
+ if (!pllcfg_valid[i]) {
|
|
continue;
|
|
}
|
|
|
|
@@ -2425,9 +2995,21 @@ static void sync_earlyboot_clocks_state(void)
|
|
|
|
int stm32mp1_clk_probe(void)
|
|
{
|
|
+ unsigned long freq_khz;
|
|
+
|
|
+ assert(PLLCFG_NB == PLAT_MAX_PLLCFG_NB);
|
|
+
|
|
stm32mp1_osc_init();
|
|
|
|
sync_earlyboot_clocks_state();
|
|
|
|
+ /* Save current CPU operating point value */
|
|
+ freq_khz = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000UL);
|
|
+ if (freq_khz > (unsigned long)UINT32_MAX) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ current_opp_khz = (uint32_t)freq_khz;
|
|
+
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c
|
|
index 99a7360..1777a24 100644
|
|
--- a/drivers/st/clk/stm32mp1_clkfunc.c
|
|
+++ b/drivers/st/clk/stm32mp1_clkfunc.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,8 +10,6 @@
|
|
#include <platform_def.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <stm32mp1_clk.h>
|
|
#include <stm32mp1_clkfunc.h>
|
|
|
|
@@ -56,6 +54,10 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq)
|
|
if (strncmp(cchar, name, (size_t)ret) == 0) {
|
|
const fdt32_t *cuint;
|
|
|
|
+ if (fdt_get_status(subnode) == DT_DISABLED) {
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
cuint = fdt_getprop(fdt, subnode, "clock-frequency",
|
|
&ret);
|
|
if (cuint == NULL) {
|
|
@@ -68,7 +70,8 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq)
|
|
}
|
|
}
|
|
|
|
- /* Oscillator not found, freq=0 */
|
|
+exit:
|
|
+ /* Oscillator not found or disabled, freq=0 */
|
|
*freq = 0;
|
|
return 0;
|
|
}
|
|
@@ -170,11 +173,11 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
|
|
******************************************************************************/
|
|
int fdt_rcc_enable_it(const char *name)
|
|
{
|
|
- void *fdt;
|
|
+ int node = fdt_get_rcc_node();
|
|
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
+ if (node < 0) {
|
|
+ return -ENODEV;
|
|
}
|
|
|
|
- return stm32_gic_enable_spi(fdt_get_rcc_node(fdt), name);
|
|
+ return stm32_gic_enable_spi(node, name);
|
|
}
|
|
diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c
|
|
index 5c7e202..a8ae62e 100644
|
|
--- a/drivers/st/clk/stm32mp_clkfunc.c
|
|
+++ b/drivers/st/clk/stm32mp_clkfunc.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -9,8 +9,6 @@
|
|
#include <platform_def.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define DT_STGEN_COMPAT "st,stm32-stgen"
|
|
#define DT_UART_COMPAT "st,stm32h7-uart"
|
|
@@ -18,37 +16,9 @@
|
|
/*******************************************************************************
|
|
* This function returns the RCC node in the device tree.
|
|
******************************************************************************/
|
|
-int fdt_get_rcc_node(void *fdt)
|
|
+int fdt_get_rcc_node(void)
|
|
{
|
|
- return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
|
|
-}
|
|
-
|
|
-/*******************************************************************************
|
|
- * This function reads the rcc base address.
|
|
- * It reads the value indicated inside the device tree.
|
|
- * Returns address on success, and 0 on failure.
|
|
- ******************************************************************************/
|
|
-uint32_t fdt_rcc_read_addr(void)
|
|
-{
|
|
- int node;
|
|
- void *fdt;
|
|
- const fdt32_t *cuint;
|
|
-
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- node = fdt_get_rcc_node(fdt);
|
|
- if (node < 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- return fdt32_to_cpu(*cuint);
|
|
+ return dt_get_node_by_compatible(DT_RCC_CLK_COMPAT);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -62,13 +32,8 @@ int fdt_rcc_read_uint32_array(const char *prop_name,
|
|
uint32_t *array, uint32_t count)
|
|
{
|
|
int node;
|
|
- void *fdt;
|
|
-
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
- }
|
|
|
|
- node = fdt_get_rcc_node(fdt);
|
|
+ node = fdt_get_rcc_node();
|
|
if (node < 0) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
@@ -85,13 +50,8 @@ int fdt_rcc_read_uint32_array(const char *prop_name,
|
|
uint32_t fdt_rcc_read_uint32_default(const char *prop_name, uint32_t dflt_value)
|
|
{
|
|
int node;
|
|
- void *fdt;
|
|
-
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return dflt_value;
|
|
- }
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
|
|
+ node = fdt_get_rcc_node();
|
|
if (node < 0) {
|
|
return dflt_value;
|
|
}
|
|
@@ -113,7 +73,7 @@ int fdt_rcc_subnode_offset(const char *name)
|
|
return -ENOENT;
|
|
}
|
|
|
|
- node = fdt_get_rcc_node(fdt);
|
|
+ node = fdt_get_rcc_node();
|
|
if (node < 0) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
@@ -142,7 +102,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
|
|
return NULL;
|
|
}
|
|
|
|
- node = fdt_get_rcc_node(fdt);
|
|
+ node = fdt_get_rcc_node();
|
|
if (node < 0) {
|
|
return NULL;
|
|
}
|
|
@@ -164,13 +124,8 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
|
|
bool fdt_get_rcc_secure_status(void)
|
|
{
|
|
int node;
|
|
- void *fdt;
|
|
-
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return false;
|
|
- }
|
|
|
|
- node = fdt_get_rcc_node(fdt);
|
|
+ node = fdt_get_rcc_node();
|
|
if (node < 0) {
|
|
return false;
|
|
}
|
|
@@ -185,25 +140,7 @@ bool fdt_get_rcc_secure_status(void)
|
|
******************************************************************************/
|
|
uintptr_t fdt_get_stgen_base(void)
|
|
{
|
|
- int node;
|
|
- const fdt32_t *cuint;
|
|
- void *fdt;
|
|
-
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT);
|
|
- if (node < 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- return fdt32_to_cpu(*cuint);
|
|
+ return dt_get_peripheral_base(DT_STGEN_COMPAT);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -273,35 +210,31 @@ unsigned long fdt_get_uart_clock_freq(uintptr_t instance)
|
|
{
|
|
int node;
|
|
void *fdt;
|
|
+ unsigned long clk_id;
|
|
|
|
if (fdt_get_address(&fdt) == 0) {
|
|
return 0;
|
|
}
|
|
|
|
/* Check for UART nodes */
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT);
|
|
- while (node != -FDT_ERR_NOTFOUND) {
|
|
- const fdt32_t *cuint;
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
- if (cuint == NULL)
|
|
- goto next;
|
|
-
|
|
- if ((uintptr_t)fdt32_to_cpu(*cuint) == instance) {
|
|
- unsigned long clk_id;
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "clocks", NULL);
|
|
- if (cuint == NULL)
|
|
- goto next;
|
|
-
|
|
- cuint++;
|
|
- clk_id = (unsigned long)(fdt32_to_cpu(*cuint));
|
|
+ node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance);
|
|
+ if (node < 0) {
|
|
+ return 0UL;
|
|
+ }
|
|
|
|
- return stm32mp_clk_get_rate(clk_id);
|
|
- }
|
|
-next:
|
|
- node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT);
|
|
+ clk_id = fdt_get_clock_id(node);
|
|
+ if (clk_id < 0) {
|
|
+ return 0UL;
|
|
}
|
|
|
|
- return 0;
|
|
+ return stm32mp_clk_get_rate(clk_id);
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function checks if PLL1 hard-coded settings have been defined in DT.
|
|
+ * Returns true if PLL1 node is found and enabled, false if not.
|
|
+ ******************************************************************************/
|
|
+bool fdt_is_pll1_predefined(void)
|
|
+{
|
|
+ return fdt_check_node(fdt_rcc_subnode_offset(DT_PLL1_NODE_NAME));
|
|
}
|
|
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
|
|
index 00ebb22..1be2c23 100644
|
|
--- a/drivers/st/ddr/stm32mp1_ddr.c
|
|
+++ b/drivers/st/ddr/stm32mp1_ddr.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
@@ -13,8 +13,6 @@
|
|
#include <platform.h>
|
|
#include <platform_def.h>
|
|
#include <stddef.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <stm32mp_pmic.h>
|
|
|
|
struct reg_desc {
|
|
@@ -652,7 +650,8 @@ static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
|
|
/* Quasi-dynamic register update*/
|
|
mmio_setbits_32((uintptr_t)&ctl->rfshctl3,
|
|
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
|
|
- mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
|
|
+ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN |
|
|
+ DDRCTRL_PWRCTL_SELFREF_EN);
|
|
mmio_clrbits_32((uintptr_t)&ctl->dfimisc,
|
|
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
|
|
stm32mp1_wait_sw_done_ack(ctl);
|
|
@@ -670,6 +669,10 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
|
|
mmio_setbits_32((uintptr_t)&ctl->pwrctl,
|
|
DDRCTRL_PWRCTL_POWERDOWN_EN);
|
|
}
|
|
+ if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN) != 0U) {
|
|
+ mmio_setbits_32((uintptr_t)&ctl->pwrctl,
|
|
+ DDRCTRL_PWRCTL_SELFREF_EN);
|
|
+ }
|
|
mmio_setbits_32((uintptr_t)&ctl->dfimisc,
|
|
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
|
|
stm32mp1_wait_sw_done_ack(ctl);
|
|
diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c
|
|
index 63f254f..8f9d07b 100644
|
|
--- a/drivers/st/ddr/stm32mp1_ddr_helpers.c
|
|
+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,7 +10,6 @@
|
|
#include <mmio.h>
|
|
#include <platform.h>
|
|
#include <platform_def.h>
|
|
-#include <stm32mp_common.h>
|
|
|
|
#define TIMEOUT_500US us2tick(500)
|
|
|
|
@@ -127,6 +126,9 @@ static int ddr_sw_self_refresh_in(void)
|
|
DDRPHYC_ACIOCR_CSPDD_MASK,
|
|
DDRPHYC_ACIOCR_CSPDD_0);
|
|
|
|
+ /* Disable command/address output driver */
|
|
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE);
|
|
+
|
|
mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD);
|
|
|
|
mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
|
|
@@ -144,6 +146,12 @@ static int ddr_sw_self_refresh_in(void)
|
|
/* Disable PZQ cell (PUBL register) */
|
|
mmio_setbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD);
|
|
|
|
+ /* Set latch */
|
|
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE);
|
|
+
|
|
+ /* Additional delay to avoid early latch */
|
|
+ udelay(10);
|
|
+
|
|
/* Activate sw retention in PWRCTRL */
|
|
pwr_regs_lock();
|
|
mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN);
|
|
@@ -293,6 +301,9 @@ int ddr_sw_self_refresh_exit(void)
|
|
/* Enable pad drivers */
|
|
mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD);
|
|
|
|
+ /* Enable command/address output driver */
|
|
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACOE);
|
|
+
|
|
mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
|
|
DDRPHYC_ACIOCR_CKPDD_MASK);
|
|
|
|
@@ -303,6 +314,9 @@ int ddr_sw_self_refresh_exit(void)
|
|
|
|
mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
|
|
|
|
+ /* Release latch */
|
|
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_CKOE);
|
|
+
|
|
mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR,
|
|
DDRPHYC_DSGCR_ODTPDD_MASK);
|
|
|
|
@@ -369,6 +383,10 @@ void ddr_sr_mode_ssr(void)
|
|
uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR;
|
|
uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
|
|
|
|
+ if (!stm32mp_ddr_supports_ssr_asr()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
stm32mp1_clk_rcc_regs_lock();
|
|
|
|
mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN);
|
|
@@ -421,6 +439,10 @@ void ddr_sr_mode_asr(void)
|
|
uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR;
|
|
uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
|
|
|
|
+ if (!stm32mp_ddr_supports_ssr_asr()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
stm32mp1_clk_rcc_regs_lock();
|
|
|
|
mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN);
|
|
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
|
|
index 773c9f7..ef35a06 100644
|
|
--- a/drivers/st/ddr/stm32mp1_ram.c
|
|
+++ b/drivers/st/ddr/stm32mp1_ram.c
|
|
@@ -1,18 +1,15 @@
|
|
/*
|
|
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
|
|
#include <arch_helpers.h>
|
|
-#include <boot_api.h>
|
|
#include <debug.h>
|
|
#include <errno.h>
|
|
#include <libfdt.h>
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define DDR_PATTERN 0xAAAAAAAAU
|
|
#define DDR_ANTIPATTERN 0x55555555U
|
|
@@ -220,9 +217,8 @@ static int stm32mp1_ddr_setup(void)
|
|
return -ENOENT;
|
|
}
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
|
|
+ node = dt_get_node_by_compatible(DT_DDR_COMPAT);
|
|
if (node < 0) {
|
|
- ERROR("%s: Cannot read DDR node in DT\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -291,11 +287,6 @@ static int stm32mp1_ddr_setup(void)
|
|
VERBOSE("%s : ram size(%x, %x)\n", __func__,
|
|
(uint32_t)priv->info.base, (uint32_t)priv->info.size);
|
|
|
|
-#ifndef DCACHE_OFF
|
|
- write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
|
|
- dcsw_op_all(DC_OP_CISW);
|
|
-#endif
|
|
-
|
|
if (config.self_refresh) {
|
|
uret = ddr_test_rw_access();
|
|
if (uret != 0U) {
|
|
@@ -329,9 +320,8 @@ static int stm32mp1_ddr_setup(void)
|
|
}
|
|
}
|
|
|
|
-#ifndef DCACHE_OFF
|
|
- write_sctlr(read_sctlr() | SCTLR_C_BIT);
|
|
-#endif
|
|
+ /* Switch to Automatic Self-Refresh */
|
|
+ ddr_sr_mode_asr();
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c
|
|
index 06c3282..f2ddd75 100644
|
|
--- a/drivers/st/etzpc/etzpc.c
|
|
+++ b/drivers/st/etzpc/etzpc.c
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
|
- * Copyright (c) 2017-2018, STMicroelectronics
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -15,8 +15,6 @@
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
#include <stdint.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <utils_def.h>
|
|
|
|
/* Device Tree related definitions */
|
|
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
|
|
index fc0dce8..8c23c5b 100644
|
|
--- a/drivers/st/gpio/stm32_gpio.c
|
|
+++ b/drivers/st/gpio/stm32_gpio.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -14,8 +14,6 @@
|
|
#include <stdbool.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define DT_GPIO_BANK_SHIFT 12
|
|
#define DT_GPIO_BANK_MASK 0x1F000U
|
|
@@ -165,7 +163,7 @@ int dt_set_pinctrl_config(int node)
|
|
void *fdt;
|
|
|
|
if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
}
|
|
|
|
if (status == DT_DISABLED) {
|
|
diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
|
|
index ce609ba..f57bf5a 100644
|
|
--- a/drivers/st/i2c/stm32_i2c.c
|
|
+++ b/drivers/st/i2c/stm32_i2c.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
@@ -15,7 +15,6 @@
|
|
#include <stdlib.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32_i2c.h>
|
|
-#include <stm32mp_common.h>
|
|
#include <utils.h>
|
|
|
|
/* STM32 I2C registers offsets */
|
|
@@ -40,8 +39,6 @@
|
|
/*
|
|
* struct i2c_spec_s - Private I2C timing specifications.
|
|
* @rate: I2C bus speed (Hz)
|
|
- * @rate_min: 80% of I2C bus speed (Hz)
|
|
- * @rate_max: 120% of I2C bus speed (Hz)
|
|
* @fall_max: Max fall time of both SDA and SCL signals (ns)
|
|
* @rise_max: Max rise time of both SDA and SCL signals (ns)
|
|
* @hddat_min: Min data hold time (ns)
|
|
@@ -52,8 +49,6 @@
|
|
*/
|
|
struct i2c_spec_s {
|
|
uint32_t rate;
|
|
- uint32_t rate_min;
|
|
- uint32_t rate_max;
|
|
uint32_t fall_max;
|
|
uint32_t rise_max;
|
|
uint32_t hddat_min;
|
|
@@ -87,10 +82,9 @@ struct i2c_timing_s {
|
|
* [1] https://www.i2c-bus.org/specification/
|
|
*/
|
|
static const struct i2c_spec_s i2c_specs[] = {
|
|
- [I2C_SPEED_STANDARD] = {
|
|
+ /* Standard - 100KHz */
|
|
+ {
|
|
.rate = STANDARD_RATE,
|
|
- .rate_min = (STANDARD_RATE * 80) / 100,
|
|
- .rate_max = (STANDARD_RATE * 120) / 100,
|
|
.fall_max = 300,
|
|
.rise_max = 1000,
|
|
.hddat_min = 0,
|
|
@@ -99,10 +93,9 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
.l_min = 4700,
|
|
.h_min = 4000,
|
|
},
|
|
- [I2C_SPEED_FAST] = {
|
|
+ /* Fast - 400KHz */
|
|
+ {
|
|
.rate = FAST_RATE,
|
|
- .rate_min = (FAST_RATE * 80) / 100,
|
|
- .rate_max = (FAST_RATE * 120) / 100,
|
|
.fall_max = 300,
|
|
.rise_max = 300,
|
|
.hddat_min = 0,
|
|
@@ -111,10 +104,9 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
.l_min = 1300,
|
|
.h_min = 600,
|
|
},
|
|
- [I2C_SPEED_FAST_PLUS] = {
|
|
+ /* FastPlus - 1MHz */
|
|
+ {
|
|
.rate = FAST_PLUS_RATE,
|
|
- .rate_min = (FAST_PLUS_RATE * 80) / 100,
|
|
- .rate_max = (FAST_PLUS_RATE * 120) / 100,
|
|
.fall_max = 100,
|
|
.rise_max = 120,
|
|
.hddat_min = 0,
|
|
@@ -125,9 +117,6 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
},
|
|
};
|
|
|
|
-static uint32_t saved_timing;
|
|
-static unsigned long saved_frequency;
|
|
-
|
|
static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
|
|
uint16_t dev_addr, uint16_t mem_addr,
|
|
uint16_t mem_add_size,
|
|
@@ -162,6 +151,21 @@ static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
|
|
hi2c->i2c_state = I2C_STATE_READY;
|
|
}
|
|
|
|
+static const struct i2c_spec_s *get_specs(uint32_t rate)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) {
|
|
+ if (rate <= i2c_specs[i].rate) {
|
|
+ return &i2c_specs[i];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* NOT REACHED */
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+#define RATE_MIN(rate) (((rate) / 100U) * 80U)
|
|
/*
|
|
* @brief Compute the I2C device timings.
|
|
* @param init: Ref to the initialization configuration structure
|
|
@@ -172,7 +176,7 @@ static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
|
|
static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
uint32_t clock_src, uint32_t *timing)
|
|
{
|
|
- enum i2c_speed_e mode = init->speed_mode;
|
|
+ const struct i2c_spec_s *specs;
|
|
uint32_t speed_freq;
|
|
uint32_t i2cclk = udiv_round_nearest(I2C_NSEC_PER_SEC, clock_src);
|
|
uint32_t i2cbus;
|
|
@@ -196,24 +200,21 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
int s = -1;
|
|
struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX];
|
|
|
|
- switch (mode) {
|
|
- case I2C_SPEED_STANDARD ... I2C_SPEED_FAST_PLUS:
|
|
- break;
|
|
- default:
|
|
- ERROR("I2C speed out of bound {%d/%d}\n",
|
|
- mode, I2C_SPEED_FAST_PLUS);
|
|
+ specs = get_specs(init->bus_rate);
|
|
+ if (specs == NULL) {
|
|
+ ERROR("I2C speed out of bound {%d}\n", init->bus_rate);
|
|
return -EINVAL;
|
|
}
|
|
|
|
- speed_freq = i2c_specs[mode].rate;
|
|
+ speed_freq = specs->rate;
|
|
i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq);
|
|
clk_error_prev = INT_MAX;
|
|
|
|
- if ((init->rise_time > i2c_specs[mode].rise_max) ||
|
|
- (init->fall_time > i2c_specs[mode].fall_max)) {
|
|
+ if ((init->rise_time > specs->rise_max) ||
|
|
+ (init->fall_time > specs->fall_max)) {
|
|
ERROR(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
|
|
- init->rise_time, i2c_specs[mode].rise_max,
|
|
- init->fall_time, i2c_specs[mode].fall_max);
|
|
+ init->rise_time, specs->rise_max,
|
|
+ init->fall_time, specs->fall_max);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -230,13 +231,13 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0);
|
|
dnf_delay = init->digital_filter_coef * i2cclk;
|
|
|
|
- sdadel_min = i2c_specs[mode].hddat_min + init->fall_time -
|
|
+ sdadel_min = specs->hddat_min + init->fall_time -
|
|
af_delay_min - ((init->digital_filter_coef + 3) * i2cclk);
|
|
|
|
- sdadel_max = i2c_specs[mode].vddat_max - init->rise_time -
|
|
+ sdadel_max = specs->vddat_max - init->rise_time -
|
|
af_delay_max - ((init->digital_filter_coef + 4) * i2cclk);
|
|
|
|
- scldel_min = init->rise_time + i2c_specs[mode].sudat_min;
|
|
+ scldel_min = init->rise_time + specs->sudat_min;
|
|
|
|
if (sdadel_min < 0) {
|
|
sdadel_min_u = 0;
|
|
@@ -290,8 +291,8 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
}
|
|
|
|
tsync = af_delay_min + dnf_delay + (2 * i2cclk);
|
|
- clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min;
|
|
- clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max;
|
|
+ clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate);
|
|
+ clk_min = I2C_NSEC_PER_SEC / specs->rate;
|
|
|
|
/*
|
|
* Among prescaler possibilities discovered above figures out SCL Low
|
|
@@ -313,7 +314,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) {
|
|
uint32_t tscl_l = ((l + 1) * prescaler) + tsync;
|
|
|
|
- if ((tscl_l < i2c_specs[mode].l_min) ||
|
|
+ if ((tscl_l < specs->l_min) ||
|
|
(i2cclk >=
|
|
((tscl_l - af_delay_min - dnf_delay) / 4))) {
|
|
continue;
|
|
@@ -326,7 +327,7 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
init->fall_time;
|
|
|
|
if ((tscl >= clk_min) && (tscl <= clk_max) &&
|
|
- (tscl_h >= i2c_specs[mode].h_min) &&
|
|
+ (tscl_h >= specs->h_min) &&
|
|
(i2cclk < tscl_h)) {
|
|
int clk_error = tscl - i2cbus;
|
|
|
|
@@ -366,6 +367,19 @@ static int i2c_compute_timing(struct stm32_i2c_init_s *init,
|
|
return 0;
|
|
}
|
|
|
|
+static uint32_t get_lower_rate(uint32_t rate)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--) {
|
|
+ if (rate > i2c_specs[i].rate) {
|
|
+ return i2c_specs[i].rate;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return i2c_specs[0].rate;
|
|
+}
|
|
+
|
|
/*
|
|
* @brief Setup the I2C device timings.
|
|
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
|
@@ -379,9 +393,9 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
uint32_t *timing)
|
|
{
|
|
int rc = 0;
|
|
- unsigned long clock_src;
|
|
+ uint32_t clock_src;
|
|
|
|
- clock_src = stm32mp_clk_get_rate(hi2c->clock);
|
|
+ clock_src = (uint32_t)stm32mp_clk_get_rate(hi2c->clock);
|
|
if (clock_src == 0U) {
|
|
ERROR("I2C clock rate is 0\n");
|
|
return -EINVAL;
|
|
@@ -391,8 +405,8 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
* If the timing has already been computed, and the frequency is the
|
|
* same as when it was computed, then use the saved timing.
|
|
*/
|
|
- if (clock_src == saved_frequency) {
|
|
- *timing = saved_timing;
|
|
+ if (clock_src == hi2c->saved_frequency) {
|
|
+ *timing = hi2c->saved_timing;
|
|
return 0;
|
|
}
|
|
|
|
@@ -400,10 +414,10 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
rc = i2c_compute_timing(init, clock_src, timing);
|
|
if (rc != 0) {
|
|
ERROR("Failed to compute I2C timings\n");
|
|
- if (init->speed_mode > I2C_SPEED_STANDARD) {
|
|
- init->speed_mode--;
|
|
+ if (init->bus_rate > STANDARD_RATE) {
|
|
+ init->bus_rate = get_lower_rate(init->bus_rate);
|
|
WARN("Downgrade I2C speed to %uHz)\n",
|
|
- i2c_specs[init->speed_mode].rate);
|
|
+ init->bus_rate);
|
|
} else {
|
|
break;
|
|
}
|
|
@@ -415,16 +429,16 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
return rc;
|
|
}
|
|
|
|
- VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%li)\n",
|
|
- init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src);
|
|
+ VERBOSE("I2C Freq(%i), Clk Source(%i)\n",
|
|
+ init->bus_rate, clock_src);
|
|
VERBOSE("I2C Rise(%i) and Fall(%i) Time\n",
|
|
init->rise_time, init->fall_time);
|
|
VERBOSE("I2C Analog Filter(%s), DNF(%i)\n",
|
|
(init->analog_filter ? "On" : "Off"),
|
|
init->digital_filter_coef);
|
|
|
|
- saved_timing = *timing;
|
|
- saved_frequency = clock_src;
|
|
+ hi2c->saved_timing = *timing;
|
|
+ hi2c->saved_frequency = clock_src;
|
|
|
|
return 0;
|
|
}
|
|
@@ -469,49 +483,30 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
|
|
/*
|
|
* @brief Get I2C setup information from the device tree and set pinctrl
|
|
* configuration.
|
|
- * @param fdt: Pointer to the device tree
|
|
* @param node: I2C node offset
|
|
* @param init: Ref to the initialization configuration structure
|
|
* @retval 0 if OK, negative value else
|
|
*/
|
|
-int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
|
|
- struct stm32_i2c_init_s *init)
|
|
+int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init)
|
|
{
|
|
- const fdt32_t *cuint;
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
|
|
- if (cuint == NULL) {
|
|
- init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
|
|
- } else {
|
|
- init->rise_time = fdt32_to_cpu(*cuint);
|
|
- }
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
|
|
- if (cuint == NULL) {
|
|
- init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
|
|
- } else {
|
|
- init->fall_time = fdt32_to_cpu(*cuint);
|
|
- }
|
|
-
|
|
- cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
|
|
- if (cuint == NULL) {
|
|
- init->speed_mode = STM32_I2C_SPEED_DEFAULT;
|
|
- } else {
|
|
- switch (fdt32_to_cpu(*cuint)) {
|
|
- case STANDARD_RATE:
|
|
- init->speed_mode = I2C_SPEED_STANDARD;
|
|
- break;
|
|
- case FAST_RATE:
|
|
- init->speed_mode = I2C_SPEED_FAST;
|
|
- break;
|
|
- case FAST_PLUS_RATE:
|
|
- init->speed_mode = I2C_SPEED_FAST_PLUS;
|
|
- break;
|
|
- default:
|
|
- init->speed_mode = STM32_I2C_SPEED_DEFAULT;
|
|
- break;
|
|
- }
|
|
+ uint32_t read_val;
|
|
+
|
|
+ init->rise_time = fdt_read_uint32_default(node,
|
|
+ "i2c-scl-rising-time-ns",
|
|
+ STM32_I2C_RISE_TIME_DEFAULT);
|
|
+
|
|
+ init->fall_time = fdt_read_uint32_default(node,
|
|
+ "i2c-scl-falling-time-ns",
|
|
+ STM32_I2C_FALL_TIME_DEFAULT);
|
|
+
|
|
+ read_val = fdt_read_uint32_default(node, "clock-frequency",
|
|
+ STANDARD_RATE);
|
|
+ if (read_val > FAST_PLUS_RATE) {
|
|
+ ERROR("Invalid bus speed (%i > %i)\n", read_val,
|
|
+ FAST_PLUS_RATE);
|
|
+ return -FDT_ERR_BADVALUE;
|
|
}
|
|
+ init->bus_rate = read_val;
|
|
|
|
return dt_set_pinctrl_config(node);
|
|
}
|
|
diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c
|
|
index a0871f6..878cfa3 100644
|
|
--- a/drivers/st/io/io_programmer_st_usb.c
|
|
+++ b/drivers/st/io/io_programmer_st_usb.c
|
|
@@ -1,13 +1,12 @@
|
|
/*
|
|
- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <arch_helpers.h>
|
|
#include <assert.h>
|
|
-#include <boot_api.h>
|
|
#include <debug.h>
|
|
#include <io_driver.h>
|
|
#include <io_programmer.h>
|
|
@@ -16,10 +15,7 @@
|
|
#include <io_storage.h>
|
|
#include <platform_def.h>
|
|
#include <stm32_iwdg.h>
|
|
-#include <stm32mp_auth.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <string.h>
|
|
-#include <usb_ctx.h>
|
|
#include <usb_st_dfu.h>
|
|
|
|
static uint8_t first_usb_buffer[USB_DFU_MAX_XFER_SIZE + 1] __aligned(4);
|
|
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
|
|
index fde6269..8d53a0d 100644
|
|
--- a/drivers/st/io/io_stm32image.c
|
|
+++ b/drivers/st/io/io_stm32image.c
|
|
@@ -1,11 +1,10 @@
|
|
/*
|
|
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <assert.h>
|
|
-#include <boot_api.h>
|
|
#include <debug.h>
|
|
#include <errno.h>
|
|
#include <io_driver.h>
|
|
@@ -13,7 +12,6 @@
|
|
#include <io_storage.h>
|
|
#include <platform.h>
|
|
#include <platform_def.h>
|
|
-#include <stm32mp_auth.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <utils.h>
|
|
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
|
|
index 1b5bfe3..ef23bfc 100644
|
|
--- a/drivers/st/iwdg/stm32_iwdg.c
|
|
+++ b/drivers/st/iwdg/stm32_iwdg.c
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -17,8 +17,6 @@
|
|
#include <platform_def.h>
|
|
#include <stm32_iwdg.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <string.h>
|
|
#include <utils.h>
|
|
|
|
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
|
|
index aab0582..df9ba63 100644
|
|
--- a/drivers/st/mmc/stm32_sdmmc2.c
|
|
+++ b/drivers/st/mmc/stm32_sdmmc2.c
|
|
@@ -17,8 +17,6 @@
|
|
#include <platform_def.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32_sdmmc2.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <stm32mp_reset.h>
|
|
#include <string.h>
|
|
#include <utils.h>
|
|
@@ -49,6 +47,7 @@
|
|
|
|
/* SDMMC power control register */
|
|
#define SDMMC_POWER_PWRCTRL GENMASK(1, 0)
|
|
+#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1)
|
|
#define SDMMC_POWER_DIRPOL BIT(4)
|
|
|
|
/* SDMMC clock control register */
|
|
@@ -115,6 +114,13 @@
|
|
#define TIMEOUT_10_MS ms2tick(10)
|
|
#define TIMEOUT_1_S s2tick(1)
|
|
|
|
+/* Power cycle delays in ms */
|
|
+#define VCC_POWER_OFF_DELAY 2
|
|
+#define VCC_POWER_ON_DELAY 2
|
|
+#define POWER_CYCLE_DELAY 2
|
|
+#define POWER_OFF_DELAY 2
|
|
+#define POWER_ON_DELAY 1
|
|
+
|
|
#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
|
|
|
|
static void stm32_sdmmc2_init(void);
|
|
@@ -136,6 +142,8 @@ static const struct mmc_ops stm32_sdmmc2_ops = {
|
|
|
|
static struct stm32_sdmmc2_params sdmmc2_params;
|
|
|
|
+static bool next_cmd_is_acmd;
|
|
+
|
|
#pragma weak plat_sdmmc2_use_dma
|
|
bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
|
|
{
|
|
@@ -173,6 +181,26 @@ static void stm32_sdmmc2_init(void)
|
|
freq = MIN(sdmmc2_params.max_freq, STM32MP_MMC_INIT_FREQ);
|
|
}
|
|
|
|
+ if (sdmmc2_params.vmmc_regu.id != -1) {
|
|
+ stm32mp_regulator_register(&sdmmc2_params.vmmc_regu);
|
|
+ stm32mp_regulator_disable(&sdmmc2_params.vmmc_regu);
|
|
+ }
|
|
+
|
|
+ mdelay(VCC_POWER_OFF_DELAY);
|
|
+
|
|
+ mmio_write_32(base + SDMMC_POWER,
|
|
+ SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol);
|
|
+ mdelay(POWER_CYCLE_DELAY);
|
|
+
|
|
+ if (sdmmc2_params.vmmc_regu.id != -1) {
|
|
+ stm32mp_regulator_enable(&sdmmc2_params.vmmc_regu);
|
|
+ }
|
|
+
|
|
+ mdelay(VCC_POWER_ON_DELAY);
|
|
+
|
|
+ mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol);
|
|
+ mdelay(POWER_OFF_DELAY);
|
|
+
|
|
clock_div = div_round_up(sdmmc2_params.clk_rate,
|
|
freq * 2);
|
|
|
|
@@ -183,7 +211,7 @@ static void stm32_sdmmc2_init(void)
|
|
mmio_write_32(base + SDMMC_POWER,
|
|
SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
|
|
|
|
- mdelay(1);
|
|
+ mdelay(POWER_ON_DELAY);
|
|
}
|
|
|
|
static int stm32_sdmmc2_stop_transfer(void)
|
|
@@ -241,6 +269,20 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
|
|
case MMC_CMD(1):
|
|
arg_reg |= OCR_POWERUP;
|
|
break;
|
|
+ case MMC_CMD(6):
|
|
+ if ((sdmmc2_params.device_info->mmc_dev_type == MMC_IS_SD_HC) &&
|
|
+ (!next_cmd_is_acmd)) {
|
|
+ cmd_reg |= SDMMC_CMDR_CMDTRANS;
|
|
+ if (sdmmc2_params.use_dma) {
|
|
+ flags_data |= SDMMC_STAR_DCRCFAIL |
|
|
+ SDMMC_STAR_DTIMEOUT |
|
|
+ SDMMC_STAR_DATAEND |
|
|
+ SDMMC_STAR_RXOVERR |
|
|
+ SDMMC_STAR_IDMATE |
|
|
+ SDMMC_STAR_DBCKEND;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
case MMC_CMD(8):
|
|
if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
|
|
cmd_reg |= SDMMC_CMDR_CMDTRANS;
|
|
@@ -278,6 +320,8 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
|
|
break;
|
|
}
|
|
|
|
+ next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55));
|
|
+
|
|
if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
|
|
mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
|
|
}
|
|
@@ -636,6 +680,7 @@ static int stm32_sdmmc2_dt_get_config(void)
|
|
int sdmmc_node;
|
|
void *fdt = NULL;
|
|
const fdt32_t *cuint;
|
|
+ struct dt_node_info dt_info;
|
|
|
|
if (fdt_get_address(&fdt) == 0) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
@@ -645,27 +690,14 @@ static int stm32_sdmmc2_dt_get_config(void)
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
|
|
- sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT);
|
|
-
|
|
- while (sdmmc_node != -FDT_ERR_NOTFOUND) {
|
|
- cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) {
|
|
- break;
|
|
- }
|
|
-
|
|
- sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node,
|
|
- DT_SDMMC2_COMPAT);
|
|
- }
|
|
-
|
|
+ sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT,
|
|
+ sdmmc2_params.reg_base);
|
|
if (sdmmc_node == -FDT_ERR_NOTFOUND) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
|
|
- if (fdt_get_status(sdmmc_node) == DT_DISABLED) {
|
|
+ dt_fill_device_info(&dt_info, sdmmc_node);
|
|
+ if (dt_info.status == DT_DISABLED) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
|
|
@@ -673,21 +705,8 @@ static int stm32_sdmmc2_dt_get_config(void)
|
|
return -FDT_ERR_BADVALUE;
|
|
}
|
|
|
|
- cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL);
|
|
- if (cuint == NULL) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
- }
|
|
-
|
|
- cuint++;
|
|
- sdmmc2_params.clock_id = fdt32_to_cpu(*cuint);
|
|
-
|
|
- cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL);
|
|
- if (cuint == NULL) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
- }
|
|
-
|
|
- cuint++;
|
|
- sdmmc2_params.reset_id = fdt32_to_cpu(*cuint);
|
|
+ sdmmc2_params.clock_id = dt_info.clock;
|
|
+ sdmmc2_params.reset_id = dt_info.reset;
|
|
|
|
if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) {
|
|
sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0;
|
|
@@ -722,6 +741,11 @@ static int stm32_sdmmc2_dt_get_config(void)
|
|
sdmmc2_params.max_freq = fdt32_to_cpu(*cuint);
|
|
}
|
|
|
|
+ cuint = fdt_getprop(fdt, sdmmc_node, "vmmc-supply", NULL);
|
|
+ if (cuint != NULL) {
|
|
+ sdmmc2_params.vmmc_regu.id = fdt32_to_cpu(*cuint);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -740,6 +764,8 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
|
|
|
|
memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
|
|
|
|
+ sdmmc2_params.vmmc_regu.id = -1;
|
|
+
|
|
if (stm32_sdmmc2_dt_get_config() != 0) {
|
|
ERROR("%s: DT error\n", __func__);
|
|
return -ENOMEM;
|
|
diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c
|
|
index 9198800..2bd076a 100644
|
|
--- a/drivers/st/nand/nand.c
|
|
+++ b/drivers/st/nand/nand.c
|
|
@@ -23,7 +23,6 @@
|
|
#include <platform.h>
|
|
#include <platform_def.h>
|
|
#include <stdint.h>
|
|
-#include <stm32mp_common.h>
|
|
#include <utils_def.h>
|
|
|
|
/* Other internal NAND driver definitions */
|
|
@@ -190,10 +189,10 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
* tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
|
|
*/
|
|
thold_att = MAX(hclkp, FMC_TALH_MIN);
|
|
- thold_att = MAX(hclkp, FMC_TCH_MIN);
|
|
- thold_att = MAX(hclkp, FMC_TCLH_MIN);
|
|
- thold_att = MAX(hclkp, FMC_TCOH_MIN);
|
|
- thold_att = MAX(hclkp, FMC_TDH_MIN);
|
|
+ thold_att = MAX(thold_att, FMC_TCH_MIN);
|
|
+ thold_att = MAX(thold_att, FMC_TCLH_MIN);
|
|
+ thold_att = MAX(thold_att, FMC_TCOH_MIN);
|
|
+ thold_att = MAX(thold_att, FMC_TDH_MIN);
|
|
if ((FMC_TWB_MAX + FMC_TIO + FMC_TSYNC > tset_mem) &&
|
|
(thold_att < FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem)) {
|
|
thold_att = FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem;
|
|
@@ -749,7 +748,7 @@ static Std_ReturnType Nand_ReadParameterPage(NAND_HandleTypeDef *hNand)
|
|
static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand)
|
|
{
|
|
NAND_IDTypeDef pNAND_ID;
|
|
- uint32_t nand_param_in_otp, result;
|
|
+ uint32_t nand_param_in_otp;
|
|
|
|
assert(hNand);
|
|
|
|
@@ -759,9 +758,7 @@ static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand)
|
|
Nand_ReadIDCode(hNand, &pNAND_ID);
|
|
|
|
/* Check if NAND parameters are stored in OTP */
|
|
- result = bsec_shadow_read_otp(&nand_param_in_otp, NAND_OTP);
|
|
- if (result != BSEC_OK) {
|
|
- ERROR("BSEC: NAND_OTP Error %i\n", result);
|
|
+ if (stm32_get_otp_value(NAND_OTP, &nand_param_in_otp) != 0) {
|
|
return STD_NOT_OK;
|
|
}
|
|
|
|
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
|
|
index c8d70db..5abd8e6 100644
|
|
--- a/drivers/st/pmic/stm32mp_pmic.c
|
|
+++ b/drivers/st/pmic/stm32mp_pmic.c
|
|
@@ -1,16 +1,16 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
+#include <assert.h>
|
|
#include <debug.h>
|
|
#include <delay_timer.h>
|
|
#include <errno.h>
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
#include <stm32_i2c.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <stm32mp_pmic.h>
|
|
#include <stpmic1.h>
|
|
#include <utils_def.h>
|
|
@@ -19,7 +19,6 @@
|
|
#define STPMIC1_LDO12356_OUTPUT_SHIFT 2
|
|
#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7))
|
|
#define STPMIC1_LDO3_DDR_SEL 31U
|
|
-#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
|
|
|
|
#define STPMIC1_BUCK_OUTPUT_SHIFT 2
|
|
#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT)
|
|
@@ -28,29 +27,43 @@
|
|
|
|
#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
|
|
|
|
+#define CMD_GET_VOLTAGE 0U
|
|
+#define CMD_CONFIG_BOOT_ON 1U
|
|
+#define CMD_CONFIG_LP 2U
|
|
+
|
|
static struct i2c_handle_s i2c_handle;
|
|
static uint32_t pmic_i2c_addr;
|
|
|
|
-static int dt_get_pmic_node(void *fdt)
|
|
+static int dt_get_pmic_node(void)
|
|
{
|
|
- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
|
|
+ static int node = -FDT_ERR_BADOFFSET;
|
|
+
|
|
+ if (node == -FDT_ERR_BADOFFSET) {
|
|
+ node = dt_get_node_by_compatible("st,stpmic1");
|
|
+ }
|
|
+
|
|
+ return node;
|
|
}
|
|
|
|
int dt_pmic_status(void)
|
|
{
|
|
+ static int status = -FDT_ERR_BADVALUE;
|
|
int node;
|
|
- void *fdt;
|
|
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
+ if (status != -FDT_ERR_BADVALUE) {
|
|
+ return status;
|
|
}
|
|
|
|
- node = dt_get_pmic_node(fdt);
|
|
+ node = dt_get_pmic_node();
|
|
if (node <= 0) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ status = -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ return status;
|
|
}
|
|
|
|
- return fdt_get_status(node);
|
|
+ status = (int)fdt_get_status(node);
|
|
+
|
|
+ return status;
|
|
}
|
|
|
|
static bool dt_pmic_is_secure(void)
|
|
@@ -62,120 +75,126 @@ static bool dt_pmic_is_secure(void)
|
|
(i2c_handle.dt_status == DT_SECURE);
|
|
}
|
|
|
|
-/*
|
|
- * Get PMIC and its I2C bus configuration from the device tree.
|
|
- * Return 0 on success, negative on error, 1 if no PMIC node is defined.
|
|
- */
|
|
-static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
|
|
- struct stm32_i2c_init_s *init)
|
|
+static int dt_pmic_get_regulator_voltage(void *fdt, int node,
|
|
+ uint16_t *voltage_mv)
|
|
{
|
|
- int pmic_node, i2c_node;
|
|
- void *fdt;
|
|
const fdt32_t *cuint;
|
|
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
- }
|
|
+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
|
|
+ if (cuint != NULL) {
|
|
+ *voltage_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
|
|
|
|
- pmic_node = dt_get_pmic_node(fdt);
|
|
- if (pmic_node < 0) {
|
|
- return 1;
|
|
+ return 0;
|
|
}
|
|
|
|
- cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
- }
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+}
|
|
|
|
- pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
|
|
- if (pmic_i2c_addr > UINT16_MAX) {
|
|
- return -EINVAL;
|
|
- }
|
|
+static int pmic_config_boot_on(void *fdt, int node, const char *regu_name)
|
|
+{
|
|
+ uint16_t voltage;
|
|
+ int status;
|
|
|
|
- i2c_node = fdt_parent_offset(fdt, pmic_node);
|
|
- if (i2c_node < 0) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ if ((fdt_getprop(fdt, node, "regulator-boot-on", NULL) == NULL) &&
|
|
+ (fdt_getprop(fdt, node, "regulator-always-on", NULL) == NULL)) {
|
|
+ return 0;
|
|
}
|
|
|
|
- dt_fill_device_info(i2c_info, i2c_node);
|
|
- if (i2c_info->base == 0U) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
- }
|
|
+ if (fdt_getprop(fdt, node, "regulator-pull-down", NULL) != NULL) {
|
|
|
|
- return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
|
|
-}
|
|
+ status = stpmic1_regulator_pull_down_set(regu_name);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
|
|
-int dt_pmic_configure_boot_on_regulators(void)
|
|
-{
|
|
- int pmic_node, regulators_node, regulator_node;
|
|
- void *fdt;
|
|
+ if (fdt_getprop(fdt, node, "st,mask-reset", NULL) != NULL) {
|
|
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- return -ENOENT;
|
|
+ status = stpmic1_regulator_mask_reset_set(regu_name);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
+ }
|
|
}
|
|
|
|
- pmic_node = dt_get_pmic_node(fdt);
|
|
- if (pmic_node < 0) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ if (dt_pmic_get_regulator_voltage(fdt, node, &voltage) < 0) {
|
|
+ return 0;
|
|
}
|
|
|
|
- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
|
|
+ status = stpmic1_regulator_voltage_set(regu_name, voltage);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
+ }
|
|
|
|
- fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
|
|
- const fdt32_t *cuint;
|
|
- const char *node_name = fdt_get_name(fdt, regulator_node, NULL);
|
|
- uint16_t voltage;
|
|
- int status;
|
|
-
|
|
-#if defined(IMAGE_BL2)
|
|
- if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on",
|
|
- NULL) == NULL) &&
|
|
- (fdt_getprop(fdt, regulator_node, "regulator-always-on",
|
|
- NULL) == NULL)) {
|
|
-#else
|
|
- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
|
|
- NULL) == NULL) {
|
|
-#endif
|
|
- continue;
|
|
+ if (!stpmic1_is_regulator_enabled(regu_name)) {
|
|
+ status = stpmic1_regulator_enable(regu_name);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
}
|
|
+ }
|
|
|
|
- if (fdt_getprop(fdt, regulator_node, "regulator-pull-down",
|
|
- NULL) != NULL) {
|
|
- int status;
|
|
+ return 0;
|
|
+}
|
|
|
|
- status = stpmic1_regulator_pull_down_set(node_name);
|
|
- if (status != 0) {
|
|
- return status;
|
|
- }
|
|
- }
|
|
+static int pmic_config_lp(void *fdt, int node, const char *node_name,
|
|
+ const char *regu_name)
|
|
+{
|
|
+ int status;
|
|
+ const fdt32_t *cuint;
|
|
+ int regulator_state_node;
|
|
+
|
|
+ status = stpmic1_powerctrl_on();
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
+ };
|
|
|
|
- if (fdt_getprop(fdt, regulator_node, "st,mask-reset",
|
|
- NULL) != NULL) {
|
|
- int status;
|
|
+ /*
|
|
+ * First, copy active configuration (Control register) to
|
|
+ * PWRCTRL Control register, even if regulator_state_node
|
|
+ * does not exist.
|
|
+ */
|
|
+ status = stpmic1_lp_copy_reg(regu_name);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
+ }
|
|
|
|
- status = stpmic1_regulator_mask_reset_set(node_name);
|
|
- if (status != 0) {
|
|
- return status;
|
|
- }
|
|
+ /* Then apply configs from regulator_state_node */
|
|
+ regulator_state_node = fdt_subnode_offset(fdt, node, node_name);
|
|
+ if (regulator_state_node <= 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (fdt_getprop(fdt, regulator_state_node, "regulator-on-in-suspend",
|
|
+ NULL) != NULL) {
|
|
+ status = stpmic1_lp_reg_on_off(regu_name, 1);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
}
|
|
+ }
|
|
|
|
- cuint = fdt_getprop(fdt, regulator_node,
|
|
- "regulator-min-microvolt", NULL);
|
|
- if (cuint == NULL) {
|
|
- continue;
|
|
+ if (fdt_getprop(fdt, regulator_state_node, "regulator-off-in-suspend",
|
|
+ NULL) != NULL) {
|
|
+ status = stpmic1_lp_reg_on_off(regu_name, 0);
|
|
+ if (status < 0) {
|
|
+ return status;
|
|
}
|
|
+ }
|
|
|
|
- /* DT uses microvolts, whereas driver awaits millivolts */
|
|
- voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
|
|
+ cuint = fdt_getprop(fdt, regulator_state_node,
|
|
+ "regulator-suspend-microvolt", NULL);
|
|
+ if (cuint != NULL) {
|
|
+ uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
|
|
|
|
- status = stpmic1_regulator_voltage_set(node_name, voltage);
|
|
- if (status != 0) {
|
|
+ status = stpmic1_lp_set_voltage(regu_name, voltage);
|
|
+ if (status < 0) {
|
|
return status;
|
|
}
|
|
+ }
|
|
|
|
- if (stpmic1_is_regulator_enabled(node_name) == 0U) {
|
|
- status = stpmic1_regulator_enable(node_name);
|
|
- if (status != 0) {
|
|
+ cuint = fdt_getprop(fdt, regulator_state_node, "regulator-mode", NULL);
|
|
+ if (cuint != NULL) {
|
|
+ if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) {
|
|
+ status = stpmic1_lp_set_mode(regu_name, 1);
|
|
+ if (status < 0) {
|
|
return status;
|
|
}
|
|
}
|
|
@@ -184,97 +203,124 @@ int dt_pmic_configure_boot_on_regulators(void)
|
|
return 0;
|
|
}
|
|
|
|
-int dt_pmic_set_lp_config(const char *node_name)
|
|
+static int pmic_operate(uint8_t command, const char *node_name,
|
|
+ uint16_t *voltage_mv)
|
|
{
|
|
- int pmic_node, regulators_node, regulator_node;
|
|
- int status;
|
|
+ int pmic_node, regulators_node, subnode;
|
|
void *fdt;
|
|
-
|
|
- if (node_name == NULL) {
|
|
- return 0;
|
|
- }
|
|
+ int ret = -EIO;
|
|
+ const char *regu_name;
|
|
|
|
if (fdt_get_address(&fdt) == 0) {
|
|
return -ENOENT;
|
|
}
|
|
|
|
- pmic_node = dt_get_pmic_node(fdt);
|
|
+ pmic_node = dt_get_pmic_node();
|
|
if (pmic_node < 0) {
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ return -ENOENT;
|
|
}
|
|
|
|
- status = stpmic1_powerctrl_on();
|
|
- if (status != 0) {
|
|
- return status;
|
|
- };
|
|
-
|
|
regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
|
|
|
|
- fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
|
|
- const fdt32_t *cuint;
|
|
- const char *reg_name;
|
|
- int regulator_state_node;
|
|
+ fdt_for_each_subnode(subnode, fdt, regulators_node) {
|
|
+ regu_name = fdt_get_name(fdt, subnode, NULL);
|
|
|
|
- /*
|
|
- * First, copy active configuration (Control register) to
|
|
- * PWRCTRL Control register, even if regulator_state_node
|
|
- * does not exist.
|
|
- */
|
|
- reg_name = fdt_get_name(fdt, regulator_node, NULL);
|
|
- status = stpmic1_lp_copy_reg(reg_name);
|
|
- if (status != 0) {
|
|
- return status;
|
|
- }
|
|
+ switch (command) {
|
|
+ case CMD_GET_VOLTAGE:
|
|
+ assert(node_name != NULL);
|
|
+ assert(voltage_mv != NULL);
|
|
|
|
- /* Then apply configs from regulator_state_node */
|
|
- regulator_state_node = fdt_subnode_offset(fdt,
|
|
- regulator_node,
|
|
- node_name);
|
|
- if (regulator_state_node <= 0) {
|
|
- continue;
|
|
- }
|
|
+ if (strcmp(regu_name, node_name) != 0) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- if (fdt_getprop(fdt, regulator_state_node,
|
|
- "regulator-on-in-suspend", NULL) != NULL) {
|
|
- status = stpmic1_lp_reg_on_off(reg_name, 1);
|
|
- if (status != 0) {
|
|
- return status;
|
|
+ ret = dt_pmic_get_regulator_voltage(fdt, subnode,
|
|
+ voltage_mv);
|
|
+ if (ret < 0) {
|
|
+ return -ENXIO;
|
|
}
|
|
- }
|
|
|
|
- if (fdt_getprop(fdt, regulator_state_node,
|
|
- "regulator-off-in-suspend", NULL) != NULL) {
|
|
- status = stpmic1_lp_reg_on_off(reg_name, 0);
|
|
- if (status != 0) {
|
|
- return status;
|
|
+ return ret;
|
|
+
|
|
+ case CMD_CONFIG_BOOT_ON:
|
|
+ ret = pmic_config_boot_on(fdt, subnode, regu_name);
|
|
+ if (ret < 0) {
|
|
+ return ret;
|
|
}
|
|
- }
|
|
+ break;
|
|
|
|
- cuint = fdt_getprop(fdt, regulator_state_node,
|
|
- "regulator-suspend-microvolt", NULL);
|
|
- if (cuint != NULL) {
|
|
- uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) /
|
|
- 1000U);
|
|
+ case CMD_CONFIG_LP:
|
|
+ assert(node_name != NULL);
|
|
|
|
- status = stpmic1_lp_set_voltage(reg_name, voltage);
|
|
- if (status != 0) {
|
|
- return status;
|
|
+ ret = pmic_config_lp(fdt, subnode, node_name,
|
|
+ regu_name);
|
|
+ if (ret < 0) {
|
|
+ return ret;
|
|
}
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return -EINVAL;
|
|
}
|
|
+ }
|
|
|
|
- cuint = fdt_getprop(fdt, regulator_state_node,
|
|
- "regulator-mode", NULL);
|
|
- if (cuint != NULL) {
|
|
- if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) {
|
|
- status = stpmic1_lp_set_mode(reg_name, 1);
|
|
- if (status != 0) {
|
|
- return status;
|
|
- }
|
|
- }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get PMIC and its I2C bus configuration from the device tree.
|
|
+ * Return 0 on success, negative on error, 1 if no PMIC node is defined.
|
|
+ */
|
|
+static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
|
|
+ struct stm32_i2c_init_s *init)
|
|
+{
|
|
+ static int i2c_node = -FDT_ERR_NOTFOUND;
|
|
+ int pmic_node;
|
|
+ void *fdt;
|
|
+ const fdt32_t *cuint;
|
|
+
|
|
+ if (i2c_node == -FDT_ERR_NOTFOUND) {
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ pmic_node = dt_get_pmic_node();
|
|
+ if (pmic_node < 0) {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
|
|
+ if (cuint == NULL) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
|
|
+ if (pmic_i2c_addr > UINT16_MAX) {
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+ }
|
|
+
|
|
+ i2c_node = fdt_parent_offset(fdt, pmic_node);
|
|
+ if (i2c_node < 0) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
- return 0;
|
|
+ dt_fill_device_info(i2c_info, i2c_node);
|
|
+ if (i2c_info->base == 0U) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ return stm32_i2c_get_setup_from_fdt(i2c_node, init);
|
|
+}
|
|
+
|
|
+int pmic_configure_boot_on_regulators(void)
|
|
+{
|
|
+ return pmic_operate(CMD_CONFIG_BOOT_ON, NULL, NULL);
|
|
+}
|
|
+
|
|
+int pmic_set_lp_config(const char *node_name)
|
|
+{
|
|
+ return pmic_operate(CMD_CONFIG_LP, node_name, NULL);
|
|
}
|
|
|
|
/*
|
|
@@ -371,43 +417,111 @@ static void register_secure_pmic(void)
|
|
stm32mp_register_secure_periph_iomem(i2c_handle.i2c_base_addr);
|
|
}
|
|
|
|
-void initialize_pmic(void)
|
|
+static int pmic_regulator_enable(struct stm32mp_regulator *regu)
|
|
{
|
|
- unsigned long pmic_version;
|
|
+ void *fdt;
|
|
+ const char *node_name;
|
|
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id),
|
|
+ NULL);
|
|
+
|
|
+ return stpmic1_regulator_enable(node_name);
|
|
+}
|
|
+
|
|
+static int pmic_regulator_disable(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ void *fdt;
|
|
+ const char *node_name;
|
|
+
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ node_name = fdt_get_name(fdt, fdt_node_offset_by_phandle(fdt, regu->id),
|
|
+ NULL);
|
|
+
|
|
+ return stpmic1_regulator_disable(node_name);
|
|
+}
|
|
+
|
|
+static const struct stm32mp_regulator_ops pmic_regu_ops = {
|
|
+ .enable = pmic_regulator_enable,
|
|
+ .disable = pmic_regulator_disable,
|
|
+};
|
|
+
|
|
+bool is_pmic_regulator(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ void *fdt;
|
|
+ int parent_node;
|
|
+
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ parent_node = fdt_parent_offset(fdt,
|
|
+ fdt_node_offset_by_phandle(fdt,
|
|
+ regu->id));
|
|
+ return (fdt_node_check_compatible(fdt, parent_node,
|
|
+ "st,stpmic1-regulators") == 0);
|
|
+}
|
|
+
|
|
+void bind_pmic_regulator(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ regu->ops = &pmic_regu_ops;
|
|
+}
|
|
+
|
|
+void initialize_pmic(void)
|
|
+{
|
|
if (!initialize_pmic_i2c()) {
|
|
VERBOSE("No PMIC\n");
|
|
register_non_secure_pmic();
|
|
return;
|
|
}
|
|
|
|
- if (stpmic1_get_version(&pmic_version) != 0) {
|
|
- ERROR("Failed to access PMIC\n");
|
|
- panic();
|
|
- }
|
|
-
|
|
- INFO("PMIC version = 0x%02lx\n", pmic_version);
|
|
- stpmic1_dump_regulators();
|
|
-
|
|
if (dt_pmic_is_secure()) {
|
|
register_secure_pmic();
|
|
} else {
|
|
VERBOSE("PMIC is not secure-only hence assumed non secure\n");
|
|
register_non_secure_pmic();
|
|
}
|
|
+}
|
|
|
|
-#if defined(IMAGE_BL2)
|
|
- if (dt_pmic_configure_boot_on_regulators() != 0) {
|
|
+void configure_pmic(void)
|
|
+{
|
|
+ if (pmic_configure_boot_on_regulators() < 0) {
|
|
panic();
|
|
};
|
|
-#endif
|
|
}
|
|
|
|
+#if DEBUG
|
|
+void print_pmic_info_and_debug(void)
|
|
+{
|
|
+ unsigned long pmic_version;
|
|
+
|
|
+ if (stpmic1_get_version(&pmic_version) != 0) {
|
|
+ ERROR("Failed to access PMIC\n");
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ INFO("PMIC version = 0x%02lx\n", pmic_version);
|
|
+ stpmic1_dump_regulators();
|
|
+}
|
|
+#endif
|
|
+
|
|
int pmic_ddr_power_init(enum ddr_type ddr_type)
|
|
{
|
|
bool buck3_at_1v8 = false;
|
|
uint8_t read_val;
|
|
int status;
|
|
+ uint16_t buck2_mv;
|
|
+ uint16_t ldo3_mv;
|
|
+
|
|
+ if (pmic_operate(CMD_GET_VOLTAGE, "buck2", &buck2_mv) != 0) {
|
|
+ return -EPERM;
|
|
+ }
|
|
|
|
switch (ddr_type) {
|
|
case STM32MP_DDR3:
|
|
@@ -427,7 +541,7 @@ int pmic_ddr_power_init(enum ddr_type ddr_type)
|
|
return status;
|
|
}
|
|
|
|
- status = stpmic1_regulator_voltage_set("buck2", 1350);
|
|
+ status = stpmic1_regulator_voltage_set("buck2", buck2_mv);
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
@@ -477,7 +591,6 @@ int pmic_ddr_power_init(enum ddr_type ddr_type)
|
|
|
|
read_val &= ~STPMIC1_LDO3_MODE;
|
|
read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
|
|
- read_val |= STPMIC1_LDO3_1800000;
|
|
if (buck3_at_1v8) {
|
|
read_val |= STPMIC1_LDO3_MODE;
|
|
}
|
|
@@ -487,7 +600,16 @@ int pmic_ddr_power_init(enum ddr_type ddr_type)
|
|
return status;
|
|
}
|
|
|
|
- status = stpmic1_regulator_voltage_set("buck2", 1200);
|
|
+ if (pmic_operate(CMD_GET_VOLTAGE, "ldo3", &ldo3_mv) != 0) {
|
|
+ return -EPERM;
|
|
+ }
|
|
+
|
|
+ status = stpmic1_regulator_voltage_set("ldo3", ldo3_mv);
|
|
+ if (status != 0) {
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ status = stpmic1_regulator_voltage_set("buck2", buck2_mv);
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c
|
|
index 2bd2b60..463ef60 100644
|
|
--- a/drivers/st/pmic/stpmic1.c
|
|
+++ b/drivers/st/pmic/stpmic1.c
|
|
@@ -581,17 +581,19 @@ int stpmic1_regulator_enable(const char *name)
|
|
{
|
|
const struct regul_struct *regul = get_regulator_data(name);
|
|
|
|
- return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0));
|
|
+ return stpmic1_register_update(regul->control_reg, LDO_BUCK_ENABLE_MASK,
|
|
+ LDO_BUCK_ENABLE_MASK);
|
|
}
|
|
|
|
int stpmic1_regulator_disable(const char *name)
|
|
{
|
|
const struct regul_struct *regul = get_regulator_data(name);
|
|
|
|
- return stpmic1_register_update(regul->control_reg, 0, BIT(0));
|
|
+ return stpmic1_register_update(regul->control_reg, 0,
|
|
+ LDO_BUCK_ENABLE_MASK);
|
|
}
|
|
|
|
-uint8_t stpmic1_is_regulator_enabled(const char *name)
|
|
+bool stpmic1_is_regulator_enabled(const char *name)
|
|
{
|
|
uint8_t val;
|
|
const struct regul_struct *regul = get_regulator_data(name);
|
|
@@ -600,7 +602,7 @@ uint8_t stpmic1_is_regulator_enabled(const char *name)
|
|
panic();
|
|
}
|
|
|
|
- return (val & 0x1U);
|
|
+ return (val & LDO_BUCK_ENABLE_MASK) == LDO_BUCK_ENABLE_MASK;
|
|
}
|
|
|
|
int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
|
|
@@ -716,13 +718,15 @@ int stpmic1_regulator_voltage_get(const char *name)
|
|
return 0;
|
|
}
|
|
|
|
- if (stpmic1_register_read(regul->control_reg, &value))
|
|
+ if (stpmic1_register_read(regul->control_reg, &value)) {
|
|
return -1;
|
|
+ }
|
|
|
|
value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT;
|
|
|
|
- if (value > regul->voltage_table_size)
|
|
+ if (value > regul->voltage_table_size) {
|
|
return -1;
|
|
+ }
|
|
|
|
return (int)regul->voltage_table[value];
|
|
}
|
|
@@ -803,11 +807,9 @@ void stpmic1_dump_regulators(void)
|
|
|
|
int stpmic1_get_version(unsigned long *version)
|
|
{
|
|
- int rc;
|
|
uint8_t read_val;
|
|
|
|
- rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
|
|
- if (rc) {
|
|
+ if (stpmic1_register_read(VERSION_STATUS_REG, &read_val) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
diff --git a/drivers/st/qspi/io_qspi.c b/drivers/st/qspi/io_qspi.c
|
|
index b00b7d6..00a778c 100644
|
|
--- a/drivers/st/qspi/io_qspi.c
|
|
+++ b/drivers/st/qspi/io_qspi.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -13,8 +13,6 @@
|
|
#include <mmio.h>
|
|
#include <platform.h>
|
|
#include <platform_def.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <string.h>
|
|
|
|
#define QSPI_COMPAT "st,stm32f469-qspi"
|
|
diff --git a/drivers/st/regulator/stm32mp_dummy_regulator.c b/drivers/st/regulator/stm32mp_dummy_regulator.c
|
|
new file mode 100644
|
|
index 0000000..23d6892
|
|
--- /dev/null
|
|
+++ b/drivers/st/regulator/stm32mp_dummy_regulator.c
|
|
@@ -0,0 +1,27 @@
|
|
+/*
|
|
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <stm32mp_dummy_regulator.h>
|
|
+
|
|
+static int dummy_regulator_enable(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int dummy_regulator_disable(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct stm32mp_regulator_ops dummy_regu_ops = {
|
|
+ .enable = dummy_regulator_enable,
|
|
+ .disable = dummy_regulator_disable,
|
|
+};
|
|
+
|
|
+void bind_dummy_regulator(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ regu->ops = &dummy_regu_ops;
|
|
+}
|
|
diff --git a/drivers/st/regulator/stm32mp_regulator.c b/drivers/st/regulator/stm32mp_regulator.c
|
|
new file mode 100644
|
|
index 0000000..f0e4a4a
|
|
--- /dev/null
|
|
+++ b/drivers/st/regulator/stm32mp_regulator.c
|
|
@@ -0,0 +1,38 @@
|
|
+/*
|
|
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+
|
|
+#include <drivers/st/stm32mp_regulator.h>
|
|
+
|
|
+#pragma weak plat_bind_regulator
|
|
+int plat_bind_regulator(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+int stm32mp_regulator_enable(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ assert((regu->ops != NULL) && (regu->ops->enable != NULL));
|
|
+
|
|
+ return regu->ops->enable(regu);
|
|
+}
|
|
+
|
|
+int stm32mp_regulator_disable(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ assert((regu->ops != NULL) && (regu->ops->disable != NULL));
|
|
+
|
|
+ if (regu->always_on) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return regu->ops->disable(regu);
|
|
+}
|
|
+
|
|
+int stm32mp_regulator_register(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ return plat_bind_regulator(regu);
|
|
+}
|
|
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
|
|
index 2e19ef0..45fb988 100644
|
|
--- a/drivers/st/reset/stm32mp1_reset.c
|
|
+++ b/drivers/st/reset/stm32mp1_reset.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,7 +10,6 @@
|
|
#include <limits.h>
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
-#include <stm32mp_common.h>
|
|
#include <stm32mp_reset.h>
|
|
#include <utils_def.h>
|
|
|
|
diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c
|
|
index eec75b2..94d74b0 100644
|
|
--- a/drivers/st/rng/stm32_rng.c
|
|
+++ b/drivers/st/rng/stm32_rng.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -13,7 +13,6 @@
|
|
#include <platform_def.h>
|
|
#include <stdbool.h>
|
|
#include <stm32_rng.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <stm32mp_reset.h>
|
|
|
|
#define DT_RNG_COMPAT "st,stm32-rng"
|
|
diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c
|
|
index 017c46d..3f469d7 100644
|
|
--- a/drivers/st/rtc/stm32_rtc.c
|
|
+++ b/drivers/st/rtc/stm32_rtc.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -12,7 +12,6 @@
|
|
#include <spinlock.h>
|
|
#include <stm32_rtc.h>
|
|
#include <stm32mp_clkfunc.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define RTC_COMPAT "st,stm32mp1-rtc"
|
|
|
|
@@ -251,20 +250,11 @@ static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal)
|
|
* This function computes the fraction difference between two timestamps.
|
|
* Here again the returned value is in milliseconds.
|
|
******************************************************************************/
|
|
-static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur,
|
|
- struct stm32_rtc_calendar *ref)
|
|
+static signed long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur,
|
|
+ struct stm32_rtc_calendar *ref)
|
|
{
|
|
- unsigned long long val_r;
|
|
- unsigned long long val_c;
|
|
-
|
|
- val_r = stm32_rtc_get_second_fraction(ref);
|
|
- val_c = stm32_rtc_get_second_fraction(cur);
|
|
-
|
|
- if (val_c >= val_r) {
|
|
- return val_c - val_r;
|
|
- } else {
|
|
- return 1000U - val_r + val_c;
|
|
- }
|
|
+ return (signed long long)stm32_rtc_get_second_fraction(cur) -
|
|
+ (signed long long)stm32_rtc_get_second_fraction(ref);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -272,10 +262,9 @@ static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur,
|
|
* It includes seconds, minutes and hours.
|
|
* Here again the returned value is in milliseconds.
|
|
******************************************************************************/
|
|
-static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current,
|
|
- struct stm32_rtc_time *ref)
|
|
+static signed long long stm32_rtc_diff_time(struct stm32_rtc_time *current,
|
|
+ struct stm32_rtc_time *ref)
|
|
{
|
|
- signed long long diff_in_s;
|
|
signed long long curr_s;
|
|
signed long long ref_s;
|
|
|
|
@@ -287,12 +276,7 @@ static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current,
|
|
(((signed long long)ref->min +
|
|
(((signed long long)ref->hour * 60))) * 60);
|
|
|
|
- diff_in_s = curr_s - ref_s;
|
|
- if (diff_in_s < 0) {
|
|
- diff_in_s += 24 * 60 * 60;
|
|
- }
|
|
-
|
|
- return (unsigned long long)diff_in_s * 1000U;
|
|
+ return (curr_s - ref_s) * 1000;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -310,8 +294,8 @@ static bool stm32_is_a_leap_year(uint32_t year)
|
|
* It includes days, months, years, with exceptions.
|
|
* Here again the returned value is in milliseconds.
|
|
******************************************************************************/
|
|
-static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current,
|
|
- struct stm32_rtc_time *ref)
|
|
+static signed long long stm32_rtc_diff_date(struct stm32_rtc_time *current,
|
|
+ struct stm32_rtc_time *ref)
|
|
{
|
|
uint32_t diff_in_days = 0;
|
|
uint32_t m;
|
|
@@ -385,7 +369,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current,
|
|
}
|
|
}
|
|
|
|
- return (24ULL * 60U * 60U * 1000U) * (unsigned long long)diff_in_days;
|
|
+ return (24 * 60 * 60 * 1000) * (signed long long)diff_in_days;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -395,7 +379,7 @@ static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current,
|
|
unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur,
|
|
struct stm32_rtc_calendar *ref)
|
|
{
|
|
- unsigned long long diff_in_ms = 0;
|
|
+ signed long long diff_in_ms = 0;
|
|
struct stm32_rtc_time curr_t;
|
|
struct stm32_rtc_time ref_t;
|
|
|
|
@@ -412,7 +396,7 @@ unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur,
|
|
|
|
stm32mp_clk_disable(rtc_dev.clock);
|
|
|
|
- return diff_in_ms;
|
|
+ return (unsigned long long)diff_in_ms;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c
|
|
index 0bfa177..b09f122 100644
|
|
--- a/drivers/st/tamper/stm32_tamp.c
|
|
+++ b/drivers/st/tamper/stm32_tamp.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -12,8 +12,6 @@
|
|
#include <stm32_rng.h>
|
|
#include <stm32_rtc.h>
|
|
#include <stm32_tamp.h>
|
|
-#include <stm32mp_common.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define DT_TAMP_COMPAT "st,stm32-tamp"
|
|
/* STM32 Registers */
|
|
diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c
|
|
index 4c58000..f33821e 100644
|
|
--- a/drivers/st/timer/stm32_timer.c
|
|
+++ b/drivers/st/timer/stm32_timer.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -12,7 +12,6 @@
|
|
#include <platform_def.h>
|
|
#include <stdbool.h>
|
|
#include <stm32_timer.h>
|
|
-#include <stm32mp_dt.h>
|
|
|
|
#define TIM_CR1 0x00U /* Control Register 1 */
|
|
#define TIM_CR2 0x04U /* Control Register 2 */
|
|
diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c
|
|
index 34a7cbb..f56a552 100644
|
|
--- a/drivers/st/uart/io_programmer_uart.c
|
|
+++ b/drivers/st/uart/io_programmer_uart.c
|
|
@@ -1,12 +1,11 @@
|
|
/*
|
|
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <arch_helpers.h>
|
|
#include <assert.h>
|
|
-#include <boot_api.h>
|
|
#include <debug.h>
|
|
#include <errno.h>
|
|
#include <io_driver.h>
|
|
@@ -16,8 +15,6 @@
|
|
#include <io_uart.h>
|
|
#include <platform_def.h>
|
|
#include <stm32_iwdg.h>
|
|
-#include <stm32mp_auth.h>
|
|
-#include <stm32mp_dt.h>
|
|
#include <string.h>
|
|
|
|
/* USART bootloader protocol version V4.0*/
|
|
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
|
|
index 1a5c51c..4825691 100644
|
|
--- a/fdts/stm32mp15-ddr.dtsi
|
|
+++ b/fdts/stm32mp15-ddr.dtsi
|
|
@@ -5,7 +5,7 @@
|
|
|
|
/ {
|
|
soc {
|
|
- ddr: ddr@5A003000{
|
|
+ ddr: ddr@5a003000{
|
|
|
|
compatible = "st,stm32mp1-ddr";
|
|
|
|
diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts
|
|
index f081575..d852171 100644
|
|
--- a/fdts/stm32mp157a-dk1.dts
|
|
+++ b/fdts/stm32mp157a-dk1.dts
|
|
@@ -34,6 +34,7 @@
|
|
pinctrl-0 = <&i2c4_pins_a>;
|
|
i2c-scl-rising-time-ns = <185>;
|
|
i2c-scl-falling-time-ns = <20>;
|
|
+ clock-frequency = <400000>;
|
|
status = "okay";
|
|
|
|
pmic: stpmic@33 {
|
|
@@ -43,10 +44,7 @@
|
|
interrupt-controller;
|
|
#interrupt-cells = <2>;
|
|
status = "okay";
|
|
-
|
|
- st,main-control-register = <0x04>;
|
|
- st,vin-control-register = <0xc0>;
|
|
- st,usb-control-register = <0x20>;
|
|
+ wakeup-source;
|
|
|
|
regulators {
|
|
compatible = "st,stpmic1-regulators";
|
|
@@ -283,12 +281,6 @@
|
|
CLK_LPTIM45_LSE
|
|
>;
|
|
|
|
- /* VCO = 1300.0 MHz => P = 650 (CPU) */
|
|
- pll1: st,pll@0 {
|
|
- cfg = < 2 80 0 0 0 PQR(1,0,0) >;
|
|
- frac = < 0x800 >;
|
|
- };
|
|
-
|
|
/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
|
|
pll2: st,pll@1 {
|
|
cfg = < 2 65 1 0 0 PQR(1,1,1) >;
|
|
@@ -311,8 +303,7 @@
|
|
&bsec {
|
|
board_id: board_id@ec {
|
|
reg = <0xec 0x4>;
|
|
- status = "okay";
|
|
- secure-status = "okay";
|
|
+ st,non-secure-otp;
|
|
};
|
|
};
|
|
|
|
@@ -332,6 +323,24 @@
|
|
secure-status = "okay";
|
|
};
|
|
|
|
+&nvmem_layout {
|
|
+ nvmem-cells = <&part_number_otp>,
|
|
+ <&monotonic_otp>,
|
|
+ <&nand_otp>,
|
|
+ <&uid_otp>,
|
|
+ <&package_otp>,
|
|
+ <&hw2_otp>,
|
|
+ <&board_id>;
|
|
+
|
|
+ nvmem-cell-names = "part_number_otp",
|
|
+ "monotonic_otp",
|
|
+ "nand_otp",
|
|
+ "uid_otp",
|
|
+ "package_otp",
|
|
+ "hw2_otp",
|
|
+ "board_id";
|
|
+};
|
|
+
|
|
&pwr {
|
|
system_suspend_supported_soc_modes = <
|
|
STM32_PM_CSLEEP_RUN
|
|
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
|
|
index 61d5301..02c4233 100644
|
|
--- a/fdts/stm32mp157c-ed1.dts
|
|
+++ b/fdts/stm32mp157c-ed1.dts
|
|
@@ -30,6 +30,7 @@
|
|
pinctrl-0 = <&i2c4_pins_a>;
|
|
i2c-scl-rising-time-ns = <185>;
|
|
i2c-scl-falling-time-ns = <20>;
|
|
+ clock-frequency = <400000>;
|
|
status = "okay";
|
|
|
|
pmic: stpmic@33 {
|
|
@@ -39,10 +40,7 @@
|
|
interrupt-controller;
|
|
#interrupt-cells = <2>;
|
|
status = "okay";
|
|
-
|
|
- st,main-control-register = <0x04>;
|
|
- st,vin-control-register = <0xc0>;
|
|
- st,usb-control-register = <0x20>;
|
|
+ wakeup-source;
|
|
|
|
regulators {
|
|
compatible = "st,stpmic1-regulators";
|
|
@@ -288,12 +286,6 @@
|
|
CLK_LPTIM45_LSE
|
|
>;
|
|
|
|
- /* VCO = 1300.0 MHz => P = 650 (CPU) */
|
|
- pll1: st,pll@0 {
|
|
- cfg = < 2 80 0 0 0 PQR(1,0,0) >;
|
|
- frac = < 0x800 >;
|
|
- };
|
|
-
|
|
/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
|
|
pll2: st,pll@1 {
|
|
cfg = < 2 65 1 0 0 PQR(1,1,1) >;
|
|
@@ -316,8 +308,7 @@
|
|
&bsec {
|
|
board_id: board_id@ec {
|
|
reg = <0xec 0x4>;
|
|
- status = "okay";
|
|
- secure-status = "okay";
|
|
+ st,non-secure-otp;
|
|
};
|
|
};
|
|
|
|
@@ -337,6 +328,24 @@
|
|
secure-status = "okay";
|
|
};
|
|
|
|
+&nvmem_layout {
|
|
+ nvmem-cells =<&part_number_otp>,
|
|
+ <&monotonic_otp>,
|
|
+ <&nand_otp>,
|
|
+ <&uid_otp>,
|
|
+ <&package_otp>,
|
|
+ <&hw2_otp>,
|
|
+ <&board_id>;
|
|
+
|
|
+ nvmem-cell-names = "part_number_otp",
|
|
+ "monotonic_otp",
|
|
+ "nand_otp",
|
|
+ "uid_otp",
|
|
+ "package_otp",
|
|
+ "hw2_otp",
|
|
+ "board_id";
|
|
+};
|
|
+
|
|
&pwr {
|
|
system_suspend_supported_soc_modes = <
|
|
STM32_PM_CSLEEP_RUN
|
|
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
|
|
index 124ed53..b18c6c3 100644
|
|
--- a/fdts/stm32mp157c-security.dtsi
|
|
+++ b/fdts/stm32mp157c-security.dtsi
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright : STMicroelectronics 2017
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
|
|
*/
|
|
@@ -8,7 +8,7 @@
|
|
|
|
/ {
|
|
soc {
|
|
- iwdg1: watchdog@5C003000 {
|
|
+ iwdg1: watchdog@5c003000 {
|
|
compatible = "st,stm32mp1-iwdg";
|
|
reg = <0x5C003000 0x400>;
|
|
clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
|
|
@@ -18,7 +18,7 @@
|
|
secure-status = "disabled";
|
|
};
|
|
|
|
- etzpc: etzpc@5C007000 {
|
|
+ etzpc: etzpc@5c007000 {
|
|
compatible = "st,stm32-etzpc";
|
|
reg = <0x5C007000 0x400>;
|
|
clocks = <&rcc TZPC>;
|
|
@@ -26,20 +26,53 @@
|
|
secure-status = "okay";
|
|
};
|
|
|
|
- stgen: stgen@5C008000 {
|
|
+ stgen: stgen@5c008000 {
|
|
compatible = "st,stm32-stgen";
|
|
reg = <0x5C008000 0x1000>;
|
|
};
|
|
+
|
|
+ nvmem_layout: nvmem_layout@0 {
|
|
+ compatible = "st,stm32-nvmem-layout";
|
|
+
|
|
+ nvmem-cells = <&part_number_otp>,
|
|
+ <&monotonic_otp>,
|
|
+ <&nand_otp>,
|
|
+ <&uid_otp>,
|
|
+ <&package_otp>,
|
|
+ <&hw2_otp>;
|
|
+
|
|
+ nvmem-cell-names = "part_number_otp",
|
|
+ "monotonic_otp",
|
|
+ "nand_otp",
|
|
+ "uid_otp",
|
|
+ "package_otp",
|
|
+ "hw2_otp";
|
|
+ };
|
|
};
|
|
};
|
|
|
|
&bsec {
|
|
- mac_addr: mac_addr@e4 {
|
|
- reg = <0xe4 0x6>;
|
|
+ part_number_otp: part_number_otp@4 {
|
|
+ reg = <0x4 0x1>;
|
|
+ };
|
|
+ monotonic_otp: monotonic_otp@10 {
|
|
+ reg = <0x10 0x4>;
|
|
};
|
|
- /* Spare field to align on 32-bit OTP granularity */
|
|
- spare_ns_ea: spare_ns_ea@ea {
|
|
- reg = <0xea 0x2>;
|
|
+ nand_otp: nand_otp@24 {
|
|
+ reg = <0x24 0x4>;
|
|
+ };
|
|
+ uid_otp: uid_otp@34 {
|
|
+ reg = <0x34 0xc>;
|
|
+ };
|
|
+ package_otp: package_otp@40 {
|
|
+ reg = <0x40 0x4>;
|
|
+ };
|
|
+ hw2_otp: hw2_otp@48 {
|
|
+ reg = <0x48 0x4>;
|
|
+ };
|
|
+ mac_addr: mac_addr@e4 {
|
|
+ reg = <0xe4 0x8>;
|
|
+ st,non-secure-otp;
|
|
};
|
|
};
|
|
|
|
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
|
|
index e649c3a..13125b1 100644
|
|
--- a/fdts/stm32mp157c.dtsi
|
|
+++ b/fdts/stm32mp157c.dtsi
|
|
@@ -388,5 +388,22 @@
|
|
compatible = "simple-bus", "syscon", "simple-mfd";
|
|
reg = <0x5c00a000 0x400>;
|
|
};
|
|
+
|
|
+ cpu_opp_table: cpu0-opp-table {
|
|
+ compatible = "operating-points-v2";
|
|
+ opp-shared;
|
|
+
|
|
+ opp-650000000 {
|
|
+ opp-hz = /bits/ 64 <650000000>;
|
|
+ opp-microvolt = <1200000>;
|
|
+ opp-supported-hw = <0x1>;
|
|
+ };
|
|
+
|
|
+ opp-800000000 {
|
|
+ opp-hz = /bits/ 64 <800000000>;
|
|
+ opp-microvolt = <1350000>;
|
|
+ opp-supported-hw = <0x2>;
|
|
+ };
|
|
+ };
|
|
};
|
|
};
|
|
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
|
|
index 38553b9..30580ea 100644
|
|
--- a/include/drivers/mmc.h
|
|
+++ b/include/drivers/mmc.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -103,6 +103,7 @@
|
|
#define MMC_STATE_SLP 10
|
|
|
|
#define MMC_FLAG_CMD23 (U(1) << 0)
|
|
+#define MMC_FLAG_SD_CMD6 (U(1) << 1)
|
|
|
|
#define CMD8_CHECK_PATTERN U(0xAA)
|
|
#define VHS_2_7_3_6_V BIT(8)
|
|
@@ -110,6 +111,9 @@
|
|
#define SD_SCR_BUS_WIDTH_1 BIT(8)
|
|
#define SD_SCR_BUS_WIDTH_4 BIT(10)
|
|
|
|
+#define SD_SWITCH_FUNC_CHECK 0U
|
|
+#define SD_SWITCH_FUNC_SWITCH 1U
|
|
+
|
|
struct mmc_cmd {
|
|
unsigned int cmd_idx;
|
|
unsigned int cmd_arg;
|
|
@@ -209,6 +213,27 @@ struct mmc_csd_sd_v2 {
|
|
unsigned int csd_structure: 2;
|
|
};
|
|
|
|
+struct sd_switch_status {
|
|
+ unsigned short max_current;
|
|
+ unsigned short support_g6;
|
|
+ unsigned short support_g5;
|
|
+ unsigned short support_g4;
|
|
+ unsigned short support_g3;
|
|
+ unsigned short support_g2;
|
|
+ unsigned short support_g1;
|
|
+ unsigned char sel_g6_g5;
|
|
+ unsigned char sel_g4_g3;
|
|
+ unsigned char sel_g2_g1;
|
|
+ unsigned char data_struct_ver;
|
|
+ unsigned short busy_g6;
|
|
+ unsigned short busy_g5;
|
|
+ unsigned short busy_g4;
|
|
+ unsigned short busy_g3;
|
|
+ unsigned short busy_g2;
|
|
+ unsigned short busy_g1;
|
|
+ unsigned short reserved[17];
|
|
+};
|
|
+
|
|
enum mmc_device_type {
|
|
MMC_IS_EMMC,
|
|
MMC_IS_SD,
|
|
diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h
|
|
index 71a68c2..25f29de 100644
|
|
--- a/include/drivers/st/bsec.h
|
|
+++ b/include/drivers/st/bsec.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -172,6 +172,9 @@ uint32_t bsec_get_base(void);
|
|
uint32_t bsec_set_config(struct bsec_config *cfg);
|
|
uint32_t bsec_get_config(struct bsec_config *cfg);
|
|
|
|
+uint32_t bsec_find_otp_name_in_dt(const char *name, uint32_t *otp,
|
|
+ uint32_t *otp_len);
|
|
+
|
|
uint32_t bsec_shadow_register(uint32_t otp);
|
|
uint32_t bsec_read_otp(uint32_t *val, uint32_t otp);
|
|
uint32_t bsec_write_otp(uint32_t val, uint32_t otp);
|
|
diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h
|
|
index 4d5e302..7e0d93f 100644
|
|
--- a/include/drivers/st/stm32_i2c.h
|
|
+++ b/include/drivers/st/stm32_i2c.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
@@ -125,12 +125,6 @@
|
|
#define I2C_ICR_TIMOUTCF BIT(12)
|
|
#define I2C_ICR_ALERTCF BIT(13)
|
|
|
|
-enum i2c_speed_e {
|
|
- I2C_SPEED_STANDARD, /* 100 kHz */
|
|
- I2C_SPEED_FAST, /* 400 kHz */
|
|
- I2C_SPEED_FAST_PLUS, /* 1 MHz */
|
|
-};
|
|
-
|
|
#define STANDARD_RATE 100000
|
|
#define FAST_RATE 400000
|
|
#define FAST_PLUS_RATE 1000000
|
|
@@ -195,12 +189,7 @@ struct stm32_i2c_init_s {
|
|
* time in nanoseconds.
|
|
*/
|
|
|
|
- enum i2c_speed_e speed_mode; /*
|
|
- * Specifies the I2C clock source
|
|
- * frequency mode.
|
|
- * This parameter can be a value of @ref
|
|
- * i2c_speed_mode_e.
|
|
- */
|
|
+ uint32_t bus_rate; /* Specifies the I2C clock frequency */
|
|
|
|
int analog_filter; /*
|
|
* Specifies if the I2C analog noise
|
|
@@ -252,6 +241,8 @@ struct i2c_handle_s {
|
|
enum i2c_state_e i2c_state; /* Communication state */
|
|
enum i2c_mode_e i2c_mode; /* Communication mode */
|
|
uint32_t i2c_err; /* Error code */
|
|
+ uint32_t saved_timing; /* Saved timing value */
|
|
+ uint32_t saved_frequency; /* Saved frequency value */
|
|
};
|
|
|
|
#define I2C_ADDRESSINGMODE_7BIT 0x00000001U
|
|
@@ -313,8 +304,7 @@ struct i2c_handle_s {
|
|
#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */
|
|
#define STM32_I2C_DIGITAL_FILTER_MAX 16
|
|
|
|
-int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
|
|
- struct stm32_i2c_init_s *init);
|
|
+int stm32_i2c_get_setup_from_fdt(int node, struct stm32_i2c_init_s *init);
|
|
int stm32_i2c_init(struct i2c_handle_s *hi2c,
|
|
struct stm32_i2c_init_s *init_data);
|
|
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
|
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
|
|
index 7fa9c5d..c2bb7f6 100644
|
|
--- a/include/drivers/st/stm32_sdmmc2.h
|
|
+++ b/include/drivers/st/stm32_sdmmc2.h
|
|
@@ -9,6 +9,7 @@
|
|
|
|
#include <mmc.h>
|
|
#include <stdbool.h>
|
|
+#include <stm32mp_regulator.h>
|
|
|
|
struct stm32_sdmmc2_params {
|
|
uintptr_t reg_base;
|
|
@@ -23,6 +24,7 @@ struct stm32_sdmmc2_params {
|
|
unsigned int reset_id;
|
|
unsigned int max_freq;
|
|
bool use_dma;
|
|
+ struct stm32mp_regulator vmmc_regu;
|
|
};
|
|
|
|
unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
|
|
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
|
|
index 4f6930b..82f488b 100644
|
|
--- a/include/drivers/st/stm32mp1_clk.h
|
|
+++ b/include/drivers/st/stm32mp1_clk.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -12,8 +12,16 @@
|
|
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
|
|
+#define PLL1_SETTINGS_VALID_ID U(0x504C4C31) /* "PLL1" */
|
|
+
|
|
int stm32mp1_clk_probe(void);
|
|
-int stm32mp1_clk_init(void);
|
|
+int stm32mp1_clk_init(uint32_t pll1_freq_mhz);
|
|
+
|
|
+int stm32mp1_clk_compute_all_pll1_settings(uint32_t buck1_voltage);
|
|
+void stm32mp1_clk_lp_save_opp_pll1_settings(uint8_t *data, size_t size);
|
|
+void stm32mp1_clk_lp_load_opp_pll1_settings(uint8_t *data, size_t size);
|
|
+
|
|
+int stm32mp1_clk_get_maxfreq_opp(uint32_t *freq_mhz, uint32_t *voltage_mv);
|
|
|
|
bool stm32mp1_rcc_is_secure(void);
|
|
bool stm32mp1_rcc_is_mckprot(void);
|
|
@@ -47,15 +55,21 @@ unsigned int stm32mp1_clk_get_refcount(unsigned long id);
|
|
unsigned long stm32mp_clk_get_rate(unsigned long id);
|
|
unsigned long stm32mp_clk_timer_get_rate(unsigned long id);
|
|
|
|
-void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
|
|
-
|
|
bool stm32mp1_rtc_get_read_twice(void);
|
|
|
|
/* SMP protection on RCC registers access */
|
|
void stm32mp1_clk_rcc_regs_lock(void);
|
|
void stm32mp1_clk_rcc_regs_unlock(void);
|
|
|
|
+void stm32mp1_stgen_restore_counter(unsigned long long value,
|
|
+ unsigned long long offset_in_ms);
|
|
+unsigned long long stm32mp1_stgen_get_counter(void);
|
|
+
|
|
unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit);
|
|
+
|
|
+int stm32mp1_round_opp_khz(uint32_t *freq_khz);
|
|
+int stm32mp1_set_opp_khz(uint32_t freq_khz);
|
|
+
|
|
#if defined(IMAGE_BL32)
|
|
void stm32mp1_clk_mpu_suspend(void);
|
|
void stm32mp1_clk_mpu_resume(void);
|
|
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
|
|
index e928688..2361dcc 100644
|
|
--- a/include/drivers/st/stm32mp1_ddr_regs.h
|
|
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
@@ -381,6 +381,7 @@ struct stm32mp1_ddrphy {
|
|
#define DDRPHYC_PTR0_TITMSRST_OFFSET 18
|
|
#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18)
|
|
|
|
+#define DDRPHYC_ACIOCR_ACOE BIT(1)
|
|
#define DDRPHYC_ACIOCR_ACPDD BIT(3)
|
|
#define DDRPHYC_ACIOCR_ACPDR BIT(4)
|
|
#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8)
|
|
@@ -400,6 +401,7 @@ struct stm32mp1_ddrphy {
|
|
#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20)
|
|
#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20)
|
|
#define DDRPHYC_DSGCR_NL2PD BIT(24)
|
|
+#define DDRPHYC_DSGCR_CKOE BIT(28)
|
|
|
|
#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0)
|
|
#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0
|
|
diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h
|
|
index c77c0b5..c0f8694 100644
|
|
--- a/include/drivers/st/stm32mp_clkfunc.h
|
|
+++ b/include/drivers/st/stm32mp_clkfunc.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,8 +10,7 @@
|
|
#include <libfdt.h>
|
|
#include <stdbool.h>
|
|
|
|
-int fdt_get_rcc_node(void *fdt);
|
|
-uint32_t fdt_rcc_read_addr(void);
|
|
+int fdt_get_rcc_node(void);
|
|
int fdt_rcc_read_uint32_array(const char *prop_name,
|
|
uint32_t *array, uint32_t count);
|
|
uint32_t fdt_rcc_read_uint32_default(const char *prop_name,
|
|
@@ -25,4 +24,6 @@ int fdt_get_clock_id(int node);
|
|
int fdt_get_clock_id_by_name(int node, const char *name);
|
|
unsigned long fdt_get_uart_clock_freq(uintptr_t instance);
|
|
|
|
+bool fdt_is_pll1_predefined(void);
|
|
+
|
|
#endif /* STM32MP_CLKFUNC_H */
|
|
diff --git a/include/drivers/st/stm32mp_dummy_regulator.h b/include/drivers/st/stm32mp_dummy_regulator.h
|
|
new file mode 100644
|
|
index 0000000..9fd83ac
|
|
--- /dev/null
|
|
+++ b/include/drivers/st/stm32mp_dummy_regulator.h
|
|
@@ -0,0 +1,14 @@
|
|
+/*
|
|
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef STM32MP_DUMMY_REGULATOR_H
|
|
+#define STM32MP_DUMMY_REGULATOR_H
|
|
+
|
|
+#include <stm32mp_regulator.h>
|
|
+
|
|
+void bind_dummy_regulator(struct stm32mp_regulator *regu);
|
|
+
|
|
+#endif /* STM32MP_DUMMY_REGULATOR_H */
|
|
diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h
|
|
index 39c80e4..1147d00 100644
|
|
--- a/include/drivers/st/stm32mp_pmic.h
|
|
+++ b/include/drivers/st/stm32mp_pmic.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,15 +10,26 @@
|
|
#include <platform_def.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
+#include <stm32mp_regulator.h>
|
|
|
|
int dt_pmic_status(void);
|
|
-int dt_pmic_configure_boot_on_regulators(void);
|
|
-int dt_pmic_set_lp_config(const char *node_name);
|
|
+int pmic_configure_boot_on_regulators(void);
|
|
+int pmic_set_lp_config(const char *node_name);
|
|
bool initialize_pmic_i2c(void);
|
|
+bool is_pmic_regulator(struct stm32mp_regulator *regu);
|
|
+void bind_pmic_regulator(struct stm32mp_regulator *regu);
|
|
void initialize_pmic(void);
|
|
+void configure_pmic(void);
|
|
#if STM32MP1_DEBUG_ENABLE
|
|
int pmic_keep_debug_unit(void);
|
|
#endif
|
|
+#if DEBUG
|
|
+void print_pmic_info_and_debug(void);
|
|
+#else
|
|
+static inline void print_pmic_info_and_debug(void)
|
|
+{
|
|
+}
|
|
+#endif
|
|
int pmic_ddr_power_init(enum ddr_type ddr_type);
|
|
|
|
#endif /* STM32MP_PMIC_H */
|
|
diff --git a/include/drivers/st/stm32mp_regulator.h b/include/drivers/st/stm32mp_regulator.h
|
|
new file mode 100644
|
|
index 0000000..7a66b97
|
|
--- /dev/null
|
|
+++ b/include/drivers/st/stm32mp_regulator.h
|
|
@@ -0,0 +1,31 @@
|
|
+/*
|
|
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef STM32MP_REGULATOR_H
|
|
+#define STM32MP_REGULATOR_H
|
|
+
|
|
+#include <stdbool.h>
|
|
+
|
|
+struct stm32mp_regulator;
|
|
+
|
|
+struct stm32mp_regulator_ops {
|
|
+ int (*enable)(struct stm32mp_regulator *regu);
|
|
+ int (*disable)(struct stm32mp_regulator *regu);
|
|
+};
|
|
+
|
|
+struct stm32mp_regulator {
|
|
+ const struct stm32mp_regulator_ops *ops;
|
|
+ int id;
|
|
+ bool always_on;
|
|
+};
|
|
+
|
|
+int stm32mp_regulator_enable(struct stm32mp_regulator *regu);
|
|
+int stm32mp_regulator_disable(struct stm32mp_regulator *regu);
|
|
+int stm32mp_regulator_register(struct stm32mp_regulator *regu);
|
|
+
|
|
+int plat_bind_regulator(struct stm32mp_regulator *regu);
|
|
+
|
|
+#endif /* STM32MP_REGULATOR_H */
|
|
diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h
|
|
index 803a69e..50e1fa3 100644
|
|
--- a/include/drivers/st/stpmic1.h
|
|
+++ b/include/drivers/st/stpmic1.h
|
|
@@ -86,15 +86,15 @@
|
|
#define ITSOURCE4_REG 0xB3U
|
|
|
|
/* Registers masks */
|
|
-#define LDO_VOLTAGE_MASK 0x7CU
|
|
-#define BUCK_VOLTAGE_MASK 0xFCU
|
|
+#define LDO_VOLTAGE_MASK GENMASK(6, 2)
|
|
+#define BUCK_VOLTAGE_MASK GENMASK(7, 2)
|
|
#define LDO_BUCK_VOLTAGE_SHIFT 2
|
|
-#define LDO_BUCK_ENABLE_MASK 0x01U
|
|
-#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U
|
|
+#define LDO_BUCK_ENABLE_MASK BIT(0)
|
|
+#define LDO_BUCK_HPLP_ENABLE_MASK BIT(1)
|
|
#define LDO_BUCK_HPLP_SHIFT 1
|
|
-#define LDO_BUCK_RANK_MASK 0x01U
|
|
-#define LDO_BUCK_RESET_MASK 0x01U
|
|
-#define LDO_BUCK_PULL_DOWN_MASK 0x03U
|
|
+#define LDO_BUCK_RANK_MASK BIT(0)
|
|
+#define LDO_BUCK_RESET_MASK BIT(0)
|
|
+#define LDO_BUCK_PULL_DOWN_MASK GENMASK(1, 0)
|
|
|
|
/* Pull down register */
|
|
#define BUCK1_PULL_DOWN_SHIFT 0
|
|
@@ -135,12 +135,12 @@
|
|
/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */
|
|
#define SWIN_DETECTOR_ENABLED BIT(7)
|
|
#define SWOUT_DETECTOR_ENABLED BIT(6)
|
|
-#define VINLOW_HYST_MASK 0x3
|
|
+#define VINLOW_HYST_MASK GENMASK(1, 0)
|
|
#define VINLOW_HYST_SHIFT 4
|
|
-#define VINLOW_THRESHOLD_MASK 0x7
|
|
+#define VINLOW_THRESHOLD_MASK GENMASK(2, 0)
|
|
#define VINLOW_THRESHOLD_SHIFT 1
|
|
-#define VINLOW_ENABLED 0x01
|
|
-#define VINLOW_CTRL_REG_MASK 0xFF
|
|
+#define VINLOW_ENABLED BIT(0)
|
|
+#define VINLOW_CTRL_REG_MASK GENMASK(7, 0)
|
|
|
|
/* USB Control Register */
|
|
#define BOOST_OVP_DISABLED BIT(7)
|
|
@@ -156,7 +156,7 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value);
|
|
int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
|
|
int stpmic1_regulator_enable(const char *name);
|
|
int stpmic1_regulator_disable(const char *name);
|
|
-uint8_t stpmic1_is_regulator_enabled(const char *name);
|
|
+bool stpmic1_is_regulator_enabled(const char *name);
|
|
int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts);
|
|
int stpmic1_regulator_voltage_get(const char *name);
|
|
int stpmic1_regulator_pull_down_set(const char *name);
|
|
diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c
|
|
index 2cf01f6..9a10f7b 100644
|
|
--- a/lib/usb/usb_st_dfu.c
|
|
+++ b/lib/usb/usb_st_dfu.c
|
|
@@ -759,7 +759,7 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req)
|
|
break;
|
|
|
|
case DFU_DETACH:
|
|
- INFO("Receive DFU detach\n");
|
|
+ usb_dfu_detach(pdev, req);
|
|
break;
|
|
|
|
default:
|
|
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
|
|
index d483c18..93f8916 100644
|
|
--- a/plat/st/common/bl2_io_storage.c
|
|
+++ b/plat/st/common/bl2_io_storage.c
|
|
@@ -89,7 +89,6 @@ static QSPI_HandleTypeDef qspi_dev_spec = {
|
|
#endif
|
|
|
|
#if STM32MP_UART_PROGRAMMER
|
|
-/* uart*/
|
|
static const io_dev_connector_t *uart_dev_con;
|
|
|
|
static UART_HandleTypeDef uart_programmer = {
|
|
@@ -112,7 +111,6 @@ static const io_dev_connector_t *usb_dev_con;
|
|
#endif /*STM32MP_USB*/
|
|
|
|
#if STM32MP_FMC_NAND
|
|
-/* nand */
|
|
static const io_dev_connector_t *nand_dev_con;
|
|
static NAND_HandleTypeDef nand_dev_spec;
|
|
#endif
|
|
@@ -305,102 +303,6 @@ static void print_boot_device(boot_api_context_t *boot_context)
|
|
}
|
|
}
|
|
|
|
-#if STM32MP_SDMMC
|
|
-static void print_bootrom_sd_status(boot_api_context_t *boot_context)
|
|
-{
|
|
- if (boot_context->sd_err_internal_timeout_cnt != 0U) {
|
|
- WARN("BootROM: %d timeout issues\n",
|
|
- boot_context->sd_err_internal_timeout_cnt);
|
|
- }
|
|
-
|
|
- if (boot_context->sd_err_dcrc_fail_cnt != 0U) {
|
|
- WARN("BootROM: %d DCRCFAIL error\n",
|
|
- boot_context->sd_err_dcrc_fail_cnt);
|
|
- }
|
|
-
|
|
- if (boot_context->sd_err_dtimeout_cnt != 0U) {
|
|
- WARN("BootROM: %d DTIMEOUT error\n",
|
|
- boot_context->sd_err_dtimeout_cnt);
|
|
- }
|
|
-
|
|
- if (boot_context->sd_err_ctimeout_cnt != 0U) {
|
|
- WARN("BootROM: %d CTIMEOUT error\n",
|
|
- boot_context->sd_err_ctimeout_cnt);
|
|
- }
|
|
-
|
|
- if (boot_context->sd_err_ccrc_fail_cnt != 0U) {
|
|
- WARN("BootROM: %d CCRCFAIL error count\n",
|
|
- boot_context->sd_err_ccrc_fail_cnt);
|
|
- }
|
|
-
|
|
- if (boot_context->sd_overall_retry_cnt != 0U) {
|
|
- WARN("BootROM: %d command retries\n",
|
|
- boot_context->sd_overall_retry_cnt);
|
|
- }
|
|
-}
|
|
-#endif
|
|
-
|
|
-#if STM32MP_EMMC
|
|
-static void print_bootrom_emmc_status(boot_api_context_t *boot_context)
|
|
-{
|
|
- INFO("BootROM: %d (0x%x) bytes copied from eMMC\n",
|
|
- boot_context->emmc_nbbytes_rxcopied_tosysram_download_area,
|
|
- boot_context->emmc_nbbytes_rxcopied_tosysram_download_area);
|
|
-
|
|
- if (boot_context->emmc_error_status !=
|
|
- BOOT_API_CTX_EMMC_ERROR_STATUS_NONE) {
|
|
- WARN("BootROM eMMC error:\n");
|
|
- switch (boot_context->emmc_error_status) {
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT:
|
|
- WARN(" CMD timeout\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT:
|
|
- WARN(" ACK timeout\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL:
|
|
- WARN(" DATA CRC failed\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX:
|
|
- WARN(" Not enough data copied\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND:
|
|
- WARN(" Header not found\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO:
|
|
- WARN(" Header size is zero\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE:
|
|
- WARN(" Image not complete\n");
|
|
- break;
|
|
- default:
|
|
- WARN(" Error not listed\n");
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- switch (boot_context->emmc_xfer_status) {
|
|
- case BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED:
|
|
- WARN("BootROM: eMMC transfer status:\n");
|
|
- WARN(" not started\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED:
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED:
|
|
- WARN("BootROM: eMMC transfer status:\n");
|
|
- WARN(" timeout detected\n");
|
|
- break;
|
|
- case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT:
|
|
- WARN("BootROM: eMMC transfer status:\n");
|
|
- WARN(" data timeout detected\n");
|
|
- break;
|
|
- default:
|
|
- WARN("BootROM: eMMC transfer status:\n");
|
|
- WARN(" status not listed\n");
|
|
- break;
|
|
- }
|
|
-}
|
|
-#endif
|
|
-
|
|
#if STM32MP_EMMC || STM32MP_SDMMC
|
|
static void boot_mmc(enum mmc_device_type mmc_dev_type,
|
|
uint16_t boot_interface_instance)
|
|
@@ -437,6 +339,10 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
|
|
break;
|
|
}
|
|
|
|
+ if (mmc_dev_type == MMC_IS_SD) {
|
|
+ params.flags = MMC_FLAG_SD_CMD6;
|
|
+ }
|
|
+
|
|
params.device_info = &device_info;
|
|
if (stm32_sdmmc2_mmc_init(¶ms) != 0) {
|
|
ERROR("SDMMC%u init failed\n", boot_interface_instance);
|
|
@@ -641,7 +547,7 @@ static void flash_uart(uint16_t boot_interface_instance)
|
|
/* Open connections to devices */
|
|
io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer,
|
|
&image_dev_handle);
|
|
- assert(!io_result);
|
|
+ assert(io_result == 0);
|
|
}
|
|
#endif
|
|
|
|
@@ -672,7 +578,13 @@ static void flash_usb(struct usb_ctx *usb_context)
|
|
usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
|
|
|
|
usb_core_handle.class_data = &usb_dfu_handle;
|
|
+
|
|
usb_dfu_handle.dev_state = DFU_STATE_IDLE;
|
|
+ usb_dfu_handle.dev_status[1] = 0;
|
|
+ usb_dfu_handle.dev_status[2] = 0;
|
|
+ usb_dfu_handle.dev_status[3] = 0;
|
|
+ usb_dfu_handle.dev_status[4] = usb_dfu_handle.dev_state;
|
|
+ usb_dfu_handle.dev_status[5] = 0;
|
|
|
|
/* Register the IO devices on this platform */
|
|
io_result = register_io_dev_usb(&usb_dev_con);
|
|
@@ -711,13 +623,11 @@ void stm32mp_io_setup(void)
|
|
switch (boot_context->boot_interface_selected) {
|
|
#if STM32MP_SDMMC
|
|
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
|
|
- print_bootrom_sd_status(boot_context);
|
|
boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
|
|
break;
|
|
#endif
|
|
#if STM32MP_EMMC
|
|
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
|
|
- print_bootrom_emmc_status(boot_context);
|
|
boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
|
|
break;
|
|
#endif
|
|
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
|
|
index dc2568b6..7e361d5 100644
|
|
--- a/plat/st/common/include/stm32mp_common.h
|
|
+++ b/plat/st/common/include/stm32mp_common.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -15,7 +15,7 @@ void __dead2 stm32mp_plat_reset(int cpu);
|
|
void stm32mp_save_boot_ctx_address(uintptr_t address);
|
|
uintptr_t stm32mp_get_boot_ctx_address(void);
|
|
|
|
-int stm32mp_is_single_core(void);
|
|
+bool stm32mp_is_single_core(void);
|
|
|
|
uintptr_t stm32mp_ddrctrl_base(void);
|
|
uintptr_t stm32mp_ddrphyc_base(void);
|
|
@@ -24,6 +24,9 @@ uintptr_t stm32mp_rcc_base(void);
|
|
|
|
int stm32_gic_enable_spi(int node, const char *name);
|
|
|
|
+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx,
|
|
+ uint32_t *otp_len);
|
|
+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val);
|
|
uint32_t stm32_read_otp_status(uint32_t *otp_value, uint32_t word);
|
|
uint8_t stm32_iwdg_get_instance(uintptr_t base);
|
|
uint32_t stm32_iwdg_get_otp_config(uintptr_t base);
|
|
@@ -35,6 +38,10 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags);
|
|
uintptr_t stm32_get_gpio_bank_base(unsigned int bank);
|
|
int stm32_get_gpio_bank_clock(unsigned int bank);
|
|
uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
|
|
+
|
|
+bool stm32mp_supports_cpu_opp(uint32_t opp_id);
|
|
+bool stm32mp_ddr_supports_ssr_asr(void);
|
|
+
|
|
void stm32mp_print_cpuinfo(void);
|
|
void stm32mp_print_boardinfo(void);
|
|
|
|
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
|
|
index ee313d5..581236c 100644
|
|
--- a/plat/st/common/include/stm32mp_dt.h
|
|
+++ b/plat/st/common/include/stm32mp_dt.h
|
|
@@ -41,10 +41,17 @@ int dt_set_stdout_pinctrl(void);
|
|
void dt_fill_device_info(struct dt_node_info *info, int node);
|
|
int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
|
|
int dt_get_stdout_uart_info(struct dt_node_info *info);
|
|
+int dt_get_node_by_compatible(const char *compatible);
|
|
+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address);
|
|
+uintptr_t dt_get_peripheral_base(const char *compatible);
|
|
uint32_t dt_get_ddr_size(void);
|
|
uintptr_t dt_get_ddrctrl_base(void);
|
|
uintptr_t dt_get_ddrphyc_base(void);
|
|
+uintptr_t dt_get_rcc_base(void);
|
|
uintptr_t dt_get_pwr_base(void);
|
|
+int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv);
|
|
+int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array,
|
|
+ uint32_t *voltage_mv_array);
|
|
uint32_t dt_get_pwr_vdd_voltage(void);
|
|
uintptr_t dt_get_syscfg_base(void);
|
|
const char *dt_get_board_model(void);
|
|
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
|
|
index 8efac68..ecc41fc 100644
|
|
--- a/plat/st/common/stm32mp_common.c
|
|
+++ b/plat/st/common/stm32mp_common.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -51,9 +51,9 @@ uintptr_t stm32mp_get_boot_ctx_address(void)
|
|
*/
|
|
#pragma weak stm32mp_is_single_core
|
|
|
|
-int stm32mp_is_single_core(void)
|
|
+bool stm32mp_is_single_core(void)
|
|
{
|
|
- return 0;
|
|
+ return false;
|
|
}
|
|
|
|
uintptr_t stm32mp_ddrctrl_base(void)
|
|
@@ -100,7 +100,7 @@ uintptr_t stm32mp_rcc_base(void)
|
|
static uintptr_t rcc_base;
|
|
|
|
if (rcc_base == 0) {
|
|
- rcc_base = fdt_rcc_read_addr();
|
|
+ rcc_base = dt_get_rcc_base();
|
|
|
|
assert(rcc_base == RCC_BASE);
|
|
}
|
|
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
|
|
index 2f9951b..203b50f 100644
|
|
--- a/plat/st/common/stm32mp_dt.c
|
|
+++ b/plat/st/common/stm32mp_dt.c
|
|
@@ -337,6 +337,74 @@ int dt_get_stdout_uart_info(struct dt_node_info *info)
|
|
}
|
|
|
|
/*******************************************************************************
|
|
+ * This function returns the node offset matching compatible string in the DT.
|
|
+ * It is only valid for single instance peripherals (DDR, RCC, PWR, STGEN,
|
|
+ * SYSCFG...).
|
|
+ * Returns value on success, and error value on failure.
|
|
+ ******************************************************************************/
|
|
+int dt_get_node_by_compatible(const char *compatible)
|
|
+{
|
|
+ int node = fdt_node_offset_by_compatible(fdt, -1, compatible);
|
|
+
|
|
+ if (node < 0) {
|
|
+ INFO("Cannot find %s node in DT\n", compatible);
|
|
+ }
|
|
+
|
|
+ return node;
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function returns the node offset matching compatible string in the DT,
|
|
+ * and also matching the reg property with the given address.
|
|
+ * Returns value on success, and error value on failure.
|
|
+ ******************************************************************************/
|
|
+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address)
|
|
+{
|
|
+ int node;
|
|
+
|
|
+ for (node = fdt_node_offset_by_compatible(fdt, -1, compatible);
|
|
+ node != -FDT_ERR_NOTFOUND;
|
|
+ node = fdt_node_offset_by_compatible(fdt, node, compatible)) {
|
|
+ const fdt32_t *cuint;
|
|
+
|
|
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
+ if (cuint == NULL) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if ((uintptr_t)fdt32_to_cpu(*cuint) == address) {
|
|
+ return node;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function returns the peripheral base address information from the
|
|
+ * compatible string in the DT. It is only valid for single instance
|
|
+ * peripherals (RCC, PWR, STGEN, SYSCFG...).
|
|
+ * Returns value on success, and 0 on failure.
|
|
+ ******************************************************************************/
|
|
+uintptr_t dt_get_peripheral_base(const char *compatible)
|
|
+{
|
|
+ int node;
|
|
+ const fdt32_t *cuint;
|
|
+
|
|
+ node = dt_get_node_by_compatible(compatible);
|
|
+ if (node < 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
+ if (cuint == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return fdt32_to_cpu(*cuint);
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
* This function gets DDR size information from the DT.
|
|
* Returns value in bytes on success, and 0 on failure.
|
|
******************************************************************************/
|
|
@@ -344,9 +412,8 @@ uint32_t dt_get_ddr_size(void)
|
|
{
|
|
int node;
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
|
|
+ node = dt_get_node_by_compatible(DT_DDR_COMPAT);
|
|
if (node < 0) {
|
|
- INFO("%s: Cannot read DDR node in DT\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
@@ -362,9 +429,8 @@ uintptr_t dt_get_ddrctrl_base(void)
|
|
int node;
|
|
uint32_t array[4];
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
|
|
+ node = dt_get_node_by_compatible(DT_DDR_COMPAT);
|
|
if (node < 0) {
|
|
- INFO("%s: Cannot read DDR node in DT\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
@@ -384,9 +450,8 @@ uintptr_t dt_get_ddrphyc_base(void)
|
|
int node;
|
|
uint32_t array[4];
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
|
|
+ node = dt_get_node_by_compatible(DT_DDR_COMPAT);
|
|
if (node < 0) {
|
|
- INFO("%s: Cannot read DDR node in DT\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
@@ -398,26 +463,186 @@ uintptr_t dt_get_ddrphyc_base(void)
|
|
}
|
|
|
|
/*******************************************************************************
|
|
+ * This function gets RCC base address information from the DT.
|
|
+ * Returns value on success, and 0 on failure.
|
|
+ ******************************************************************************/
|
|
+uintptr_t dt_get_rcc_base(void)
|
|
+{
|
|
+ return dt_get_peripheral_base(DT_RCC_CLK_COMPAT);
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
* This function gets PWR base address information from the DT.
|
|
* Returns value on success, and 0 on failure.
|
|
******************************************************************************/
|
|
uintptr_t dt_get_pwr_base(void)
|
|
{
|
|
+ return dt_get_peripheral_base(DT_PWR_COMPAT);
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function gets OPP table node from the DT.
|
|
+ * Returns node offset on success and a negative FDT error code on failure.
|
|
+ ******************************************************************************/
|
|
+static int dt_get_opp_table_node(void)
|
|
+{
|
|
+ return dt_get_node_by_compatible(DT_OPP_COMPAT);
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function gets OPP parameters (frequency in KHz and voltage in mV) from
|
|
+ * an OPP table subnode. Platform HW support capabilities are also checked.
|
|
+ * Returns 0 on success and a negative FDT error code on failure.
|
|
+ ******************************************************************************/
|
|
+static int dt_get_opp_freqvolt_from_subnode(int subnode, uint32_t *freq_khz,
|
|
+ uint32_t *voltage_mv)
|
|
+{
|
|
+ const fdt64_t *cuint64;
|
|
+ const fdt32_t *cuint32;
|
|
+ uint64_t read_freq_64;
|
|
+ uint32_t read_voltage_32;
|
|
+
|
|
+ assert(freq_khz != NULL);
|
|
+ assert(voltage_mv != NULL);
|
|
+
|
|
+ cuint32 = fdt_getprop(fdt, subnode, "opp-supported-hw", NULL);
|
|
+ if (cuint32 != NULL) {
|
|
+ if (!stm32mp_supports_cpu_opp(fdt32_to_cpu(*cuint32))) {
|
|
+ VERBOSE("Invalid opp-supported-hw 0x%x\n",
|
|
+ fdt32_to_cpu(*cuint32));
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cuint64 = fdt_getprop(fdt, subnode, "opp-hz", NULL);
|
|
+ if (cuint64 == NULL) {
|
|
+ VERBOSE("Missing opp-hz\n");
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ /* Frequency value expressed in KHz must fit on 32 bits */
|
|
+ read_freq_64 = fdt64_to_cpu(*cuint64) / 1000ULL;
|
|
+ if (read_freq_64 > (uint64_t)UINT32_MAX) {
|
|
+ VERBOSE("Invalid opp-hz %llu\n", read_freq_64);
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+ }
|
|
+
|
|
+ cuint32 = fdt_getprop(fdt, subnode, "opp-microvolt", NULL);
|
|
+ if (cuint32 == NULL) {
|
|
+ VERBOSE("Missing opp-microvolt\n");
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ /* Millivolt value must fit on 16 bits */
|
|
+ read_voltage_32 = fdt32_to_cpu(*cuint32) / 1000U;
|
|
+ if (read_voltage_32 > (uint32_t)UINT16_MAX) {
|
|
+ VERBOSE("Invalid opp-microvolt %u\n", read_voltage_32);
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+ }
|
|
+
|
|
+ *freq_khz = (uint32_t)read_freq_64;
|
|
+
|
|
+ *voltage_mv = read_voltage_32;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function parses OPP table in DT and finds the parameters for the
|
|
+ * highest frequency supported by the HW platform.
|
|
+ * If found, the new frequency and voltage values override the original ones.
|
|
+ * Returns 0 on success and a negative FDT error code on failure.
|
|
+ ******************************************************************************/
|
|
+int dt_get_max_opp_freqvolt(uint32_t *freq_khz, uint32_t *voltage_mv)
|
|
+{
|
|
int node;
|
|
- const fdt32_t *cuint;
|
|
+ int subnode;
|
|
+ uint32_t freq = 0U;
|
|
+ uint32_t voltage = 0U;
|
|
|
|
- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
|
|
+ assert(freq_khz != NULL);
|
|
+ assert(voltage_mv != NULL);
|
|
+
|
|
+ node = dt_get_opp_table_node();
|
|
if (node < 0) {
|
|
- INFO("%s: Cannot read PWR node in DT\n", __func__);
|
|
- return 0;
|
|
+ return node;
|
|
}
|
|
|
|
- cuint = fdt_getprop(fdt, node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- return 0;
|
|
+ fdt_for_each_subnode(subnode, fdt, node) {
|
|
+ uint32_t read_freq;
|
|
+ uint32_t read_voltage;
|
|
+
|
|
+ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq,
|
|
+ &read_voltage) != 0) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (read_freq > freq) {
|
|
+ freq = read_freq;
|
|
+ voltage = read_voltage;
|
|
+ }
|
|
}
|
|
|
|
- return fdt32_to_cpu(*cuint);
|
|
+ if ((freq == 0U) || (voltage == 0U)) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ *freq_khz = freq;
|
|
+ *voltage_mv = voltage;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*******************************************************************************
|
|
+ * This function parses OPP table in DT and finds all parameters supported by
|
|
+ * the HW platform.
|
|
+ * If found, the corresponding frequency and voltage values are respectively
|
|
+ * stored in @*freq_khz_array and @*voltage_mv_array.
|
|
+ * Note that @*count has to be set by caller to the effective size allocated
|
|
+ * for both tables. Its value is then replaced by the number of filled elements.
|
|
+ * Returns 0 on success and a negative FDT error code on failure.
|
|
+ ******************************************************************************/
|
|
+int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array,
|
|
+ uint32_t *voltage_mv_array)
|
|
+{
|
|
+ int node;
|
|
+ int subnode;
|
|
+ int idx = 0;
|
|
+
|
|
+ assert(count != NULL);
|
|
+ assert(freq_khz_array != NULL);
|
|
+ assert(voltage_mv_array != NULL);
|
|
+
|
|
+ node = dt_get_opp_table_node();
|
|
+ if (node < 0) {
|
|
+ return node;
|
|
+ }
|
|
+
|
|
+ fdt_for_each_subnode(subnode, fdt, node) {
|
|
+ uint32_t read_freq;
|
|
+ uint32_t read_voltage;
|
|
+
|
|
+ if (dt_get_opp_freqvolt_from_subnode(subnode, &read_freq,
|
|
+ &read_voltage) != 0) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (idx >= *count) {
|
|
+ return -FDT_ERR_NOSPACE;
|
|
+ }
|
|
+
|
|
+ freq_khz_array[idx] = read_freq;
|
|
+ voltage_mv_array[idx] = read_voltage;
|
|
+ idx++;
|
|
+ }
|
|
+
|
|
+ if (idx == 0U) {
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+
|
|
+ *count = idx;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -429,9 +654,8 @@ 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);
|
|
+ node = dt_get_node_by_compatible(DT_PWR_COMPAT);
|
|
if (node < 0) {
|
|
- INFO("%s: Cannot read PWR node in DT\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
@@ -465,21 +689,7 @@ uint32_t dt_get_pwr_vdd_voltage(void)
|
|
******************************************************************************/
|
|
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);
|
|
+ return dt_get_peripheral_base(DT_SYSCFG_COMPAT);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
|
|
index 1a2e2d6..ef5a13d 100644
|
|
--- a/plat/st/stm32mp1/bl2_plat_setup.c
|
|
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -23,6 +23,7 @@
|
|
#include <stm32_gpio.h>
|
|
#include <stm32_iwdg.h>
|
|
#include <stm32mp_auth.h>
|
|
+#include <stm32mp_clkfunc.h>
|
|
#include <stm32mp_common.h>
|
|
#include <stm32mp_dt.h>
|
|
#include <stm32mp_pmic.h>
|
|
@@ -36,6 +37,7 @@
|
|
#include <stm32mp1_ram.h>
|
|
#include <stm32mp1_rcc.h>
|
|
#include <stm32mp1_shared_resources.h>
|
|
+#include <stpmic1.h>
|
|
#include <string.h>
|
|
#include <xlat_tables_v2.h>
|
|
|
|
@@ -146,19 +148,13 @@ void bl2_platform_setup(void)
|
|
{
|
|
int ret;
|
|
|
|
- if (dt_pmic_status() > 0) {
|
|
- initialize_pmic();
|
|
-#if STM32MP1_DEBUG_ENABLE
|
|
- /* Program PMIC to keep debug ON */
|
|
- if ((stm32mp1_dbgmcu_boot_debug_info() == 1) &&
|
|
- (stm32mp1_dbgmcu_is_debug_on() != 0)) {
|
|
- VERBOSE("Program PMIC to keep debug ON\n");
|
|
- if (pmic_keep_debug_unit() != 0) {
|
|
- ERROR("PMIC not properly set for debug\n");
|
|
- }
|
|
- }
|
|
-#endif
|
|
- }
|
|
+ /*
|
|
+ * Map DDR non cacheable during its initialisation to avoid
|
|
+ * speculative loads before accesses are fully setup.
|
|
+ */
|
|
+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
|
|
+ STM32MP_DDR_MAX_SIZE,
|
|
+ MT_NON_CACHEABLE | MT_RW | MT_NS);
|
|
|
|
ret = stm32mp1_ddr_probe();
|
|
if (ret < 0) {
|
|
@@ -166,15 +162,118 @@ void bl2_platform_setup(void)
|
|
panic();
|
|
}
|
|
|
|
+ mmap_remove_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_MAX_SIZE);
|
|
+
|
|
#ifdef AARCH32_SP_OPTEE
|
|
INFO("BL2 runs OP-TEE setup\n");
|
|
+
|
|
+ /* Map non secure DDR for BL33 load, now with cacheable attribute */
|
|
+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
|
|
+ dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
|
|
+ STM32MP_DDR_SHMEM_SIZE,
|
|
+ MT_MEMORY | MT_RW | MT_NS);
|
|
+
|
|
+ mmap_add_dynamic_region(STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
|
|
+ STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
|
|
+ STM32MP_DDR_S_SIZE,
|
|
+ MT_MEMORY | MT_RW | MT_SECURE);
|
|
+
|
|
/* Initialize tzc400 after DDR initialization */
|
|
stm32mp1_security_setup();
|
|
#else
|
|
INFO("BL2 runs SP_MIN setup\n");
|
|
+
|
|
+ /* Map non secure DDR for BL33 load, now with cacheable attribute */
|
|
+ mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
|
|
+ dt_get_ddr_size(),
|
|
+ MT_MEMORY | MT_RW | MT_NS);
|
|
#endif
|
|
}
|
|
|
|
+static void update_monotonic_counter(void)
|
|
+{
|
|
+ uint32_t version;
|
|
+ uint32_t otp;
|
|
+
|
|
+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
|
|
+ assert_stm32mp1_monotonic_counter_reach_max);
|
|
+
|
|
+ /* Check if monotonic counter needs to be incremented */
|
|
+ if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ if (stm32_get_otp_value(MONOTONIC_OTP, &version) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ if ((version + 1U) < BIT(STM32_TF_VERSION)) {
|
|
+ uint32_t result;
|
|
+
|
|
+ /* Need to increment the monotonic counter */
|
|
+ version = BIT(STM32_TF_VERSION) - 1U;
|
|
+
|
|
+ result = bsec_program_otp(version, otp);
|
|
+ if (result != BSEC_OK) {
|
|
+ ERROR("BSEC: MONOTONIC_OTP program Error %i\n",
|
|
+ result);
|
|
+ panic();
|
|
+ }
|
|
+ INFO("Monotonic counter has been incremented value 0x%x\n",
|
|
+ version);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void initialize_clock(bool wakeup_standby)
|
|
+{
|
|
+ uint32_t voltage_mv = 0U;
|
|
+ uint32_t freq_khz = 0U;
|
|
+ int ret;
|
|
+
|
|
+ if (wakeup_standby) {
|
|
+ stm32_get_pll1_settings_from_context();
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * If no pre-defined PLL1 settings in DT, find the highest frequency
|
|
+ * in the OPP table (in DT, compatible with plaform capabilities, or
|
|
+ * in structure restored in RAM), and set related VDDCORE voltage.
|
|
+ * If PLL1 settings found in DT, we consider VDDCORE voltage in DT is
|
|
+ * consistent with it.
|
|
+ */
|
|
+ if (!fdt_is_pll1_predefined()) {
|
|
+ if (wakeup_standby) {
|
|
+ ret = stm32mp1_clk_get_maxfreq_opp(&freq_khz,
|
|
+ &voltage_mv);
|
|
+ } else {
|
|
+ ret = dt_get_max_opp_freqvolt(&freq_khz, &voltage_mv);
|
|
+ }
|
|
+
|
|
+ if (ret != 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ if (dt_pmic_status() > 0) {
|
|
+ int read_voltage;
|
|
+ const char *name = "buck1";
|
|
+
|
|
+ read_voltage = stpmic1_regulator_voltage_get(name);
|
|
+ if (voltage_mv != (uint32_t)read_voltage) {
|
|
+ if (stpmic1_regulator_voltage_set(name,
|
|
+ (uint16_t)voltage_mv) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (stm32mp1_clk_init(freq_khz) < 0) {
|
|
+ panic();
|
|
+ }
|
|
+}
|
|
+
|
|
void bl2_el3_plat_arch_setup(void)
|
|
{
|
|
int32_t result;
|
|
@@ -189,6 +288,7 @@ void bl2_el3_plat_arch_setup(void)
|
|
tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
|
|
uint32_t bkpr_core1_addr =
|
|
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
|
|
+ bool wakeup_standby = false;
|
|
|
|
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
|
BL_CODE_END - BL_CODE_BASE,
|
|
@@ -201,14 +301,6 @@ void bl2_el3_plat_arch_setup(void)
|
|
#endif
|
|
|
|
#ifdef AARCH32_SP_OPTEE
|
|
- /* OP-TEE image needs post load processing: keep RAM read/write */
|
|
- mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
- STM32MP_DDR_S_SIZE,
|
|
- STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
- STM32MP_DDR_S_SIZE,
|
|
- STM32MP_DDR_S_SIZE,
|
|
- MT_MEMORY | MT_RW | MT_SECURE);
|
|
-
|
|
mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
|
|
STM32MP_OPTEE_SIZE,
|
|
MT_MEMORY | MT_RW | MT_SECURE);
|
|
@@ -216,19 +308,12 @@ void bl2_el3_plat_arch_setup(void)
|
|
/* Prevent corruption of preloaded BL32 */
|
|
mmap_add_region(BL32_BASE, BL32_BASE,
|
|
BL32_LIMIT - BL32_BASE,
|
|
- MT_MEMORY | MT_RO | MT_SECURE);
|
|
-
|
|
+ MT_RO_DATA | MT_SECURE);
|
|
#endif
|
|
- /* Map non secure DDR for BL33 load and DDR training area restore */
|
|
- mmap_add_region(STM32MP_DDR_BASE,
|
|
- STM32MP_DDR_BASE,
|
|
- STM32MP_DDR_MAX_SIZE,
|
|
- MT_MEMORY | MT_RW | MT_NS);
|
|
-
|
|
/* Prevent corruption of preloaded Device Tree */
|
|
mmap_add_region(DTB_BASE, DTB_BASE,
|
|
DTB_LIMIT - DTB_BASE,
|
|
- MT_MEMORY | MT_RO | MT_SECURE);
|
|
+ MT_RO_DATA | MT_SECURE);
|
|
|
|
configure_mmu();
|
|
|
|
@@ -301,6 +386,10 @@ void bl2_el3_plat_arch_setup(void)
|
|
mmio_write_32(bkpr_core1_magic, 0);
|
|
}
|
|
|
|
+ if (mmio_read_32(bkpr_core1_addr) != 0U) {
|
|
+ wakeup_standby = true;
|
|
+ }
|
|
+
|
|
generic_delay_timer_init();
|
|
|
|
#ifdef STM32MP_USB
|
|
@@ -325,10 +414,16 @@ void bl2_el3_plat_arch_setup(void)
|
|
panic();
|
|
}
|
|
|
|
- if (stm32mp1_clk_init() < 0) {
|
|
- panic();
|
|
+ if (dt_pmic_status() > 0) {
|
|
+ initialize_pmic();
|
|
+
|
|
+ if (!wakeup_standby) {
|
|
+ configure_pmic();
|
|
+ }
|
|
}
|
|
|
|
+ initialize_clock(wakeup_standby);
|
|
+
|
|
stm32mp1_syscfg_init();
|
|
|
|
result = dt_get_stdout_uart_info(&dt_uart_info);
|
|
@@ -418,6 +513,23 @@ skip_console_init:
|
|
|
|
print_reset_reason();
|
|
|
|
+ if (dt_pmic_status() > 0) {
|
|
+ initialize_pmic();
|
|
+ print_pmic_info_and_debug();
|
|
+#if STM32MP1_DEBUG_ENABLE
|
|
+ /* Program PMIC to keep debug ON */
|
|
+ if ((stm32mp1_dbgmcu_boot_debug_info() == 1) &&
|
|
+ (stm32mp1_dbgmcu_is_debug_on())) {
|
|
+ VERBOSE("Program PMIC to keep debug ON\n");
|
|
+ if (pmic_keep_debug_unit() != 0) {
|
|
+ ERROR("PMIC not properly set for debug\n");
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ update_monotonic_counter();
|
|
+
|
|
stm32mp_io_setup();
|
|
}
|
|
|
|
@@ -438,11 +550,12 @@ static void set_mem_params_info(entry_point_info_t *ep_info,
|
|
unpaged->image_max_size = STM32MP_OPTEE_SIZE;
|
|
} else {
|
|
unpaged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
- STM32MP_DDR_S_SIZE;
|
|
+ STM32MP_DDR_S_SIZE -
|
|
+ STM32MP_DDR_SHMEM_SIZE;
|
|
unpaged->image_max_size = STM32MP_DDR_S_SIZE;
|
|
}
|
|
paged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() -
|
|
- STM32MP_DDR_S_SIZE;
|
|
+ STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE;
|
|
paged->image_max_size = STM32MP_DDR_S_SIZE;
|
|
}
|
|
#endif
|
|
diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h
|
|
index 4cd6643..ba325c5 100644
|
|
--- a/plat/st/stm32mp1/include/stm32mp1_context.h
|
|
+++ b/plat/st/stm32mp1/include/stm32mp1_context.h
|
|
@@ -15,8 +15,11 @@
|
|
void stm32_clean_context(void);
|
|
int stm32_save_context(uint32_t zq0cr0_zdata);
|
|
int stm32_restore_context(void);
|
|
+unsigned long long stm32_get_stgen_from_context(void);
|
|
int stm32_restore_backup_reg(void);
|
|
uint32_t stm32_get_zdata_from_context(void);
|
|
+void stm32_get_pll1_settings_from_context(void);
|
|
+bool stm32_are_pll1_settings_valid_in_context(void);
|
|
int stm32_save_boot_interface(uint32_t interface, uint32_t instance);
|
|
int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance);
|
|
void stm32_save_ddr_training_area(void);
|
|
diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
|
|
index fd97a16..c3cb0b3 100644
|
|
--- a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
|
|
+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -15,12 +15,12 @@
|
|
#define VERBOSE_HEXDUMP8(buf, len)
|
|
#endif
|
|
|
|
-uint32_t stm32mp1_dbgmcu_get_chip_version(void);
|
|
-uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void);
|
|
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version);
|
|
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id);
|
|
int stm32mp1_dbgmcu_freeze_iwdg2(void);
|
|
int stm32mp1_dbgmcu_boot_debug_info(void);
|
|
-int stm32mp1_dbgmcu_clear_boot_info(void);
|
|
-uint32_t stm32mp1_dbgmcu_is_debug_on(void);
|
|
+void stm32mp1_dbgmcu_clear_boot_info(void);
|
|
+bool stm32mp1_dbgmcu_is_debug_on(void);
|
|
void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len);
|
|
|
|
#endif /* __PLAT_DBGMCU_H__ */
|
|
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
|
|
index 956493f..7014ff7 100644
|
|
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
|
|
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
|
|
@@ -1,68 +1,169 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
-#ifndef __STM32MP1_SMC_H__
|
|
-#define __STM32MP1_SMC_H__
|
|
+#ifndef STM32MP1_SMC_H
|
|
+#define STM32MP1_SMC_H
|
|
|
|
#include <platform_def.h>
|
|
|
|
+/* SMC service generic return codes */
|
|
+#define STM32_SMC_OK 0x00000000U
|
|
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
|
|
+#define STM32_SMC_FAILED 0xFFFFFFFEU
|
|
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
|
|
+
|
|
/*
|
|
- * SMC function IDs for STM32 Service queries
|
|
+ * SMC function IDs for STM32 Service queries.
|
|
* STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
|
|
* like this is defined in SMC calling Convention by ARM
|
|
- * for SiP (silicon Partner)
|
|
+ * for SiP (silicon Partner).
|
|
* https://developer.arm.com/docs/den0028/latest
|
|
*/
|
|
|
|
/* Secure Service access from Non-secure */
|
|
+
|
|
+/*
|
|
+ * SMC function STM32_SMC_RCC.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx).
|
|
+ * Argument a2: (input) Register offset or physical address.
|
|
+ * (output) Register read value, if applicable.
|
|
+ * Argument a3: (input) Register target value if applicable.
|
|
+ */
|
|
#define STM32_SMC_RCC 0x82001000
|
|
+
|
|
+/*
|
|
+ * SMC function STM32_SMC_PWR.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx).
|
|
+ * Argument a2: (input) Register offset or physical address.
|
|
+ * (output) Register read value, if applicable.
|
|
+ * Argument a3: (input) Register target value if applicable.
|
|
+ */
|
|
#define STM32_SMC_PWR 0x82001001
|
|
+
|
|
+/*
|
|
+ * SMC functions STM32_SMC_RCC_CAL.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (input) Clock ID (from DT clock bindings).
|
|
+ */
|
|
#define STM32_SMC_RCC_CAL 0x82001002
|
|
+
|
|
+/*
|
|
+ * SMC functions STM32_SMC_BSEC.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (input) Service ID (STM32_SMC_READ_xxx/_PROG_xxx/_WRITE_xxx).
|
|
+ * (output) OTP read value, if applicable.
|
|
+ * Argument a2: (input) OTP index.
|
|
+ * Argument a3: (input) OTP value if applicable.
|
|
+ */
|
|
#define STM32_SMC_BSEC 0x82001003
|
|
|
|
/* Low Power services */
|
|
+
|
|
+/*
|
|
+ * SIP functions STM32_SMC_SR_MODE.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (unused).
|
|
+ * Argument a2: (input) Target selfrefresh mode (STM32_SMC_SR_MODE_xxx).
|
|
+ */
|
|
#define STM32_SMC_SR_MODE 0x82001004
|
|
+
|
|
+/*
|
|
+ * SIP function STM32_SMC_PD_DOMAIN.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a2: (index) ID of target power domain to be enabled/disabled.
|
|
+ * Argument a3: (input) 0 to disable, 1 to enable target domain.
|
|
+ */
|
|
#define STM32_SMC_PD_DOMAIN 0x82001008
|
|
|
|
+/*
|
|
+ * SIP function STM32_SMC_RCC_OPP.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Status return code.
|
|
+ * Argument a1: (input) Service ID (STM32_SMC_RCC_OPP_xxx).
|
|
+ * (output) Rounded frequency, if applicable.
|
|
+ * Argument a2: (input) Requested frequency.
|
|
+ */
|
|
+#define STM32_SMC_RCC_OPP 0x82001009
|
|
+
|
|
/* SMC function IDs for SiP Service queries */
|
|
+
|
|
+/*
|
|
+ * SIP function STM32_SIP_SVC_CALL_COUNT.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Dummy value 0.
|
|
+ */
|
|
#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
|
|
+
|
|
+/*
|
|
+ * SIP function STM32_SIP_SVC_UID.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) Lowest 32bit of the stm32mp1 SIP service UUID.
|
|
+ * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID.
|
|
+ * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID.
|
|
+ * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID.
|
|
+ */
|
|
#define STM32_SIP_SVC_UID 0x8200ff01
|
|
-/* 0x8200ff02 is reserved */
|
|
-#define STM32_SIP_SVC_VERSION 0x8200ff03
|
|
|
|
-/* STM32 SiP Service Calls version numbers */
|
|
-#define STM32_SIP_SVC_VERSION_MAJOR 0x0
|
|
-#define STM32_SIP_SVC_VERSION_MINOR 0x1
|
|
+/* 0x8200ff02 is reserved */
|
|
|
|
-/* Number of STM32 SiP Calls implemented */
|
|
-#define STM32_COMMON_SIP_NUM_CALLS 10
|
|
+/*
|
|
+ * SIP function STM32_SIP_SVC_VERSION.
|
|
+ *
|
|
+ * Argument a0: (input) SMCC ID.
|
|
+ * (output) STM32 SIP service major.
|
|
+ * Argument a1: (output) STM32 SIP service minor.
|
|
+ */
|
|
+#define STM32_SIP_SVC_VERSION 0x8200ff03
|
|
|
|
-/* Register access service use for RCC/RTC/PWR */
|
|
+/* Service ID for STM32_SMC_RCC/_PWR */
|
|
#define STM32_SMC_REG_READ 0x0
|
|
#define STM32_SMC_REG_WRITE 0x1
|
|
#define STM32_SMC_REG_SET 0x2
|
|
#define STM32_SMC_REG_CLEAR 0x3
|
|
|
|
-/* Service for BSEC */
|
|
+/* Service ID for STM32_SMC_BSEC */
|
|
#define STM32_SMC_READ_SHADOW 0x01
|
|
#define STM32_SMC_PROG_OTP 0x02
|
|
#define STM32_SMC_WRITE_SHADOW 0x03
|
|
#define STM32_SMC_READ_OTP 0x04
|
|
#define STM32_SMC_READ_ALL 0x05
|
|
#define STM32_SMC_WRITE_ALL 0x06
|
|
-
|
|
-/* SMC error codes */
|
|
-#define STM32_SMC_OK 0x00000000U
|
|
-#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
|
|
-#define STM32_SMC_FAILED 0xFFFFFFFEU
|
|
-#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
|
|
+#define STM32_SMC_WRLOCK_OTP 0x07
|
|
|
|
/* DDR Self-Refresh modes */
|
|
#define STM32_SMC_SR_MODE_SSR 0x0
|
|
#define STM32_SMC_SR_MODE_ASR 0x1
|
|
#define STM32_SMC_SR_MODE_HSR 0x2
|
|
|
|
-#endif /* __STM32MP1_SMC_H__ */
|
|
+/* Service ID for STM32_SMC_RCC_OPP */
|
|
+#define STM32_SMC_RCC_OPP_SET 0x0
|
|
+#define STM32_SMC_RCC_OPP_ROUND 0x1
|
|
+
|
|
+/* STM32 SiP Service Calls version numbers */
|
|
+#define STM32_SIP_SVC_VERSION_MAJOR 0x0
|
|
+#define STM32_SIP_SVC_VERSION_MINOR 0x1
|
|
+
|
|
+/* Number of STM32 SiP Calls implemented */
|
|
+#define STM32_COMMON_SIP_NUM_CALLS 11
|
|
+
|
|
+#endif /* STM32MP1_SMC_H */
|
|
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
|
|
index db53c37..a6ca9ce 100644
|
|
--- a/plat/st/stm32mp1/plat_image_load.c
|
|
+++ b/plat/st/stm32mp1/plat_image_load.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -7,7 +7,6 @@
|
|
#include <bl_common.h>
|
|
#include <boot_api.h>
|
|
#include <bsec.h>
|
|
-#include <cassert.h>
|
|
#include <debug.h>
|
|
#include <desc_image_load.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
@@ -28,37 +27,7 @@
|
|
******************************************************************************/
|
|
void plat_flush_next_bl_params(void)
|
|
{
|
|
- uint32_t version;
|
|
-
|
|
flush_bl_params_desc();
|
|
-
|
|
- CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
|
|
- assert_stm32mp1_monotonic_counter_reach_max);
|
|
-
|
|
- /* Check if monotonic counter need to be incremented */
|
|
- ;
|
|
- if (bsec_shadow_read_otp(&version, MONOTONIC_OTP) != BSEC_OK) {
|
|
- ERROR("BSEC: MONOTONIC_OTP Error\n");
|
|
- panic();
|
|
- }
|
|
-
|
|
- INFO("read version %i current version %i\n", version, STM32_TF_VERSION);
|
|
-
|
|
- if ((version + 1U) < BIT(STM32_TF_VERSION)) {
|
|
- uint32_t result;
|
|
-
|
|
- /* need to increment the monotonic counter */
|
|
- version = BIT(STM32_TF_VERSION) - 1U;
|
|
-
|
|
- result = bsec_program_otp(version, MONOTONIC_OTP);
|
|
- if (result != BSEC_OK) {
|
|
- ERROR("BSEC: MONOTONIC_OTP program Error %i\n",
|
|
- result);
|
|
- panic();
|
|
- }
|
|
- INFO("Monotonic counter has been incremented value 0x%x\n",
|
|
- version);
|
|
- }
|
|
}
|
|
|
|
#ifdef AARCH32_SP_OPTEE
|
|
@@ -121,7 +90,13 @@ bl_load_info_t *plat_get_bl_image_load_info(void)
|
|
stm32mp_clk_disable(RTCAPB);
|
|
}
|
|
|
|
- bl33->image_info.image_max_size = dt_get_ddr_size();
|
|
+ /* Max size is non-secure DDR end address minus image_base */
|
|
+ bl33->image_info.image_max_size = dt_get_ddr_size() -
|
|
+#ifdef AARCH32_SP_OPTEE
|
|
+ STM32MP_DDR_S_SIZE -
|
|
+ STM32MP_DDR_SHMEM_SIZE -
|
|
+#endif
|
|
+ bl33->image_info.image_base;
|
|
|
|
return get_bl_load_info_from_mem_params_desc();
|
|
}
|
|
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
|
|
index 91bb1ca..31cc273 100644
|
|
--- a/plat/st/stm32mp1/platform.mk
|
|
+++ b/plat/st/stm32mp1/platform.mk
|
|
@@ -1,5 +1,5 @@
|
|
#
|
|
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
@@ -11,7 +11,7 @@ USE_COHERENT_MEM := 0
|
|
MULTI_CONSOLE_API := 1
|
|
|
|
# Add specific ST version
|
|
-ST_VERSION := r1.5
|
|
+ST_VERSION := r3.0
|
|
VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING}
|
|
|
|
# Please don't increment this value without good understanding of
|
|
@@ -19,6 +19,11 @@ VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE
|
|
STM32_TF_VERSION ?= 0
|
|
$(eval $(call add_define_val,STM32_TF_VERSION,${STM32_TF_VERSION}))
|
|
|
|
+# Enable dynamic memory mapping
|
|
+PLAT_XLAT_TABLES_DYNAMIC := 1
|
|
+$(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC))
|
|
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
|
|
+
|
|
# Enable software PMIC programming in case of debug purpose
|
|
STM32MP1_DEBUG_ENABLE ?= 1
|
|
$(eval $(call add_define_val,STM32MP1_DEBUG_ENABLE,${STM32MP1_DEBUG_ENABLE}))
|
|
@@ -134,6 +139,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \
|
|
drivers/st/iwdg/stm32_iwdg.c \
|
|
drivers/st/pmic/stm32mp_pmic.c \
|
|
drivers/st/pmic/stpmic1.c \
|
|
+ drivers/st/regulator/stm32mp_dummy_regulator.c \
|
|
+ drivers/st/regulator/stm32mp_regulator.c \
|
|
drivers/st/reset/stm32mp1_reset.c \
|
|
plat/st/common/stm32mp_dt.c \
|
|
plat/st/common/stm32mp_shres_helpers.c \
|
|
@@ -219,7 +226,7 @@ STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
|
|
.PHONY: ${STM32_TF_STM32}
|
|
.SUFFIXES:
|
|
|
|
-all: check_dtc_version ${STM32_TF_STM32} stm32image
|
|
+all: check_dtc_version stm32image ${STM32_TF_STM32}
|
|
|
|
ifeq ($(AARCH32_SP),sp_min)
|
|
# BL32 is built only if using SP_MIN
|
|
@@ -232,6 +239,8 @@ distclean realclean clean: clean_stm32image
|
|
stm32image:
|
|
${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH}
|
|
|
|
+${STM32IMAGE}: stm32image
|
|
+
|
|
clean_stm32image:
|
|
${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
|
|
|
|
@@ -266,7 +275,7 @@ ${STM32_TF_BINARY}: ${STM32_TF_ELF}
|
|
@echo "Built $@ successfully"
|
|
@echo
|
|
|
|
-${STM32_TF_STM32}: stm32image ${STM32_TF_BINARY}
|
|
+${STM32_TF_STM32}: ${STM32IMAGE} ${STM32_TF_BINARY}
|
|
@echo
|
|
@echo "Generated $@"
|
|
$(eval LOADADDR = $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}'))
|
|
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
|
|
index b13580d..85cf3c6 100644
|
|
--- a/plat/st/stm32mp1/services/bsec_svc.c
|
|
+++ b/plat/st/stm32mp1/services/bsec_svc.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -94,6 +94,7 @@ static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update)
|
|
return BSEC_NO_SSP;
|
|
}
|
|
|
|
+#if STM32MP_USB || STM32MP_UART_PROGRAMMER
|
|
static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange)
|
|
{
|
|
uint32_t i;
|
|
@@ -382,6 +383,7 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
|
|
|
|
return BSEC_OK;
|
|
}
|
|
+#endif /* STM32MP_USB || STM32MP_UART_PROGRAMMER */
|
|
|
|
uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
uint32_t *ret_otp_value)
|
|
@@ -391,14 +393,16 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
|
|
if ((x1 != STM32_SMC_READ_ALL) && (x1 != STM32_SMC_WRITE_ALL) &&
|
|
(bsec_check_nsec_access_rights(x2) != BSEC_OK)) {
|
|
- return BSEC_ERROR;
|
|
+ return STM32_SMC_INVALID_PARAMS;
|
|
}
|
|
|
|
+#if STM32MP_USB || STM32MP_UART_PROGRAMMER
|
|
if (((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) &&
|
|
(!ddr_is_nonsecured_area((uintptr_t)x2,
|
|
sizeof(struct otp_exchange)))) {
|
|
- return BSEC_ERROR;
|
|
+ return STM32_SMC_INVALID_PARAMS;
|
|
}
|
|
+#endif
|
|
|
|
switch (x1) {
|
|
case STM32_SMC_READ_SHADOW:
|
|
@@ -443,6 +447,7 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
|
|
result = bsec_write_otp(tmp_data, x2);
|
|
break;
|
|
+#if STM32MP_USB || STM32MP_UART_PROGRAMMER
|
|
case STM32_SMC_READ_ALL:
|
|
result = bsec_read_all_bsec((struct otp_exchange *)x2);
|
|
break;
|
|
@@ -450,10 +455,13 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
result = bsec_write_all_bsec((struct otp_exchange *)x2,
|
|
ret_otp_value);
|
|
break;
|
|
- default:
|
|
- result = BSEC_ERROR;
|
|
+#endif
|
|
+ case STM32_SMC_WRLOCK_OTP:
|
|
+ result = bsec_permanent_lock_otp(x2);
|
|
break;
|
|
+ default:
|
|
+ return STM32_SMC_INVALID_PARAMS;
|
|
}
|
|
|
|
- return result;
|
|
+ return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED;
|
|
}
|
|
diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c
|
|
index 6e8f9d0..3dc4ab0 100644
|
|
--- a/plat/st/stm32mp1/services/rcc_svc.c
|
|
+++ b/plat/st/stm32mp1/services/rcc_svc.c
|
|
@@ -1,6 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -475,3 +474,34 @@ uint32_t rcc_cal_scv_handler(uint32_t x1)
|
|
|
|
return ret;
|
|
}
|
|
+
|
|
+uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res)
|
|
+{
|
|
+ uint32_t cmd = x1;
|
|
+ uint32_t opp = x2 / 1000U; /* KHz */
|
|
+
|
|
+ switch (cmd) {
|
|
+ case STM32_SMC_RCC_OPP_SET:
|
|
+ if (stm32mp1_set_opp_khz(opp) != 0) {
|
|
+ return STM32_SMC_FAILED;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case STM32_SMC_RCC_OPP_ROUND:
|
|
+ if (stm32mp1_round_opp_khz(&opp) != 0) {
|
|
+ return STM32_SMC_FAILED;
|
|
+ }
|
|
+
|
|
+ if (opp > (UINT32_MAX / 1000U)) {
|
|
+ return STM32_SMC_FAILED;
|
|
+ }
|
|
+
|
|
+ *res = opp * 1000U;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return STM32_SMC_INVALID_PARAMS;
|
|
+ }
|
|
+
|
|
+ return STM32_SMC_OK;
|
|
+}
|
|
diff --git a/plat/st/stm32mp1/services/rcc_svc.h b/plat/st/stm32mp1/services/rcc_svc.h
|
|
index 75d4a3c..23c7582 100644
|
|
--- a/plat/st/stm32mp1/services/rcc_svc.h
|
|
+++ b/plat/st/stm32mp1/services/rcc_svc.h
|
|
@@ -1,6 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -10,5 +9,6 @@
|
|
|
|
uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3);
|
|
uint32_t rcc_cal_scv_handler(uint32_t x1);
|
|
+uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res);
|
|
|
|
#endif /* RCC_SVC_H */
|
|
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
|
|
index fff91c0..cabaf16 100644
|
|
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
|
|
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
|
|
@@ -1,6 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2014-2018, STMicroelectronics - All Rights Reserved
|
|
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -74,6 +73,11 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
|
|
ret1 = rcc_cal_scv_handler(x1);
|
|
break;
|
|
|
|
+ case STM32_SMC_RCC_OPP:
|
|
+ ret1 = rcc_opp_scv_handler(x1, x2, &ret2);
|
|
+ ret2_enabled = true;
|
|
+ break;
|
|
+
|
|
case STM32_SMC_PWR:
|
|
ret1 = pwr_scv_handler(x1, x2, x3);
|
|
break;
|
|
@@ -88,7 +92,7 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
|
|
|
|
default:
|
|
WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
|
|
- ret1 = SMC_UNK;
|
|
+ ret1 = STM32_SMC_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
index 8748b68..1d87080 100644
|
|
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
@@ -33,6 +33,7 @@
|
|
#include <stm32mp1_power_config.h>
|
|
#include <stm32mp1_private.h>
|
|
#include <stm32mp1_shared_resources.h>
|
|
+#include <stpmic1.h>
|
|
#include <string.h>
|
|
#include <tzc400.h>
|
|
#include <xlat_tables_v2.h>
|
|
@@ -97,6 +98,29 @@ static void configure_wakeup_interrupt(void)
|
|
plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO);
|
|
}
|
|
|
|
+static void initialize_pll1_settings(void)
|
|
+{
|
|
+ uint32_t vddcore_voltage = 0U;
|
|
+ int ret;
|
|
+
|
|
+ if (stm32_are_pll1_settings_valid_in_context()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (dt_pmic_status() > 0) {
|
|
+ ret = stpmic1_regulator_voltage_get("buck1");
|
|
+ if (ret < 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ vddcore_voltage = (uint32_t)ret;
|
|
+ }
|
|
+
|
|
+ if (stm32mp1_clk_compute_all_pll1_settings(vddcore_voltage) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+}
|
|
+
|
|
/*******************************************************************************
|
|
* Interrupt handler for FIQ (secure IRQ)
|
|
******************************************************************************/
|
|
@@ -299,6 +323,8 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
|
initialize_pmic();
|
|
}
|
|
|
|
+ initialize_pll1_settings();
|
|
+
|
|
stm32mp1_init_lp_states();
|
|
}
|
|
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
|
|
index 8dc1146..362b672 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_context.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_context.c
|
|
@@ -28,24 +28,46 @@
|
|
#define TRAINING_AREA_SIZE 64
|
|
|
|
#ifdef AARCH32_SP_OPTEE
|
|
-/* OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined */
|
|
-#define OPTEE_MAILBOX_MAGIC_V1 0x01
|
|
-#define OPTEE_MAILBOX_MAGIC ((OPTEE_MAILBOX_MAGIC_V1 << 16) + \
|
|
- TRAINING_AREA_SIZE)
|
|
+/*
|
|
+ * OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined
|
|
+ *
|
|
+ * OPTEE_MAILBOX_MAGIC_V1:
|
|
+ * Context provides magic, resume entry, zq0cr0 zdata and DDR training buffer.
|
|
+ *
|
|
+ * OPTEE_MAILBOX_MAGIC_V2:
|
|
+ * Context provides magic, resume entry, zq0cr0 zdata, DDR training buffer
|
|
+ * and PLL1 dual OPP settings structure (86 bytes).
|
|
+ */
|
|
+#define OPTEE_MAILBOX_MAGIC_V1 (0x0001 << 16)
|
|
+#define OPTEE_MAILBOX_MAGIC_V2 (0x0002 << 16)
|
|
+#define OPTEE_MAILBOX_MAGIC (OPTEE_MAILBOX_MAGIC_V2 | \
|
|
+ TRAINING_AREA_SIZE)
|
|
+
|
|
+#if (PLAT_MAX_OPP_NB != 2) || (PLAT_MAX_PLLCFG_NB != 6)
|
|
+#error OPTEE_MAILBOX_MAGIC_V1 does not support expected PLL1 settings
|
|
+#endif
|
|
#endif
|
|
|
|
+/* pll_settings structure size definitions (reference to clock driver) */
|
|
+#define PLL1_SETTINGS_SIZE (((PLAT_MAX_OPP_NB * \
|
|
+ (PLAT_MAX_PLLCFG_NB + 3)) + 1) * \
|
|
+ sizeof(uint32_t))
|
|
+
|
|
struct backup_data_s {
|
|
#ifdef AARCH32_SP_OPTEE
|
|
uint32_t magic;
|
|
uint32_t core0_resume_hint;
|
|
uint32_t zq0cr0_zdata;
|
|
uint8_t ddr_training_backup[TRAINING_AREA_SIZE];
|
|
+ uint8_t pll1_settings[PLL1_SETTINGS_SIZE];
|
|
#else
|
|
smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT];
|
|
cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT];
|
|
uint32_t zq0cr0_zdata;
|
|
struct stm32_rtc_calendar rtc;
|
|
uint8_t ddr_training_backup[TRAINING_AREA_SIZE];
|
|
+ uint8_t pll1_settings[PLL1_SETTINGS_SIZE];
|
|
+ unsigned long long stgen;
|
|
#endif
|
|
};
|
|
|
|
@@ -106,6 +128,10 @@ int stm32_save_context(uint32_t zq0cr0_zdata)
|
|
backup_data->zq0cr0_zdata = zq0cr0_zdata;
|
|
|
|
stm32_rtc_get_calendar(&backup_data->rtc);
|
|
+ backup_data->stgen = stm32mp1_stgen_get_counter();
|
|
+
|
|
+ stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings,
|
|
+ sizeof(backup_data->pll1_settings));
|
|
|
|
stm32mp_clk_disable(BKPSRAM);
|
|
|
|
@@ -137,16 +163,35 @@ int stm32_restore_context(void)
|
|
memcpy(cpu_context, backup_data->saved_cpu_context,
|
|
sizeof(cpu_context_t) * PLATFORM_CORE_COUNT);
|
|
|
|
- /* update STGEN counter with standby mode length */
|
|
+ /* Restore STGEN counter with standby mode length */
|
|
stm32_rtc_get_calendar(¤t_calendar);
|
|
stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar,
|
|
&backup_data->rtc);
|
|
- stm32mp1_stgen_increment(stdby_time_in_ms);
|
|
+ stm32mp1_stgen_restore_counter(backup_data->stgen, stdby_time_in_ms);
|
|
+
|
|
+ stm32mp1_clk_lp_load_opp_pll1_settings(backup_data->pll1_settings,
|
|
+ sizeof(backup_data->pll1_settings));
|
|
|
|
stm32mp_clk_disable(BKPSRAM);
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+unsigned long long stm32_get_stgen_from_context(void)
|
|
+{
|
|
+ struct backup_data_s *backup_data;
|
|
+ unsigned long long stgen_cnt;
|
|
+
|
|
+ stm32mp_clk_enable(BKPSRAM);
|
|
+
|
|
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
|
|
+
|
|
+ stgen_cnt = backup_data->stgen;
|
|
+
|
|
+ stm32mp_clk_disable(BKPSRAM);
|
|
+
|
|
+ return stgen_cnt;
|
|
+}
|
|
#endif /*AARCH32_SP_OPTEE*/
|
|
|
|
uint32_t stm32_get_zdata_from_context(void)
|
|
@@ -166,6 +211,40 @@ uint32_t stm32_get_zdata_from_context(void)
|
|
return zdata;
|
|
}
|
|
|
|
+void stm32_get_pll1_settings_from_context(void)
|
|
+{
|
|
+ struct backup_data_s *backup_data;
|
|
+ uint8_t *data;
|
|
+
|
|
+ stm32mp_clk_enable(BKPSRAM);
|
|
+
|
|
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
|
|
+
|
|
+ data = (uint8_t *)backup_data->pll1_settings;
|
|
+ stm32mp1_clk_lp_load_opp_pll1_settings(data,
|
|
+ sizeof(backup_data->pll1_settings));
|
|
+
|
|
+ stm32mp_clk_disable(BKPSRAM);
|
|
+}
|
|
+
|
|
+bool stm32_are_pll1_settings_valid_in_context(void)
|
|
+{
|
|
+ struct backup_data_s *backup_data;
|
|
+ uint32_t *data;
|
|
+ bool is_valid;
|
|
+
|
|
+ stm32mp_clk_enable(BKPSRAM);
|
|
+
|
|
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
|
|
+ data = (uint32_t *)backup_data->pll1_settings;
|
|
+
|
|
+ is_valid = (data[0] == PLL1_SETTINGS_VALID_ID);
|
|
+
|
|
+ stm32mp_clk_disable(BKPSRAM);
|
|
+
|
|
+ return is_valid;
|
|
+}
|
|
+
|
|
int stm32_save_boot_interface(uint32_t interface, uint32_t instance)
|
|
{
|
|
uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID);
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
|
|
index 716f7d8..39cf5d7 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
|
|
@@ -1,9 +1,10 @@
|
|
/*
|
|
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
+#include <assert.h>
|
|
#include <bsec.h>
|
|
#include <debug.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
@@ -16,8 +17,12 @@
|
|
#include <utils_def.h>
|
|
|
|
#define DBGMCU_IDC 0x0U
|
|
-#define IDC_DEV_ID_MASK GENMASK(11, 0)
|
|
#define DBGMCU_APB4FZ1 0x2CU
|
|
+
|
|
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
|
|
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
|
|
+#define DBGMCU_IDC_REV_ID_SHIFT 16
|
|
+
|
|
#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
|
|
|
|
#define TAMP_DBG_BACKUP_REG_ID 20
|
|
@@ -55,6 +60,10 @@ static int stm32mp1_dbgmcu_init(void)
|
|
}
|
|
|
|
#if STM32MP1_DEBUG_ENABLE
|
|
+/*
|
|
+ * @brief Get debug mode information from backup registers.
|
|
+ * @retval 1 if debug mode is enabled, 0 otherwise.
|
|
+ */
|
|
int stm32mp1_dbgmcu_boot_debug_info(void)
|
|
{
|
|
uint32_t backup_reg_dbg;
|
|
@@ -73,7 +82,11 @@ int stm32mp1_dbgmcu_boot_debug_info(void)
|
|
return 0;
|
|
}
|
|
|
|
-int stm32mp1_dbgmcu_clear_boot_info(void)
|
|
+/*
|
|
+ * @brief Clear debug mode information in backup registers.
|
|
+ * @retval None.
|
|
+ */
|
|
+void stm32mp1_dbgmcu_clear_boot_info(void)
|
|
{
|
|
stm32mp_clk_enable(RTCAPB);
|
|
|
|
@@ -81,20 +94,28 @@ int stm32mp1_dbgmcu_clear_boot_info(void)
|
|
TAMP_DBG_DEBUG);
|
|
|
|
stm32mp_clk_disable(RTCAPB);
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
-uint32_t stm32mp1_dbgmcu_is_debug_on(void)
|
|
+/*
|
|
+ * @brief Get DBGMCU debug mode in BSEC registers.
|
|
+ * @retval True if debug mode enabled, false otherwise.
|
|
+ */
|
|
+bool stm32mp1_dbgmcu_is_debug_on(void)
|
|
{
|
|
uint32_t dbg_conf;
|
|
|
|
dbg_conf = bsec_read_debug_conf();
|
|
|
|
- return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN));
|
|
+ return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN)) != 0U;
|
|
}
|
|
|
|
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
|
+/*
|
|
+ * @brief Dump 8-bits buffer content in hexadecimal.
|
|
+ * @param buf: Pointer to the 8-bits buffer.
|
|
+ * @parma len: Length in bytes of the dump.
|
|
+ * @retval None.
|
|
+ */
|
|
void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len)
|
|
{
|
|
uint32_t i;
|
|
@@ -116,25 +137,48 @@ void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len)
|
|
#endif
|
|
#endif
|
|
|
|
-uint32_t stm32mp1_dbgmcu_get_chip_version(void)
|
|
+/*
|
|
+ * @brief Get silicon revision from DBGMCU registers.
|
|
+ * @param chip_version: pointer to the read value.
|
|
+ * @retval 0 on success, negative value on failure.
|
|
+ */
|
|
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version)
|
|
{
|
|
- if (stm32mp1_dbgmcu_init() == 0) {
|
|
- return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) >> 16);
|
|
+ assert(chip_version != NULL);
|
|
+
|
|
+ if (stm32mp1_dbgmcu_init() != 0) {
|
|
+ return -EPERM;
|
|
}
|
|
|
|
+ *chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
|
|
+ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
-uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void)
|
|
+/*
|
|
+ * @brief Get device ID from DBGMCU registers.
|
|
+ * @param chip_version: pointer to the read value.
|
|
+ * @retval 0 on success, negative value on failure.
|
|
+ */
|
|
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
|
|
{
|
|
- if (stm32mp1_dbgmcu_init() == 0) {
|
|
- return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
|
|
- IDC_DEV_ID_MASK);
|
|
+ assert(chip_dev_id != NULL);
|
|
+
|
|
+ if (stm32mp1_dbgmcu_init() != 0) {
|
|
+ return -EPERM;
|
|
}
|
|
|
|
+ *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
|
|
+ DBGMCU_IDC_DEV_ID_MASK;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * @brief Freeze IWDG2 in debug mode.
|
|
+ * @retval None.
|
|
+ */
|
|
int stm32mp1_dbgmcu_freeze_iwdg2(void)
|
|
{
|
|
if (stm32mp1_dbgmcu_init() == 0) {
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
|
|
index 7d7d773..f130eab 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_def.h
|
|
+++ b/plat/st/stm32mp1/stm32mp1_def.h
|
|
@@ -8,12 +8,17 @@
|
|
#define STM32MP1_DEF_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
+#include <boot_api.h>
|
|
#include <bsec.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
|
#include <dt-bindings/reset/stm32mp1-resets.h>
|
|
#include <dt-bindings/soc/st,stm32-etzpc.h>
|
|
#include <etzpc.h>
|
|
+#include <stm32mp_auth.h>
|
|
+#include <stm32mp_common.h>
|
|
+#include <stm32mp_dt.h>
|
|
+#include <stm32mp_shres_helpers.h>
|
|
#include <stm32mp1_calib.h>
|
|
#include <stm32mp1_clkfunc.h>
|
|
#include <stm32mp1_clk.h>
|
|
@@ -29,6 +34,7 @@
|
|
#include <stm32mp1_shared_resources.h>
|
|
#include <stm32mp1_usb_desc.h>
|
|
#include <stm32mp1xx_hal_uart.h>
|
|
+#include <usb_ctx.h>
|
|
#endif
|
|
#include <tbbr_img_def.h>
|
|
#include <utils_def.h>
|
|
@@ -45,9 +51,16 @@
|
|
#define STM32MP153A_PART_NB U(0x05000025)
|
|
#define STM32MP151C_PART_NB U(0x0500002E)
|
|
#define STM32MP151A_PART_NB U(0x0500002F)
|
|
+#define STM32MP157F_PART_NB U(0x05000080)
|
|
+#define STM32MP157D_PART_NB U(0x05000081)
|
|
+#define STM32MP153F_PART_NB U(0x050000A4)
|
|
+#define STM32MP153D_PART_NB U(0x050000A5)
|
|
+#define STM32MP151F_PART_NB U(0x050000AE)
|
|
+#define STM32MP151D_PART_NB U(0x050000AF)
|
|
|
|
#define STM32MP1_REV_A U(0x1000)
|
|
#define STM32MP1_REV_B U(0x2000)
|
|
+#define STM32MP1_REV_Z U(0x2001)
|
|
|
|
/*******************************************************************************
|
|
* PACKAGE ID
|
|
@@ -85,7 +98,7 @@
|
|
#define STM32MP_DDR_BASE U(0xC0000000)
|
|
#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
|
|
#ifdef AARCH32_SP_OPTEE
|
|
-#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */
|
|
+#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */
|
|
#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */
|
|
#else
|
|
#define STM32MP_DDR_S_SIZE U(0) /* DDR is non secure */
|
|
@@ -122,9 +135,9 @@ enum ddr_type {
|
|
STM32MP_OPTEE_BASE)
|
|
#else
|
|
#if STACK_PROTECTOR_ENABLED
|
|
-#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */
|
|
+#define STM32MP_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */
|
|
#else
|
|
-#define STM32MP_BL32_SIZE U(0x00010000) /* 64 Ko for BL32 */
|
|
+#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */
|
|
#endif
|
|
#endif
|
|
|
|
@@ -134,30 +147,35 @@ enum ddr_type {
|
|
|
|
#ifdef AARCH32_SP_OPTEE
|
|
#if STACK_PROTECTOR_ENABLED
|
|
-#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */
|
|
+#define STM32MP_BL2_SIZE U(0x0001A000) /* 104 Ko for BL2 */
|
|
#else
|
|
-#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */
|
|
+#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */
|
|
#endif
|
|
#else
|
|
#if STACK_PROTECTOR_ENABLED
|
|
-#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */
|
|
+#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */
|
|
#else
|
|
-#define STM32MP_BL2_SIZE U(0x00016000) /* 88 Ko for BL2 */
|
|
+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */
|
|
#endif
|
|
#endif
|
|
|
|
#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \
|
|
STM32MP_BL2_SIZE)
|
|
|
|
-/* BL2 and BL32/sp_min require 7 tables */
|
|
-#define MAX_XLAT_TABLES U(7) /* 28 Ko for mapping */
|
|
+#if defined(STM32MP_USB)
|
|
+/* BL2 and BL32/sp_min require 5 finer granularity tables */
|
|
+ #define MAX_XLAT_TABLES U(5) /* 20 Ko for mapping */
|
|
+#else
|
|
+/* BL2 and BL32/sp_min require 4 finer granularity tables */
|
|
+ #define MAX_XLAT_TABLES U(4) /* 16 Ko for mapping */
|
|
+#endif
|
|
|
|
/*
|
|
* MAX_MMAP_REGIONS is usually:
|
|
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
|
|
*/
|
|
#if defined(IMAGE_BL2)
|
|
- #if (defined STM32MP_USB)
|
|
+ #if defined(STM32MP_USB)
|
|
#define MAX_MMAP_REGIONS 12
|
|
#else
|
|
#define MAX_MMAP_REGIONS 11
|
|
@@ -365,21 +383,16 @@ enum ddr_type {
|
|
|
|
#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U)
|
|
|
|
-/* OTP offsets */
|
|
-#define DATA0_OTP U(0)
|
|
-#define PART_NUMBER_OTP U(1)
|
|
-#define MONOTONIC_OTP U(4)
|
|
-#define NAND_OTP U(9)
|
|
-#define UID0_OTP U(13)
|
|
-#define UID1_OTP U(14)
|
|
-#define UID2_OTP U(15)
|
|
-#define PACKAGE_OTP U(16)
|
|
-#define HW2_OTP U(18) /* HW watchdog OTP */
|
|
+/* OTP labels */
|
|
+#define PART_NUMBER_OTP "part_number_otp"
|
|
+#define PACKAGE_OTP "package_otp"
|
|
+#define HW2_OTP "hw2_otp"
|
|
+#define NAND_OTP "nand_otp"
|
|
+#define MONOTONIC_OTP "monotonic_otp"
|
|
+#define UID_OTP "uid_otp"
|
|
+#define BOARD_ID_OTP "board_id"
|
|
|
|
/* OTP mask */
|
|
-/* DATA0 */
|
|
-#define DATA0_OTP_SECURED BIT(6)
|
|
-
|
|
/* PART NUMBER */
|
|
#define PART_SHIFT 0
|
|
#define PART_MASK GENMASK_32(7, 0)
|
|
@@ -431,8 +444,12 @@ enum ddr_type {
|
|
#define NAND_ECC_BIT_NB_4_BITS 2
|
|
#define NAND_ECC_BIT_NB_8_BITS 3
|
|
|
|
+/* MONOTONIC OTP */
|
|
#define MAX_MONOTONIC_VALUE 32
|
|
|
|
+/* UID OTP */
|
|
+#define UID_WORD_NB 3
|
|
+
|
|
/*******************************************************************************
|
|
* STM32MP1 FMC
|
|
******************************************************************************/
|
|
@@ -522,6 +539,14 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
|
|
#define TIM_MAX_INSTANCE U(2)
|
|
|
|
/*******************************************************************************
|
|
+ * STM32MP1 OPP
|
|
+ ******************************************************************************/
|
|
+#define PLAT_OPP_ID1 U(1)
|
|
+#define PLAT_OPP_ID2 U(2)
|
|
+#define PLAT_MAX_OPP_NB U(2)
|
|
+#define PLAT_MAX_PLLCFG_NB U(6)
|
|
+
|
|
+/*******************************************************************************
|
|
* DEBUG
|
|
******************************************************************************/
|
|
/*#define ICACHE_OFF*/
|
|
@@ -531,9 +556,12 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
|
|
/*******************************************************************************
|
|
* Device Tree defines
|
|
******************************************************************************/
|
|
-#define DT_BSEC_COMPAT "st,stm32mp15-bsec"
|
|
+#define DT_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout"
|
|
+#define DT_OPP_COMPAT "operating-points-v2"
|
|
#define DT_PWR_COMPAT "st,stm32mp1-pwr"
|
|
#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
|
|
#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg"
|
|
|
|
+#define DT_PLL1_NODE_NAME "st,pll@0"
|
|
+
|
|
#endif /* STM32MP1_DEF_H */
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_helper_dbg.S b/plat/st/stm32mp1/stm32mp1_helper_dbg.S
|
|
index 32a86fb..6e88e5b 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_helper_dbg.S
|
|
+++ b/plat/st/stm32mp1/stm32mp1_helper_dbg.S
|
|
@@ -10,6 +10,9 @@
|
|
* fixes the limitation. Anyway, this source code identifies the Soc revision
|
|
* and is only executed if it corresponds, so it can be kept on other
|
|
* revisions without any consequence.
|
|
+ * The revisions that need the workaround have ID values:
|
|
+ * - 0x2000X500
|
|
+ * - 0x2001X500
|
|
****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
@@ -18,6 +21,8 @@
|
|
* other pieces of software.
|
|
****************************************************************************/
|
|
|
|
+#include <asm_macros.S>
|
|
+
|
|
#define BIT_(nr) ((1) << (nr))
|
|
|
|
#define BSEC_BASE 0x5C005000
|
|
@@ -27,7 +32,7 @@
|
|
|
|
#define DBGMCU_BASE 0x50081000
|
|
#define DBGMCU_IDC 0x00
|
|
-#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFF0FFF
|
|
+#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFE0FFF
|
|
#define DBGMCU_IDC_REV_ID_DEV_ID_VALUE 0x20000500
|
|
|
|
#define RCC_BASE 0x50000000
|
|
@@ -53,7 +58,7 @@
|
|
.globl plat_dbg_attach_loop
|
|
|
|
|
|
-plat_dbg_attach_loop:
|
|
+func plat_dbg_attach_loop
|
|
/*
|
|
* This function is the first call of FSBL_ENTRYPOINT.
|
|
* Boot rom parameters are stored in r0..r3, so we mustn't use them
|
|
@@ -225,3 +230,4 @@ msb_incr:
|
|
bmi loop
|
|
func_exit:
|
|
bx lr
|
|
+endfunc plat_dbg_attach_loop
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
index f8b35dd..48b7af6 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
@@ -32,8 +32,7 @@
|
|
#include <stpmic1.h>
|
|
|
|
static unsigned int gicc_pmr;
|
|
-static struct stm32_rtc_calendar sleep_time, current_calendar;
|
|
-static unsigned long long stdby_time_in_ms;
|
|
+static struct stm32_rtc_calendar sleep_time;
|
|
static bool enter_cstop_done;
|
|
static uint8_t int_stack[STM32MP_INT_STACK_SIZE];
|
|
|
|
@@ -101,11 +100,11 @@ void stm32_apply_pmic_suspend_config(uint32_t mode)
|
|
panic();
|
|
}
|
|
|
|
- if (dt_pmic_set_lp_config(node_name) != 0) {
|
|
+ if (pmic_set_lp_config(node_name) < 0) {
|
|
panic();
|
|
}
|
|
|
|
- if (dt_pmic_configure_boot_on_regulators() != 0) {
|
|
+ if (pmic_configure_boot_on_regulators() < 0) {
|
|
panic();
|
|
}
|
|
}
|
|
@@ -131,6 +130,9 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
|
|
stm32mp1_syscfg_disable_io_compensation();
|
|
|
|
+ /* Switch to Software Self-Refresh */
|
|
+ ddr_sr_mode_ssr();
|
|
+
|
|
dcsw_op_all(DC_OP_CISW);
|
|
|
|
stm32_clean_context();
|
|
@@ -225,6 +227,8 @@ void stm32_exit_cstop(void)
|
|
{
|
|
uintptr_t pwr_base = stm32mp_pwr_base();
|
|
uintptr_t rcc_base = stm32mp_rcc_base();
|
|
+ unsigned long long stdby_time_in_ms;
|
|
+ struct stm32_rtc_calendar current_calendar;
|
|
|
|
if (!enter_cstop_done) {
|
|
return;
|
|
@@ -238,6 +242,9 @@ void stm32_exit_cstop(void)
|
|
panic();
|
|
}
|
|
|
|
+ /* Switch to Automatic Self-Refresh */
|
|
+ ddr_sr_mode_asr();
|
|
+
|
|
plat_ic_set_priority_mask(gicc_pmr);
|
|
|
|
/* Disable RCC Wake-up */
|
|
@@ -259,7 +266,8 @@ void stm32_exit_cstop(void)
|
|
stdby_time_in_ms = stm32_rtc_diff_calendar(¤t_calendar,
|
|
&sleep_time);
|
|
|
|
- stm32mp1_stgen_increment(stdby_time_in_ms);
|
|
+ stm32mp1_stgen_restore_counter(stm32_get_stgen_from_context(),
|
|
+ stdby_time_in_ms);
|
|
|
|
stm32mp1_syscfg_enable_io_compensation();
|
|
}
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
|
|
index b95bc3d..e431199 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_pm.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -71,14 +71,8 @@ static int stm32_pwr_domain_on(u_register_t mpidr)
|
|
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
|
|
uint32_t bkpr_core1_magic =
|
|
tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
|
|
- int result;
|
|
|
|
- result = stm32mp_is_single_core();
|
|
- if (result < 0) {
|
|
- return PSCI_E_INTERN_FAIL;
|
|
- }
|
|
-
|
|
- if (result == 1) {
|
|
+ if (stm32mp_is_single_core()) {
|
|
return PSCI_E_INTERN_FAIL;
|
|
}
|
|
|
|
@@ -203,7 +197,7 @@ static void __dead2 stm32_system_off(void)
|
|
{
|
|
uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF);
|
|
|
|
- if (stm32mp_is_single_core() == 0) {
|
|
+ if (!stm32mp_is_single_core()) {
|
|
/* Prepare Core 1 reset */
|
|
mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
|
|
RCC_MP_GRSTCSETR_MPUP1RST);
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c
|
|
index ec7ecb1..d5dd671 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_power_config.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_power_config.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -13,7 +13,6 @@
|
|
#include <stm32mp_dt.h>
|
|
#include <stm32mp1_power_config.h>
|
|
|
|
-#define DT_PWR_COMPAT "st,stm32mp1-pwr"
|
|
#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes"
|
|
#define SYSTEM_OFF_MODE "system_off_soc_mode"
|
|
|
|
@@ -21,9 +20,9 @@ static uint32_t deepest_system_suspend_mode;
|
|
static uint32_t system_off_mode;
|
|
static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE];
|
|
|
|
-static int dt_get_pwr_node(void *fdt)
|
|
+static int dt_get_pwr_node(void)
|
|
{
|
|
- return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
|
|
+ return dt_get_node_by_compatible(DT_PWR_COMPAT);
|
|
}
|
|
|
|
static void save_supported_mode(void *fdt, int pwr_node)
|
|
@@ -77,7 +76,7 @@ static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state)
|
|
return -ENOENT;
|
|
}
|
|
|
|
- pwr_node = dt_get_pwr_node(fdt);
|
|
+ pwr_node = dt_get_pwr_node();
|
|
if (pwr_node < 0) {
|
|
return -FDT_ERR_NOTFOUND;
|
|
}
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
|
|
index aae537f..d399dc8 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_private.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_private.c
|
|
@@ -15,6 +15,9 @@
|
|
#include <stm32_iwdg.h>
|
|
#include <stm32mp_common.h>
|
|
#include <stm32mp_dt.h>
|
|
+#include <stm32mp_dummy_regulator.h>
|
|
+#include <stm32mp_pmic.h>
|
|
+#include <stm32mp_regulator.h>
|
|
#include <stm32mp_reset.h>
|
|
#include <xlat_tables_v2.h>
|
|
|
|
@@ -243,7 +246,7 @@ void __dead2 stm32mp_plat_reset(int cpu)
|
|
}
|
|
}
|
|
|
|
- if (stm32mp_is_single_core() == 0) {
|
|
+ if (!stm32mp_is_single_core()) {
|
|
unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ?
|
|
STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU;
|
|
|
|
@@ -266,38 +269,131 @@ void __dead2 stm32mp_plat_reset(int cpu)
|
|
stm32mp_wait_cpu_reset();
|
|
}
|
|
|
|
-static uint32_t get_part_number(void)
|
|
+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx,
|
|
+ uint32_t *otp_len)
|
|
{
|
|
- uint32_t part_number = 0;
|
|
+ assert(otp_name != NULL);
|
|
+ assert(otp_idx != NULL);
|
|
|
|
- if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) {
|
|
- ERROR("BSEC: PART_NUMBER_OTP Error\n");
|
|
+ if (bsec_find_otp_name_in_dt(otp_name, otp_idx, otp_len) != BSEC_OK) {
|
|
+ ERROR("BSEC: Get %s number Error\n", otp_name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val)
|
|
+{
|
|
+ uint32_t otp;
|
|
+
|
|
+ assert(otp_name != NULL);
|
|
+ assert(otp_val != NULL);
|
|
+
|
|
+ if (stm32_get_otp_index(otp_name, &otp, NULL) != 0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+#if defined(IMAGE_BL2)
|
|
+ if (bsec_shadow_read_otp(otp_val, otp) != BSEC_OK) {
|
|
+ ERROR("BSEC: %s Read Error\n", otp_name);
|
|
+ return -1;
|
|
+ }
|
|
+#elif defined(IMAGE_BL32)
|
|
+ if (bsec_read_otp(otp_val, otp) != BSEC_OK) {
|
|
+ ERROR("BSEC: %s Read Error\n", otp_name);
|
|
+ return -1;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int get_part_number(uint32_t *part_nb)
|
|
+{
|
|
+ uint32_t part_number;
|
|
+ uint32_t dev_id;
|
|
+
|
|
+ assert(part_nb != NULL);
|
|
+
|
|
+ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
part_number = (part_number & PART_MASK) >> PART_SHIFT;
|
|
|
|
- return (part_number | (stm32mp1_dbgmcu_get_chip_dev_id() << 16));
|
|
+ *part_nb = part_number | (dev_id << 16);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
-static uint32_t get_cpu_package(void)
|
|
+static int get_cpu_package(uint32_t *cpu_package)
|
|
{
|
|
- uint32_t package = 0;
|
|
+ uint32_t package;
|
|
+
|
|
+ assert(cpu_package != NULL);
|
|
|
|
- if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) {
|
|
- ERROR("BSEC: PART_NUMBER_OTP Error\n");
|
|
+ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
- return ((package & PKG_MASK) >> PKG_SHIFT);
|
|
+ *cpu_package = (package & PKG_MASK) >> PKG_SHIFT;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+bool stm32mp_supports_cpu_opp(uint32_t opp_id)
|
|
+{
|
|
+ uint32_t part_number;
|
|
+ uint32_t id;
|
|
+
|
|
+ if (get_part_number(&part_number) != 0) {
|
|
+ ERROR("Cannot get part number\n");
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ switch (opp_id) {
|
|
+ case PLAT_OPP_ID1:
|
|
+ case PLAT_OPP_ID2:
|
|
+ id = opp_id;
|
|
+ break;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ switch (part_number) {
|
|
+ case STM32MP157F_PART_NB:
|
|
+ case STM32MP157D_PART_NB:
|
|
+ case STM32MP153F_PART_NB:
|
|
+ case STM32MP153D_PART_NB:
|
|
+ case STM32MP151F_PART_NB:
|
|
+ case STM32MP151D_PART_NB:
|
|
+ return true;
|
|
+ default:
|
|
+ return id == PLAT_OPP_ID1;
|
|
+ }
|
|
}
|
|
|
|
void stm32mp_print_cpuinfo(void)
|
|
{
|
|
const char *cpu_s, *cpu_r, *pkg;
|
|
+ uint32_t part_number;
|
|
+ uint32_t cpu_package;
|
|
+ uint32_t chip_dev_id;
|
|
+ int ret;
|
|
|
|
/* MPUs Part Numbers */
|
|
- switch (get_part_number()) {
|
|
+ ret = get_part_number(&part_number);
|
|
+ if (ret < 0) {
|
|
+ WARN("Cannot get part number\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ switch (part_number) {
|
|
case STM32MP157C_PART_NB:
|
|
cpu_s = "157C";
|
|
break;
|
|
@@ -316,13 +412,37 @@ void stm32mp_print_cpuinfo(void)
|
|
case STM32MP151A_PART_NB:
|
|
cpu_s = "151A";
|
|
break;
|
|
+ case STM32MP157F_PART_NB:
|
|
+ cpu_s = "157F";
|
|
+ break;
|
|
+ case STM32MP157D_PART_NB:
|
|
+ cpu_s = "157D";
|
|
+ break;
|
|
+ case STM32MP153F_PART_NB:
|
|
+ cpu_s = "153F";
|
|
+ break;
|
|
+ case STM32MP153D_PART_NB:
|
|
+ cpu_s = "153D";
|
|
+ break;
|
|
+ case STM32MP151F_PART_NB:
|
|
+ cpu_s = "151F";
|
|
+ break;
|
|
+ case STM32MP151D_PART_NB:
|
|
+ cpu_s = "151D";
|
|
+ break;
|
|
default:
|
|
cpu_s = "????";
|
|
break;
|
|
}
|
|
|
|
/* Package */
|
|
- switch (get_cpu_package()) {
|
|
+ ret = get_cpu_package(&cpu_package);
|
|
+ if (ret < 0) {
|
|
+ WARN("Cannot get CPU package\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ switch (cpu_package) {
|
|
case PKG_AA_LBGA448:
|
|
pkg = "AA";
|
|
break;
|
|
@@ -341,13 +461,22 @@ void stm32mp_print_cpuinfo(void)
|
|
}
|
|
|
|
/* REVISION */
|
|
- switch (stm32mp1_dbgmcu_get_chip_version()) {
|
|
+ ret = stm32mp1_dbgmcu_get_chip_version(&chip_dev_id);
|
|
+ if (ret < 0) {
|
|
+ WARN("Cannot get CPU version\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ switch (chip_dev_id) {
|
|
case STM32MP1_REV_A:
|
|
cpu_r = "A";
|
|
break;
|
|
case STM32MP1_REV_B:
|
|
cpu_r = "B";
|
|
break;
|
|
+ case STM32MP1_REV_Z:
|
|
+ cpu_r = "Z";
|
|
+ break;
|
|
default:
|
|
cpu_r = "?";
|
|
break;
|
|
@@ -359,35 +488,8 @@ void stm32mp_print_cpuinfo(void)
|
|
void stm32mp_print_boardinfo(void)
|
|
{
|
|
uint32_t board_id = 0;
|
|
- uint32_t board_otp;
|
|
- int bsec_node, bsec_board_id_node;
|
|
- void *fdt;
|
|
- const fdt32_t *cuint;
|
|
|
|
- if (fdt_get_address(&fdt) == 0) {
|
|
- panic();
|
|
- }
|
|
-
|
|
- bsec_node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT);
|
|
- if (bsec_node < 0) {
|
|
- return;
|
|
- }
|
|
-
|
|
- bsec_board_id_node = fdt_subnode_offset(fdt, bsec_node, "board_id");
|
|
- if (bsec_board_id_node <= 0) {
|
|
- return;
|
|
- }
|
|
-
|
|
- cuint = fdt_getprop(fdt, bsec_board_id_node, "reg", NULL);
|
|
- if (cuint == NULL) {
|
|
- ERROR("board_id node without reg property\n");
|
|
- panic();
|
|
- }
|
|
-
|
|
- board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
|
|
-
|
|
- if (bsec_shadow_read_otp(&board_id, board_otp) != BSEC_OK) {
|
|
- ERROR("BSEC: PART_NUMBER_OTP Error\n");
|
|
+ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) {
|
|
return;
|
|
}
|
|
|
|
@@ -404,22 +506,35 @@ void stm32mp_print_boardinfo(void)
|
|
}
|
|
}
|
|
|
|
-/*
|
|
- * This function determines if one single core is presently running. This is
|
|
- * done by OTP read.
|
|
- * Returns 1 if yes, 0 if more that one core is running, -1 if error.
|
|
- */
|
|
-int stm32mp_is_single_core(void)
|
|
+/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */
|
|
+bool stm32mp_is_single_core(void)
|
|
{
|
|
- uint32_t part_number = get_part_number();
|
|
+ uint32_t part_number;
|
|
|
|
- /* STM32MP151x is a single core */
|
|
- if ((part_number == STM32MP151A_PART_NB) ||
|
|
- (part_number == STM32MP151C_PART_NB)) {
|
|
- return 1;
|
|
+ if (get_part_number(&part_number) < 0) {
|
|
+ ERROR("Invalid part number, assume single core chip");
|
|
+ return true;
|
|
}
|
|
|
|
- return 0;
|
|
+ switch (part_number) {
|
|
+ case STM32MP151A_PART_NB:
|
|
+ case STM32MP151C_PART_NB:
|
|
+ case STM32MP151D_PART_NB:
|
|
+ case STM32MP151F_PART_NB:
|
|
+ return true;
|
|
+
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Return true if DDR supports Software/Automatic Self-Refresh */
|
|
+bool stm32mp_ddr_supports_ssr_asr(void)
|
|
+{
|
|
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
|
|
+ uint32_t mstr = mmio_read_32(ddrctrl_base + DDRCTRL_MSTR);
|
|
+
|
|
+ return (mstr & DDRCTRL_MSTR_LPDDR2) != 0U;
|
|
}
|
|
|
|
uint8_t stm32_iwdg_get_instance(uintptr_t base)
|
|
@@ -440,15 +555,9 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base)
|
|
uint32_t iwdg_cfg = 0;
|
|
uint32_t otp_value;
|
|
|
|
-#if defined(IMAGE_BL2)
|
|
- if (bsec_shadow_read_otp(&otp_value, HW2_OTP) != BSEC_OK) {
|
|
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
|
|
panic();
|
|
}
|
|
-#elif defined(IMAGE_BL32)
|
|
- if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) {
|
|
- panic();
|
|
- }
|
|
-#endif
|
|
|
|
idx = stm32_iwdg_get_instance(base);
|
|
|
|
@@ -471,31 +580,36 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base)
|
|
uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags)
|
|
{
|
|
uint32_t idx;
|
|
+ uint32_t otp_value;
|
|
uint32_t otp;
|
|
uint32_t result;
|
|
|
|
- if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) {
|
|
+ if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
|
|
panic();
|
|
}
|
|
|
|
idx = stm32_iwdg_get_instance(base);
|
|
|
|
if ((flags & IWDG_DISABLE_ON_STOP) != 0) {
|
|
- otp |= BIT(idx + IWDG_FZ_STOP_POS);
|
|
+ otp_value |= BIT(idx + IWDG_FZ_STOP_POS);
|
|
}
|
|
|
|
if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) {
|
|
- otp |= BIT(idx + IWDG_FZ_STANDBY_POS);
|
|
+ otp_value |= BIT(idx + IWDG_FZ_STANDBY_POS);
|
|
}
|
|
|
|
- result = bsec_write_otp(otp, HW2_OTP);
|
|
+ result = bsec_write_otp(otp_value, otp);
|
|
if (result != BSEC_OK) {
|
|
return result;
|
|
}
|
|
|
|
/* Sticky lock OTP_IWDG (read and write) */
|
|
- if ((bsec_set_sr_lock(HW2_OTP) != BSEC_OK) ||
|
|
- (bsec_set_sw_lock(HW2_OTP) != BSEC_OK)) {
|
|
+ if ((bsec_set_sr_lock(otp) != BSEC_OK) ||
|
|
+ (bsec_set_sw_lock(otp) != BSEC_OK)) {
|
|
return BSEC_LOCK_FAIL;
|
|
}
|
|
|
|
@@ -524,3 +638,26 @@ enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode)
|
|
panic();
|
|
}
|
|
}
|
|
+
|
|
+int plat_bind_regulator(struct stm32mp_regulator *regu)
|
|
+{
|
|
+ void *fdt;
|
|
+ int regu_node;
|
|
+
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if ((dt_pmic_status() > 0) && is_pmic_regulator(regu)) {
|
|
+ bind_pmic_regulator(regu);
|
|
+ } else {
|
|
+ bind_dummy_regulator(regu);
|
|
+ }
|
|
+
|
|
+ regu_node = fdt_node_offset_by_phandle(fdt, regu->id);
|
|
+ if (fdt_getprop(fdt, regu_node, "regulator-always-on", NULL) != NULL) {
|
|
+ regu->always_on = true;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
|
|
index d2da110..9ad9486 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_security.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_security.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -24,6 +24,7 @@ static void init_tzc400(void)
|
|
unsigned long long region_base, region_top;
|
|
unsigned long long ddr_base = STM32MP_DDR_BASE;
|
|
unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size();
|
|
+ unsigned long long ddr_top = ddr_base + (ddr_size - 1U);
|
|
|
|
tzc400_init(STM32MP1_TZC_BASE);
|
|
|
|
@@ -35,7 +36,7 @@ static void init_tzc400(void)
|
|
* same configuration to all filters in the TZC.
|
|
*/
|
|
region_base = ddr_base;
|
|
- region_top = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE - 1U);
|
|
+ region_top = ddr_top - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE;
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
|
region_base,
|
|
region_top,
|
|
@@ -53,8 +54,8 @@ static void init_tzc400(void)
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
|
|
|
|
/* Region 2 set to cover all secure DRAM. */
|
|
- region_base = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE);
|
|
- region_top = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE - 1U);
|
|
+ region_base = region_top + 1U;
|
|
+ region_top = ddr_top - STM32MP_DDR_SHMEM_SIZE;
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
|
|
region_base,
|
|
region_top,
|
|
@@ -62,8 +63,8 @@ static void init_tzc400(void)
|
|
0);
|
|
|
|
/* Region 3 set to cover non-secure shared memory DRAM. */
|
|
- region_base = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE);
|
|
- region_top = ddr_base + (ddr_size - 1U);
|
|
+ region_base = region_top + 1U;
|
|
+ region_top = ddr_top;
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
|
|
region_base,
|
|
region_top,
|
|
@@ -85,7 +86,7 @@ static void init_tzc400(void)
|
|
* same configuration to all filters in the TZC.
|
|
*/
|
|
region_base = ddr_base;
|
|
- region_top = ddr_base + (ddr_size - 1U);
|
|
+ region_top = ddr_top;
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
|
region_base,
|
|
region_top,
|
|
@@ -103,8 +104,11 @@ static void init_tzc400(void)
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
|
|
#endif
|
|
|
|
- /* Raise an exception if a NS device tries to access secure memory */
|
|
- tzc400_set_action(TZC_ACTION_ERR);
|
|
+ /*
|
|
+ * Raise an interrupt (secure FIQ) if a NS device tries to access
|
|
+ * secure memory
|
|
+ */
|
|
+ tzc400_set_action(TZC_ACTION_INT);
|
|
|
|
tzc400_enable_filters();
|
|
}
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
index 3276870..47a16ac 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
@@ -4,18 +4,18 @@
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
-#include <bsec.h>
|
|
#include <debug.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
+#include <stm32mp_common.h>
|
|
#include <stm32mp_dt.h>
|
|
#include <stm32mp1_clk.h>
|
|
#include <stm32mp1_private.h>
|
|
#include <stpmic1.h>
|
|
|
|
/*
|
|
- * SYSCFG REGISTER OFFSET (base relative)
|
|
+ * SYSCFG register offsets (base relative)
|
|
*/
|
|
#define SYSCFG_BOOTR 0x00U
|
|
#define SYSCFG_IOCTRLSETR 0x18U
|
|
@@ -52,6 +52,8 @@
|
|
#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
|
|
#define SYSCFG_CMPCR_ANSRC_SHIFT 24
|
|
|
|
+#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
|
|
+
|
|
/*
|
|
* SYSCFG_CMPENSETR Register
|
|
*/
|
|
@@ -60,9 +62,10 @@
|
|
void stm32mp1_syscfg_init(void)
|
|
{
|
|
uint32_t bootr;
|
|
- uint32_t otp = 0;
|
|
+ uint32_t otp_value;
|
|
uint32_t vdd_voltage;
|
|
uintptr_t syscfg_base = dt_get_syscfg_base();
|
|
+ bool product_below_2v5;
|
|
|
|
/*
|
|
* Interconnect update : select master using the port 1.
|
|
@@ -96,11 +99,11 @@ void stm32mp1_syscfg_init(void)
|
|
* => 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) {
|
|
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
|
|
panic();
|
|
}
|
|
|
|
- otp = otp & HW2_OTP_PRODUCT_BELOW_2V5;
|
|
+ product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
|
|
|
|
/* Get VDD supply */
|
|
vdd_voltage = dt_get_pwr_vdd_voltage();
|
|
@@ -117,11 +120,11 @@ void stm32mp1_syscfg_init(void)
|
|
SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
|
|
SYSCFG_IOCTRLSETR_HSLVEN_SPI);
|
|
|
|
- if (otp == 0U) {
|
|
+ if (!product_below_2v5) {
|
|
INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
|
|
}
|
|
} else {
|
|
- if (otp != 0U) {
|
|
+ if (product_below_2v5) {
|
|
ERROR("Product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
|
|
panic();
|
|
}
|
|
@@ -137,6 +140,7 @@ void stm32mp1_syscfg_init(void)
|
|
void stm32mp1_syscfg_enable_io_compensation(void)
|
|
{
|
|
uintptr_t syscfg_base = dt_get_syscfg_base();
|
|
+ uint64_t start;
|
|
|
|
/*
|
|
* Activate automatic I/O compensation.
|
|
@@ -148,9 +152,18 @@ void stm32mp1_syscfg_enable_io_compensation(void)
|
|
mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR,
|
|
SYSCFG_CMPENSETR_MPU_EN);
|
|
|
|
+ start = timeout_start();
|
|
+
|
|
while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) &
|
|
SYSCFG_CMPCR_READY) == 0U) {
|
|
- ;
|
|
+ if (timeout_elapsed(start, SYSCFG_CMPCR_READY_TIMEOUT_US)) {
|
|
+ /*
|
|
+ * Failure on IO compensation enable is not a issue:
|
|
+ * warn only.
|
|
+ */
|
|
+ WARN("IO compensation cell not ready\n");
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
|
|
@@ -180,9 +193,7 @@ void stm32mp1_syscfg_disable_io_compensation(void)
|
|
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_write_32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL);
|
|
|
|
VERBOSE("[0x%x] SYSCFG.cmpcr = 0x%08x\n",
|
|
(uint32_t)syscfg_base + SYSCFG_CMPCR,
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_usb_desc.c b/plat/st/stm32mp1/stm32mp1_usb_desc.c
|
|
index 410cfa1..25246e9 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_usb_desc.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_usb_desc.c
|
|
@@ -1,12 +1,14 @@
|
|
/*
|
|
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <bsec.h>
|
|
#include <debug.h>
|
|
+#include <limits.h>
|
|
#include <platform_def.h>
|
|
+#include <stm32mp_common.h>
|
|
#include <stm32mp1_usb_desc.h>
|
|
#include <string.h>
|
|
#include <usb_core.h>
|
|
@@ -148,10 +150,22 @@ static void update_serial_num_string(void)
|
|
{
|
|
/* serial number is set to 0*/
|
|
uint8_t i;
|
|
- uint32_t deviceserial[3] = {0, 0, 0};
|
|
+ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U};
|
|
+ uint32_t otp;
|
|
+ uint32_t len;
|
|
|
|
- for (i = 0; i < 3; i++) {
|
|
- if (bsec_shadow_read_otp(&deviceserial[i], i + UID0_OTP) !=
|
|
+ if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
|
|
+ ERROR("BSEC: Get UID_OTP number Error\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if ((len / __WORD_BIT) != UID_WORD_NB) {
|
|
+ ERROR("BSEC: Get UID_OTP length Error\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < UID_WORD_NB; i++) {
|
|
+ if (bsec_shadow_read_otp(&deviceserial[i], i + otp) !=
|
|
BSEC_OK) {
|
|
ERROR("BSEC: UID%d Error\n", i);
|
|
return;
|
|
diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c
|
|
index 41024e2..e80bf0b 100644
|
|
--- a/tools/stm32image/stm32image.c
|
|
+++ b/tools/stm32image/stm32image.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -45,8 +45,6 @@ struct stm32_header {
|
|
uint8_t binary_type;
|
|
};
|
|
|
|
-static struct stm32_header stm32image_header;
|
|
-
|
|
static void stm32image_default_header(struct stm32_header *ptr)
|
|
{
|
|
if (!ptr) {
|
|
@@ -56,8 +54,8 @@ static void stm32image_default_header(struct stm32_header *ptr)
|
|
ptr->magic_number = HEADER_MAGIC;
|
|
ptr->header_version[VER_MAJOR] = HEADER_VERSION_V1;
|
|
ptr->option_flags = HEADER_DEFAULT_OPTION;
|
|
- ptr->ecdsa_algorithm = 1;
|
|
- ptr->version_number = 0;
|
|
+ ptr->ecdsa_algorithm = __cpu_to_le32(1);
|
|
+ ptr->version_number = __cpu_to_le32(0);
|
|
ptr->binary_type = TF_BINARY_TYPE;
|
|
}
|
|
|
|
@@ -115,7 +113,8 @@ static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd,
|
|
stm32hdr->image_entry_point = __cpu_to_le32(ep);
|
|
stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size -
|
|
sizeof(struct stm32_header));
|
|
- stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size);
|
|
+ stm32hdr->image_checksum =
|
|
+ __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size));
|
|
stm32hdr->version_number = __cpu_to_le32(ver);
|
|
}
|
|
|
|
@@ -126,6 +125,7 @@ static int stm32image_create_header_file(char *srcname, char *destname,
|
|
int src_fd, dest_fd;
|
|
struct stat sbuf;
|
|
unsigned char *ptr;
|
|
+ struct stm32_header stm32image_header;
|
|
|
|
dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666);
|
|
if (dest_fd == -1) {
|
|
@@ -204,13 +204,13 @@ int main(int argc, char *argv[])
|
|
dest = optarg;
|
|
break;
|
|
case 'l':
|
|
- loadaddr = strtol(optarg, NULL, 16);
|
|
+ loadaddr = strtol(optarg, NULL, 0);
|
|
break;
|
|
case 'e':
|
|
- entry = strtol(optarg, NULL, 16);
|
|
+ entry = strtol(optarg, NULL, 0);
|
|
break;
|
|
case 'v':
|
|
- version = strtol(optarg, NULL, 10);
|
|
+ version = strtol(optarg, NULL, 0);
|
|
break;
|
|
default:
|
|
fprintf(stderr,
|
|
--
|
|
2.7.4
|
|
|