meta-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-st-update-r1.2.0.patch

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(&params) != 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(&current_calendar);
stdby_time_in_ms = stm32_rtc_diff_calendar(&current_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(&current_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