meta-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0003-v2.4-stm32mp-r2.patch

8217 lines
227 KiB
Diff

From 1fe2b03c3d3ef5e550fefe361f69bff86bddf698 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Thu, 28 Oct 2021 15:51:21 +0200
Subject: [PATCH] v2.4-stm32mp-r2
---
bl32/tsp/aarch64/tsp_entrypoint.S | 22 +-
docs/license.rst | 10 +
drivers/mtd/nand/spi_nand.c | 8 +-
drivers/regulator/regulator_core.c | 1142 +++++++++++++++++
drivers/st/clk/stm32mp1_clk.c | 29 +-
drivers/st/ddr/stm32mp1_ddr.c | 11 +-
drivers/st/ddr/stm32mp1_ram.c | 169 +--
drivers/st/ddr/stm32mp_ddr_test.c | 148 +++
drivers/st/fmc/stm32_fmc2_nand.c | 11 +-
drivers/st/gpio/stm32_gpio.c | 9 +-
drivers/st/mmc/stm32_sdmmc2.c | 16 +-
drivers/st/pmic/stm32mp_pmic.c | 718 +++++------
drivers/st/pmic/stpmic1.c | 158 ++-
drivers/st/regulator/regulator_fixed.c | 91 ++
.../st/regulator/stm32mp_dummy_regulator.c | 27 -
drivers/st/regulator/stm32mp_regulator.c | 38 -
drivers/st/tamper/stm32_tamp.c | 691 +++++++---
drivers/st/uart/aarch32/stm32_console.S | 11 +-
fdts/stm32mp15-ddr-512m-fw-config.dts | 63 -
fdts/stm32mp15-ddr.dtsi | 266 ++--
fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 6 +-
fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 6 +-
...-fw-config.dts => stm32mp15-fw-config.dts} | 25 +-
fdts/stm32mp151.dtsi | 18 +
fdts/stm32mp157a-avenger96-fw-config.dts | 3 +-
fdts/stm32mp157a-dk1-fw-config.dts | 3 +-
fdts/stm32mp157a-ed1-fw-config.dts | 3 +-
fdts/stm32mp157a-ev1-fw-config.dts | 3 +-
fdts/stm32mp157c-dk2-fw-config.dts | 3 +-
fdts/stm32mp157c-ed1-fw-config.dts | 3 +-
fdts/stm32mp157c-ev1-fw-config.dts | 3 +-
fdts/stm32mp157d-dk1-fw-config.dts | 3 +-
fdts/stm32mp157d-ed1-fw-config.dts | 3 +-
fdts/stm32mp157d-ev1-fw-config.dts | 3 +-
fdts/stm32mp157f-dk2-fw-config.dts | 3 +-
fdts/stm32mp157f-ed1-fw-config.dts | 3 +-
fdts/stm32mp157f-ev1-fw-config.dts | 3 +-
fdts/stm32mp15xx-dkx.dtsi | 8 +-
fdts/stm32mp15xx-edx.dtsi | 8 +-
include/arch/aarch32/el3_common_macros.S | 13 +-
include/arch/aarch64/el3_common_macros.S | 15 +-
include/drivers/regulator.h | 160 +++
include/drivers/st/regulator_fixed.h | 12 +
include/drivers/st/stm32_gpio.h | 3 +-
include/drivers/st/stm32_sdmmc2.h | 4 +-
include/drivers/st/stm32_tamp.h | 311 +++--
include/drivers/st/stm32mp1_ddr_regs.h | 1 +
include/drivers/st/stm32mp1_rcc.h | 2 +
include/drivers/st/stm32mp_ddr_test.h | 15 +
include/drivers/st/stm32mp_dummy_regulator.h | 14 -
include/drivers/st/stm32mp_pmic.h | 46 +-
include/drivers/st/stm32mp_regulator.h | 31 -
include/drivers/st/stpmic1.h | 28 +
.../interrupt-controller/arm-gic.h | 19 +-
.../dt-bindings/interrupt-controller/irq.h | 23 +
lib/aarch32/misc_helpers.S | 4 +-
licenses/LICENSE.MIT | 21 +
plat/st/common/bl2_io_storage.c | 10 +-
plat/st/common/include/stm32cubeprogrammer.h | 3 -
plat/st/common/include/stm32mp_common.h | 15 +-
plat/st/common/include/stm32mp_dt.h | 6 +-
plat/st/common/stm32cubeprogrammer_uart.c | 21 +-
plat/st/common/stm32mp_common.c | 94 +-
plat/st/common/stm32mp_dt.c | 86 +-
plat/st/common/stm32mp_trusted_boot.c | 2 +-
plat/st/stm32mp1/bl2_plat_setup.c | 49 +-
.../stm32mp1/include/stm32mp1_critic_power.h | 8 +-
plat/st/stm32mp1/include/stm32mp1_private.h | 4 +-
plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 61 +-
plat/st/stm32mp1/platform.mk | 23 +-
plat/st/stm32mp1/services/bsec_svc.c | 11 +-
plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 1 +
plat/st/stm32mp1/sp_min/sp_min_setup.c | 157 +--
plat/st/stm32mp1/stm32mp1_context.c | 16 +-
plat/st/stm32mp1/stm32mp1_critic_power.c | 49 +-
.../stm32mp1/stm32mp1_critic_power_wrapper.S | 16 +-
plat/st/stm32mp1/stm32mp1_def.h | 23 +-
plat/st/stm32mp1/stm32mp1_helper.S | 4 +-
plat/st/stm32mp1/stm32mp1_low_power.c | 51 +-
plat/st/stm32mp1/stm32mp1_pm.c | 7 +-
plat/st/stm32mp1/stm32mp1_private.c | 234 ++--
plat/st/stm32mp1/stm32mp1_ssp.c | 23 +-
plat/st/stm32mp1/stm32mp1_syscfg.c | 130 +-
plat/st/stm32mp1/stm32mp1_usb.c | 4 +-
84 files changed, 3675 insertions(+), 1903 deletions(-)
create mode 100644 drivers/regulator/regulator_core.c
create mode 100644 drivers/st/ddr/stm32mp_ddr_test.c
create mode 100644 drivers/st/regulator/regulator_fixed.c
delete mode 100644 drivers/st/regulator/stm32mp_dummy_regulator.c
delete mode 100644 drivers/st/regulator/stm32mp_regulator.c
delete mode 100644 fdts/stm32mp15-ddr-512m-fw-config.dts
rename fdts/{stm32mp15-ddr-1g-fw-config.dts => stm32mp15-fw-config.dts} (60%)
create mode 100644 include/drivers/regulator.h
create mode 100644 include/drivers/st/regulator_fixed.h
create mode 100644 include/drivers/st/stm32mp_ddr_test.h
delete mode 100644 include/drivers/st/stm32mp_dummy_regulator.h
delete mode 100644 include/drivers/st/stm32mp_regulator.h
create mode 100644 include/dt-bindings/interrupt-controller/irq.h
create mode 100644 licenses/LICENSE.MIT
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index a007bab302..a9d03c379e 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -100,11 +100,27 @@ func tsp_entrypoint _align=3
* sections. This is done to safeguard against
* possible corruption of this memory by dirty
* cache lines in a system cache as a result of
- * use by an earlier boot loader stage.
+ * use by an earlier boot loader stage. If PIE
+ * is enabled however, RO sections including the
+ * GOT may be modified during pie fixup.
+ * Therefore, to be on the safe side, invalidate
+ * the entire image region if PIE is enabled.
* ---------------------------------------------
*/
- adr x0, __RW_START__
- adr x1, __RW_END__
+#if ENABLE_PIE
+#if SEPARATE_CODE_AND_RODATA
+ adrp x0, __TEXT_START__
+ add x0, x0, :lo12:__TEXT_START__
+#else
+ adrp x0, __RO_START__
+ add x0, x0, :lo12:__RO_START__
+#endif /* SEPARATE_CODE_AND_RODATA */
+#else
+ adrp x0, __RW_START__
+ add x0, x0, :lo12:__RW_START__
+#endif /* ENABLE_PIE */
+ adrp x1, __RW_END__
+ add x1, x1, :lo12:__RW_END__
sub x1, x1, x0
bl inv_dcache_range
diff --git a/docs/license.rst b/docs/license.rst
index 2f9704335f..80f1118609 100644
--- a/docs/license.rst
+++ b/docs/license.rst
@@ -76,5 +76,15 @@ license text is included in those source files.
BSD-3-Clause license. Any contributions to this code must be made under the
terms of both licenses.
+- Some source files originating from the Linux source tree, which are
+ disjunctively dual licensed (GPL-2.0 OR MIT), are redistributed under the
+ terms of the MIT license. These files are:
+
+ - ``include/dt-bindings/interrupt-controller/arm-gic.h``
+ - ``include/dt-bindings/interrupt-controller/irq.h``
+
+ See the original `Linux MIT license`_.
+
.. _FreeBSD: http://www.freebsd.org
+.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT
.. _SCC: http://www.simple-cc.org/
diff --git a/drivers/mtd/nand/spi_nand.c b/drivers/mtd/nand/spi_nand.c
index d01a11963f..18913a57db 100644
--- a/drivers/mtd/nand/spi_nand.c
+++ b/drivers/mtd/nand/spi_nand.c
@@ -286,6 +286,10 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size)
return -EINVAL;
}
+ assert((spinand_dev.nand_dev->page_size != 0U) &&
+ (spinand_dev.nand_dev->block_size != 0U) &&
+ (spinand_dev.nand_dev->size != 0U));
+
ret = spi_nand_reset();
if (ret != 0) {
return ret;
@@ -301,12 +305,12 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size)
return ret;
}
- ret = spi_nand_quad_enable(id[0]);
+ ret = spi_nand_quad_enable(id[1]);
if (ret != 0) {
return ret;
}
- VERBOSE("SPI_NAND Detected ID 0x%x 0x%x\n", id[0], id[1]);
+ VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]);
VERBOSE("Page size %i, Block size %i, size %lli\n",
spinand_dev.nand_dev->page_size,
diff --git a/drivers/regulator/regulator_core.c b/drivers/regulator/regulator_core.c
new file mode 100644
index 0000000000..67da7d2920
--- /dev/null
+++ b/drivers/regulator/regulator_core.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/regulator.h>
+
+#define MAX_PROPERTY_LEN 64
+
+static struct rdev rdev_array[PLAT_NB_RDEVS];
+
+#pragma weak plat_get_lp_mode_name
+const char *plat_get_lp_mode_name(int mode)
+{
+ return NULL;
+}
+
+#define for_each_rdev(rdev) \
+ for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++)
+
+#define for_each_registered_rdev(rdev) \
+ for (rdev = rdev_array; \
+ (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++)
+
+#if defined(IMAGE_BL32)
+static void lock_driver(const struct rdev *rdev)
+{
+ if (rdev->desc->ops->lock != NULL) {
+ rdev->desc->ops->lock(rdev->desc);
+ }
+}
+
+static void unlock_driver(const struct rdev *rdev)
+{
+ if (rdev->desc->ops->unlock != NULL) {
+ rdev->desc->ops->unlock(rdev->desc);
+ }
+}
+#else
+#define lock_driver(desc) {}
+#define unlock_driver(desc) {}
+#endif
+
+static struct rdev *regulator_get_by_phandle(int32_t phandle)
+{
+ struct rdev *rdev;
+
+ for_each_registered_rdev(rdev) {
+ if (rdev->phandle == phandle) {
+ return rdev;
+ }
+ }
+
+ WARN("%s: phandle %d not found\n", __func__, phandle);
+ return NULL;
+}
+
+/*
+ * Get a regulator from its node name
+ *
+ * @fdt - pointer to device tree memory
+ * @node_name - name of the node "ldo1"
+ * Return pointer to rdev if succeed, NULL else.
+ */
+struct rdev *regulator_get_by_name(const char *node_name)
+{
+ struct rdev *rdev;
+
+ assert(node_name != NULL);
+ VERBOSE("get %s\n", node_name);
+
+ for_each_registered_rdev(rdev) {
+ if (strcmp(rdev->desc->node_name, node_name) == 0) {
+ return rdev;
+ }
+ }
+
+ WARN("%s: %s not found\n", __func__, node_name);
+ return NULL;
+}
+
+#if defined(IMAGE_BL32)
+/*
+ * Get a regulator from its regulator name property value
+ *
+ * @reg_name - target value of regulator-name property
+ * Return pointer to rdev if succeed, NULL else.
+ */
+struct rdev *regulator_get_by_regulator_name(const char *reg_name)
+{
+ struct rdev *rdev;
+
+ assert(reg_name != NULL);
+ VERBOSE("get %s\n", reg_name);
+
+ for_each_registered_rdev(rdev) {
+ if ((rdev->reg_name != NULL) && (strcmp(rdev->reg_name, reg_name) == 0)) {
+ return rdev;
+ }
+ }
+
+ WARN("%s: %s not found\n", __func__, reg_name);
+ return NULL;
+}
+#endif
+
+static int32_t get_supply_phandle(const void *fdt, int node, const char *name)
+{
+ const fdt32_t *cuint;
+ int len __unused;
+ int supply_phandle = -FDT_ERR_NOTFOUND;
+ char prop_name[MAX_PROPERTY_LEN];
+
+ len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name);
+ assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1));
+
+ cuint = fdt_getprop(fdt, node, prop_name, NULL);
+ if (cuint != NULL) {
+ supply_phandle = fdt32_to_cpu(*cuint);
+ VERBOSE("%s: supplied by %d\n", name, supply_phandle);
+ }
+
+ return supply_phandle;
+}
+
+/*
+ * Get a regulator from a supply name
+ *
+ * @fdt - pointer to device tree memory
+ * @node - offset of the node that contains the supply description
+ * @name - name of the supply "vdd" for "vdd-supply'
+ * Return pointer to rdev if succeed, NULL else.
+ */
+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name)
+{
+ const int p = get_supply_phandle(fdt, node, name);
+
+ if (p < 0) {
+ return NULL;
+ }
+
+ return regulator_get_by_phandle(p);
+}
+
+static int __regulator_set_state(struct rdev *rdev, bool state)
+{
+ if (rdev->desc->ops->set_state == NULL) {
+ return -ENODEV;
+ }
+
+ return rdev->desc->ops->set_state(rdev->desc, state);
+}
+
+#if defined(IMAGE_BL32)
+/*
+ * Enable regulator supply
+ * Enable regulator if use_count == 0
+ * Apply ramp delay
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+static int __regulator_enable(struct rdev *rdev)
+{
+ VERBOSE("%s: en\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->set_state == NULL) {
+ return -ENODEV;
+ }
+
+ if (rdev->supply_dev != NULL)
+ regulator_enable(rdev->supply_dev);
+
+ lock_driver(rdev);
+
+ if (rdev->use_count == 0) {
+ int ret;
+
+ ret = __regulator_set_state(rdev, STATE_ENABLE);
+ if (ret != 0) {
+ ERROR("regul %s set state failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ unlock_driver(rdev);
+ return ret;
+ }
+
+ udelay(rdev->enable_ramp_delay);
+ }
+
+ rdev->use_count++;
+
+ assert(rdev->use_count != UINT8_MAX);
+
+ VERBOSE("%s: en count:%u\n", rdev->desc->node_name, rdev->use_count);
+
+ unlock_driver(rdev);
+
+ return 0;
+}
+
+/*
+ * Enable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_enable(struct rdev *rdev)
+{
+ assert(rdev != NULL);
+
+ if (rdev->flags & REGUL_ALWAYS_ON) {
+ return 0;
+ }
+
+ return __regulator_enable(rdev);
+}
+
+/*
+ * Disable regulator if use_count fall to zero
+ * Warn if count is < 0 because too many disable were requested
+ * Disable regulator supply
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+static int __regulator_disable(struct rdev *rdev)
+{
+ VERBOSE("%s: dis\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->set_state == NULL) {
+ return -ENODEV;
+ }
+
+ lock_driver(rdev);
+
+ if (rdev->use_count == 1) {
+ int ret;
+
+ ret = __regulator_set_state(rdev, STATE_DISABLE);
+ if (ret != 0) {
+ ERROR("regul %s set state failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ unlock_driver(rdev);
+ return ret;
+ }
+ }
+
+ if (rdev->use_count == 0) {
+ WARN("regulator %s unbalanced disable\n", rdev->desc->node_name);
+ } else {
+ rdev->use_count--;
+ }
+
+ VERBOSE("%s: dis count:%u\n", rdev->desc->node_name, rdev->use_count);
+
+ unlock_driver(rdev);
+
+ if (rdev->supply_dev != NULL) {
+ regulator_disable(rdev->supply_dev);
+ }
+
+ return 0;
+}
+
+/*
+ * Disable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_disable(struct rdev *rdev)
+{
+ assert(rdev != NULL);
+
+ if (rdev->flags & REGUL_ALWAYS_ON) {
+ return 0;
+ }
+
+ return __regulator_disable(rdev);
+}
+#else
+/*
+ * Enable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_enable(struct rdev *rdev)
+{
+ int ret;
+
+ assert(rdev != NULL);
+
+ ret = __regulator_set_state(rdev, STATE_ENABLE);
+
+ udelay(rdev->enable_ramp_delay);
+
+ return ret;
+}
+
+/*
+ * Disable regulator
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_disable(struct rdev *rdev)
+{
+ int ret;
+
+ assert(rdev != NULL);
+
+ ret = __regulator_set_state(rdev, STATE_DISABLE);
+
+ udelay(rdev->enable_ramp_delay);
+
+ return ret;
+}
+#endif
+
+/*
+ * Regulator enabled query
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if disabled, 1 if enabled, <0 else.
+ */
+int regulator_is_enabled(const struct rdev *rdev)
+{
+ int ret = 0;
+
+ assert(rdev != NULL);
+
+ VERBOSE("%s: is en\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->get_state == NULL) {
+ return -ENODEV;
+ }
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->get_state(rdev->desc);
+ if (ret < 0) {
+ ERROR("regul %s get state failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ }
+
+ unlock_driver(rdev);
+
+ return ret;
+}
+
+/*
+ * Set regulator voltage
+ *
+ * @rdev - pointer to rdev struct
+ * @mvolt - Target voltage level in millivolt
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt)
+{
+ int ret = 0;
+
+ assert(rdev != NULL);
+
+ VERBOSE("%s: set mvolt\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->set_voltage == NULL) {
+ return -ENODEV;
+ }
+
+ if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) {
+ return -EPERM;
+ }
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt);
+ if (ret < 0) {
+ ERROR("regul %s set volt failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ }
+
+ unlock_driver(rdev);
+
+ return ret;
+}
+
+/*
+ * Set regulator min voltage
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_min_voltage(struct rdev *rdev)
+{
+ return regulator_set_voltage(rdev, rdev->min_mv);
+}
+
+/*
+ * Get regulator voltage
+ *
+ * @rdev - pointer to rdev struct
+ * Return milli volts if succeed, <0 else.
+ */
+int regulator_get_voltage(const struct rdev *rdev)
+{
+ int ret = 0;
+
+ assert(rdev != NULL);
+
+ VERBOSE("%s: get volt\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->get_voltage == NULL) {
+ return rdev->min_mv;
+ }
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->get_voltage(rdev->desc);
+ if (ret < 0) {
+ ERROR("regul %s get voltage failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ }
+
+ unlock_driver(rdev);
+
+ return ret;
+}
+
+/*
+ * List regulator voltages
+ *
+ * @rdev - pointer to rdev struct
+ * @levels - out: array of supported millitvolt levels from min to max value
+ * @count - out: number of possible millivolt values
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count)
+{
+ int ret;
+ size_t n;
+
+ assert(rdev != NULL);
+ assert(levels != NULL);
+ assert(count != NULL);
+
+ VERBOSE("%s: list volt\n", rdev->desc->node_name);
+
+ if (rdev->desc->ops->list_voltages == NULL) {
+ return -ENODEV;
+ }
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count);
+
+ unlock_driver(rdev);
+
+ if (ret < 0) {
+ ERROR("regul %s list_voltages failed: err: %d\n",
+ rdev->desc->node_name, ret);
+ return ret;
+ }
+
+ /*
+ * Reduce the possible values depending on min and max from device-tree
+ */
+ n = *count;
+ while (((*levels)[n - 1U] > rdev->max_mv) && (n > 1U)) {
+ n--;
+ }
+
+ /* Verify that max val is a valid value */
+ if (rdev->max_mv != (*levels)[n - 1]) {
+ ERROR("regul %s: max value %u is invalid\n",
+ rdev->desc->node_name, rdev->max_mv);
+ return -EINVAL;
+ }
+
+ while (((*levels[0U]) < rdev->min_mv) && (n > 1U)) {
+ (*levels)++;
+ n--;
+ }
+
+ /* Verify that min is not too high */
+ if (n == 0U) {
+ ERROR("regul %s set min voltage is too high\n",
+ rdev->desc->node_name);
+ return -EINVAL;
+ }
+
+ /* Verify that min val is a valid vlue */
+ if (rdev->min_mv != (*levels)[0U]) {
+ ERROR("regul %s: min value %u is invalid\n",
+ rdev->desc->node_name, rdev->min_mv);
+ return -EINVAL;
+ }
+
+ *count = n;
+
+ VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv);
+
+ return 0;
+}
+
+/*
+ * Get regulator voltages range
+ *
+ * @rdev - pointer to rdev struct
+ * @min_mv - out: min possible millivolt value
+ * @max_mv - out: max possible millivolt value
+ * Return 0 if succeed, non 0 else.
+ */
+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv)
+{
+ assert(rdev != NULL);
+
+ if (min_mv != NULL) {
+ *min_mv = rdev->min_mv;
+ }
+ if (max_mv != NULL) {
+ *max_mv = rdev->max_mv;
+ }
+}
+
+/*
+ * Set regulator flag
+ *
+ * @rdev - pointer to rdev struct
+ * @flag - flag value to set (eg: REGUL_OCP)
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_set_flag(struct rdev *rdev, uint16_t flag)
+{
+ int ret;
+
+ /* check that only one bit is set on flag */
+ if (__builtin_popcount(flag) != 1) {
+ return -EINVAL;
+ }
+
+ /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */
+ if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) {
+ rdev->flags |= flag;
+ return 0;
+ }
+
+ if (rdev->desc->ops->set_flag == NULL) {
+ ERROR("%s can not set any flag\n", rdev->desc->node_name);
+ return -ENODEV;
+ }
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->set_flag(rdev->desc, flag);
+
+ unlock_driver(rdev);
+
+ if (ret != 0) {
+ ERROR("%s: could not set flag %d ret=%d\n",
+ rdev->desc->node_name, flag, ret);
+ return ret;
+ }
+
+ rdev->flags |= flag;
+
+ return 0;
+}
+
+#if defined(IMAGE_BL32)
+
+struct regul_property {
+ char *name;
+ uint16_t flag;
+};
+
+static struct regul_property flag_prop[] = {
+ {
+ .name = "regulator-always-on",
+ .flag = REGUL_ALWAYS_ON,
+ },
+ {
+ .name = "regulator-boot-on",
+ .flag = REGUL_BOOT_ON,
+ },
+ {
+ .name = "regulator-active-discharge",
+ .flag = REGUL_ACTIVE_DISCHARGE,
+ },
+ {
+ .name = "regulator-over-current-protection",
+ .flag = REGUL_OCP,
+ },
+ {
+ .name = "regulator-pull-down",
+ .flag = REGUL_PULL_DOWN,
+ },
+ {
+ .name = "st,mask-reset",
+ .flag = REGUL_MASK_RESET,
+ },
+ {
+ .name = "st,regulator-sink-source",
+ .flag = REGUL_SINK_SOURCE,
+ },
+ {
+ .name = "st,regulator-bypass",
+ .flag = REGUL_ENABLE_BYPASS,
+ },
+};
+
+static int parse_properties(const void *fdt, struct rdev *rdev, int node)
+{
+ const fdt32_t *cuint;
+ int ret = 0;
+ struct regul_property *prop;
+
+ for (prop = flag_prop; prop < (flag_prop + ARRAY_SIZE(flag_prop)); prop++) {
+ if (fdt_getprop(fdt, node, prop->name, NULL) != NULL) {
+ VERBOSE("%s: prop 0x%x\n", rdev->desc->node_name, prop->flag);
+ ret = regulator_set_flag(rdev, prop->flag);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-enable-ramp-delay", NULL);
+ if (cuint != NULL) {
+ rdev->enable_ramp_delay = (uint32_t)(fdt32_to_cpu(*cuint));
+ VERBOSE("%s: enable_ramp_delay=%u\n", rdev->desc->node_name,
+ rdev->enable_ramp_delay);
+ }
+
+ rdev->reg_name = fdt_getprop(fdt, node, "regulator-name", NULL);
+
+ return 0;
+}
+
+static void parse_supply(const void *fdt, struct rdev *rdev, int node)
+{
+ const char *name = rdev->desc->supply_name;
+
+ if (name == NULL) {
+ name = rdev->desc->node_name;
+ }
+
+ rdev->supply_phandle = get_supply_phandle(fdt, node, name);
+ if (rdev->supply_phandle < 0) {
+ node = fdt_parent_offset(fdt, node);
+ rdev->supply_phandle = get_supply_phandle(fdt, node, name);
+ }
+}
+
+static void parse_low_power_mode(const void *fdt, struct rdev *rdev, int node, int mode)
+{
+ const fdt32_t *cuint;
+
+ rdev->lp_state[mode] = 0;
+
+ if (fdt_getprop(fdt, node, "regulator-off-in-suspend", NULL) != NULL) {
+ VERBOSE("%s: mode:%d OFF\n", rdev->desc->node_name, mode);
+ rdev->lp_state[mode] |= LP_STATE_OFF;
+ } else if (fdt_getprop(fdt, node, "regulator-on-in-suspend", NULL) != NULL) {
+ VERBOSE("%s: mode:%d ON\n", rdev->desc->node_name, mode);
+ rdev->lp_state[mode] |= LP_STATE_ON;
+ } else {
+ rdev->lp_state[mode] |= LP_STATE_UNCHANGED;
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-suspend-microvolt", NULL);
+ if (cuint != NULL) {
+ uint16_t mv;
+
+ mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+ VERBOSE("%s: mode:%d suspend mv=%u\n", rdev->desc->node_name,
+ mode, mv);
+
+ rdev->lp_state[mode] |= LP_STATE_SET_VOLT;
+ rdev->lp_mv[mode] = mv;
+ }
+}
+
+static void parse_low_power_modes(const void *fdt, struct rdev *rdev, int node)
+{
+ int i;
+
+ for (i = 0; i < PLAT_NB_SUSPEND_MODES; i++) {
+ const char *lp_mode_name = plat_get_lp_mode_name(i);
+ int n;
+
+ if (lp_mode_name == NULL) {
+ continue;
+ }
+
+ /* Get the configs from regulator_state_node subnode */
+ n = fdt_subnode_offset(fdt, node, lp_mode_name);
+ if (n >= 0) {
+ parse_low_power_mode(fdt, rdev, n, i);
+ }
+ }
+}
+#endif
+
+/*
+ * Parse the device-tree for a regulator
+ *
+ * Read min/max voltage from dt and check its validity
+ * Read the properties, and call the driver to set flags
+ * Read power supply phandle
+ * Read and store low power mode states
+ *
+ * @rdev - pointer to rdev struct
+ * @node - device-tree node offset of the regulator
+ * Return 0 if disabled, 1 if enabled, <0 else.
+ */
+static int parse_dt(struct rdev *rdev, int node)
+{
+ void *fdt;
+ const fdt32_t *cuint;
+ const uint16_t *levels;
+ size_t size;
+ int ret = 0;
+
+ VERBOSE("%s: parse dt\n", rdev->desc->node_name);
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ rdev->phandle = fdt_get_phandle(fdt, node);
+
+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
+ if (cuint != NULL) {
+ uint16_t min_mv;
+
+ min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+ VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv);
+ if (min_mv <= rdev->max_mv) {
+ rdev->min_mv = min_mv;
+ } else {
+ ERROR("%s: min_mv=%d is too high\n",
+ rdev->desc->node_name, (int)min_mv);
+ return -EINVAL;
+ }
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
+ if (cuint != NULL) {
+ uint16_t max_mv;
+
+ max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+ VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv);
+ if (max_mv >= rdev->min_mv) {
+ rdev->max_mv = max_mv;
+ } else {
+ ERROR("%s: max_mv=%d is too low\n",
+ rdev->desc->node_name, (int)max_mv);
+ return -EINVAL;
+ }
+ }
+
+ /* validate that min and max values can be used */
+ ret = regulator_list_voltages(rdev, &levels, &size);
+ if ((ret != 0) && (ret != -ENODEV)) {
+ return ret;
+ }
+
+#if defined(IMAGE_BL32)
+ ret = parse_properties(fdt, rdev, node);
+ if (ret != 0) {
+ return ret;
+ }
+
+ parse_supply(fdt, rdev, node);
+
+ parse_low_power_modes(fdt, rdev, node);
+#endif
+
+ return 0;
+}
+
+/*
+ * Register a regulator driver in regulator framework.
+ * Initialize voltage range from driver description
+ *
+ * @desc - pointer to the regulator description
+ * @node - device-tree node offset of the regulator
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_register(const struct regul_description *desc, int node)
+{
+ struct rdev *rdev;
+
+ assert(desc != NULL);
+
+ VERBOSE("register %s\n", desc->node_name);
+
+ for_each_rdev(rdev) {
+ if (rdev->desc == NULL) {
+ break;
+ }
+ }
+
+ if (rdev == rdev_array + PLAT_NB_RDEVS) {
+ WARN("out of memory\n");
+ return -ENOMEM;
+ }
+
+ rdev->desc = desc;
+ rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay;
+
+ if (rdev->desc->ops->list_voltages != NULL) {
+ int ret = 0;
+ const uint16_t *levels;
+ size_t count;
+
+ lock_driver(rdev);
+
+ ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count);
+
+ unlock_driver(rdev);
+
+ if (ret < 0) {
+ ERROR("regul %s set state failed: err:%d\n",
+ rdev->desc->node_name, ret);
+ return ret;
+ }
+
+ rdev->min_mv = levels[0];
+ rdev->max_mv = levels[count - 1U];
+ } else {
+ rdev->max_mv = UINT16_MAX;
+ }
+
+ return parse_dt(rdev, node);
+}
+
+#if defined(IMAGE_BL32)
+/*
+ * Suspend a single regulator before low power entry
+ * Call regulator suspend call back,
+ * Enable the regulator if boot_on flag is set as regulator is needed during
+ * boot/resume from suspend sequences.
+ *
+ * @rdev - pointer to rdev struct
+ * @mode - low power mode index
+ * Return 0 if succeed, non 0 else.
+ */
+static int suspend_regulator(struct rdev *rdev, int mode)
+{
+ int ret = 0;
+
+ if (rdev->desc->ops->suspend != NULL) {
+ lock_driver(rdev);
+ ret = rdev->desc->ops->suspend(rdev->desc,
+ rdev->lp_state[mode],
+ rdev->lp_mv[mode]);
+ unlock_driver(rdev);
+ if (ret != 0) {
+ ERROR("%s failed to suspend: %d\n", rdev->desc->node_name, ret);
+ return ret;
+ }
+ }
+
+ if (rdev->flags & REGUL_BOOT_ON) {
+ ret = regulator_enable(rdev);
+ }
+
+ return ret;
+}
+
+/*
+ * Resume a single regulator after low power
+ *
+ * @rdev - pointer to rdev struct
+ * Return 0 if succeed, non 0 else.
+ */
+static int resume_regulator(struct rdev *rdev)
+{
+ int ret = 0;
+
+ if (rdev->flags & REGUL_BOOT_ON) {
+ /* Revert to the state it was before suspend */
+ ret = regulator_disable(rdev);
+ if (ret != 0) {
+ ERROR("%s failed to resume: %d\n", rdev->desc->node_name, ret);
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Suspend regulators before entering low power
+ *
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_core_suspend(int mode)
+{
+ struct rdev *rdev;
+
+ VERBOSE("Regulator core suspend\n");
+
+ if (mode >= PLAT_NB_SUSPEND_MODES) {
+ return -EINVAL;
+ }
+
+ /* Suspend each regulator */
+ for_each_registered_rdev(rdev) {
+ if (suspend_regulator(rdev, mode) != 0) {
+ panic();
+ }
+ }
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ regulator_core_dump();
+#endif
+
+ return 0;
+}
+
+/*
+ * Resume regulators from low power
+ *
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_core_resume(void)
+{
+ struct rdev *rdev;
+
+ VERBOSE("Regulator core resume\n");
+
+ /* Resume each regulator */
+ for_each_registered_rdev(rdev) {
+ if (resume_regulator(rdev) != 0) {
+ panic();
+ }
+ }
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ regulator_core_dump();
+#endif
+
+ return 0;
+}
+
+/*
+ * save regulators data
+ *
+ * @backup_area - pointer to save data
+ * @backup_size - size of the backup area
+ */
+void regulator_core_backup_context(void *backup_area, size_t backup_size)
+{
+ int8_t *data = (int8_t *)backup_area;
+ struct rdev *rdev;
+
+ assert(data != NULL);
+ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE);
+
+ for_each_rdev(rdev) {
+ *data = rdev->use_count;
+ data++;
+ }
+}
+
+/*
+ * restore regulators data
+ *
+ * @backup_area - pointer to retrieve saved data
+ * @backup_size - size of the backup area
+ */
+void regulator_core_restore_context(void *backup_area, size_t backup_size)
+{
+ int8_t *data = (int8_t *)backup_area;
+ struct rdev *rdev;
+
+ assert(data != NULL);
+ assert(backup_size == PLAT_BACKUP_REGULATOR_SIZE);
+
+ for_each_rdev(rdev) {
+ rdev->use_count = *data;
+ data++;
+ }
+}
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+static void sprint_name(char *dest, const char *src, int len)
+{
+ int l;
+
+ if (src == NULL) {
+ src = "";
+ }
+
+ l = strlen(src);
+ if (l > len) {
+ l = len;
+ }
+
+ memset(dest, ' ', len);
+ memcpy(dest, src, l);
+ dest[len] = 0;
+}
+
+/*
+ * Log regulators state
+ */
+void regulator_core_dump(void)
+{
+ struct rdev *rdev;
+
+ VERBOSE("Dump Regulators\n");
+
+ INFO("reg name use\ten\tmV\tmin\tmax\tflags\tsupply\n");
+
+ for_each_registered_rdev(rdev) {
+ uint16_t min_mv, max_mv;
+ char reg[9] = "";
+ char name[9];
+ const char *supply = "";
+
+ sprint_name(name, rdev->desc->node_name, 8);
+ sprint_name(reg, rdev->reg_name, 8);
+
+ regulator_get_range(rdev, &min_mv, &max_mv);
+ if (rdev->supply_dev != NULL)
+ supply = rdev->supply_dev->desc->node_name;
+
+ INFO("%s %s %d\t%d\t%d\t%d\t%d\t0x%x\t%s\n",
+ reg, name,
+ rdev->use_count,
+ regulator_is_enabled(rdev),
+ regulator_get_voltage(rdev), min_mv, max_mv,
+ rdev->flags, supply);
+ }
+}
+#endif
+
+/*
+ * Connect each regulator to its supply
+ * Apply min voltage if the voltage is outside the authorized range
+ * Enable always-on regulators
+ *
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_core_config(void)
+{
+ int ret;
+ struct rdev *rdev;
+
+ VERBOSE("Regul Core config\n");
+
+ for_each_registered_rdev(rdev) {
+ if (rdev->supply_phandle >= 0) {
+ struct rdev *s;
+
+ VERBOSE("%s: connect supply\n", rdev->desc->node_name);
+
+ s = regulator_get_by_phandle(rdev->supply_phandle);
+ if (s == NULL) {
+ return -EINVAL;
+ }
+
+ rdev->supply_dev = s;
+ }
+ }
+
+ for_each_registered_rdev(rdev) {
+ uint16_t mv, min_mv, max_mv;
+
+ regulator_get_range(rdev, &min_mv, &max_mv);
+
+ ret = regulator_get_voltage(rdev);
+ if (ret >= 0) {
+ mv = ret;
+ if ((mv < min_mv) || (mv > max_mv)) {
+ ret = regulator_set_voltage(rdev, min_mv);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ } else {
+ return ret;
+ }
+
+ /*
+ * Enable always-on regulator and increment its use_count so that
+ * the regulator is not being disabled during clean-up sequence.
+ */
+ if (rdev->flags & REGUL_ALWAYS_ON) {
+ ret = __regulator_enable(rdev);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Sync hardware regulator state with use refcount
+ *
+ * Return 0 if succeed, non 0 else.
+ */
+int regulator_core_cleanup(void)
+{
+ struct rdev *rdev;
+
+ VERBOSE("Regul Core cleanup\n");
+
+ for_each_registered_rdev(rdev) {
+ if (!(rdev->flags & REGUL_BOOT_ON)) {
+ if ((rdev->use_count == 0) && (regulator_is_enabled(rdev) == 1)) {
+ VERBOSE("disable %s during cleanup\n", rdev->desc->node_name);
+ /* force disable to synchronize the framework */
+ __regulator_set_state(rdev, STATE_DISABLE);
+ }
+ }
+ }
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ regulator_core_dump();
+#endif
+
+ return 0;
+}
+
+#endif
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index d074a1568c..73c9b147b7 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -71,6 +71,7 @@ enum stm32mp1_parent_id {
_HSI_KER = NB_OSC,
_HSE_KER,
_HSE_KER_DIV2,
+ _HSE_RTC,
_CSI_KER,
_PLL1_P,
_PLL1_Q,
@@ -140,6 +141,7 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = {
[_HSI_KER] = CK_HSI,
[_HSE_KER] = CK_HSE,
[_HSE_KER_DIV2] = CK_HSE_DIV2,
+ [_HSE_RTC] = _UNKNOWN_ID,
[_CSI_KER] = CK_CSI,
[_PLL1_P] = PLL1_P,
[_PLL1_Q] = PLL1_Q,
@@ -384,21 +386,17 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
#if defined(IMAGE_BL32)
_CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
#endif
-#if defined(IMAGE_BL2)
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
-#endif
#if defined(IMAGE_BL32)
_CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
#endif
-#if defined(IMAGE_BL2)
_CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
-#endif
_CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
@@ -543,7 +541,7 @@ static const uint8_t per_parents[] = {
};
static const uint8_t rtc_parents[] = {
- _UNKNOWN_ID, _LSE, _LSI, _HSE
+ _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
};
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
@@ -639,6 +637,7 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
[_HSI_KER] = "HSI_KER",
[_HSE_KER] = "HSE_KER",
[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+ [_HSE_RTC] = "HSE_RTC",
[_CSI_KER] = "CSI_KER",
[_PLL1_P] = "PLL1_P",
[_PLL1_Q] = "PLL1_Q",
@@ -696,6 +695,7 @@ 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 uint32_t save_current_opp_khz;
static uint32_t pll3cr;
static uint32_t pll4cr;
static uint32_t mssckselr;
@@ -1063,6 +1063,10 @@ static unsigned long get_clock_rate(int p)
case _HSE_KER_DIV2:
clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
break;
+ case _HSE_RTC:
+ clock = stm32mp1_clk_get_fixed(_HSE);
+ clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
+ break;
case _LSI:
clock = stm32mp1_clk_get_fixed(_LSI);
break;
@@ -2951,6 +2955,7 @@ static void secure_parent_clocks(unsigned long parent_id)
case _HSE:
case _HSE_KER:
case _HSE_KER_DIV2:
+ case _HSE_RTC:
case _LSE:
break;
@@ -3238,6 +3243,13 @@ void save_clock_pm_context(void)
stm32mp1_pm_save_clock_cfg(offset,
(uint8_t *)gate_refcounts,
sizeof(gate_refcounts));
+ offset += sizeof(gate_refcounts);
+
+ save_current_opp_khz = current_opp_khz;
+
+ stm32mp1_pm_save_clock_cfg(offset,
+ (uint8_t *)&save_current_opp_khz,
+ sizeof(save_current_opp_khz));
}
void restore_clock_pm_context(void)
@@ -3267,6 +3279,13 @@ void restore_clock_pm_context(void)
stm32mp1_pm_restore_clock_cfg(offset,
(uint8_t *)gate_refcounts,
sizeof(gate_refcounts));
+ offset += sizeof(gate_refcounts);
+
+ stm32mp1_pm_restore_clock_cfg(offset,
+ (uint8_t *)&save_current_opp_khz,
+ sizeof(save_current_opp_khz));
+
+ stm32mp1_set_opp_khz(save_current_opp_khz);
}
void stm32mp1_clock_suspend(void)
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
index 7e8041743e..fb0c7d782f 100644
--- a/drivers/st/ddr/stm32mp1_ddr.c
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -1017,9 +1017,14 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
/*
* 10. configure PUBL PIR register to specify which training
* step to run
- * Warning : RVTRN is not supported by this PUBL
+ * RVTRN is executed only on LPDDR2/LPDDR3
*/
- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
+ pir = DDRPHYC_PIR_QSTRN;
+ if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) == 0U) {
+ pir |= DDRPHYC_PIR_RVTRN;
+ }
+
+ stm32mp1_ddrphy_init(priv->phy, pir);
/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training
* sequence
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 3918eb7be5..d7ee35fec9 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -14,14 +14,12 @@
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <drivers/clk.h>
+#include <drivers/st/stm32mp_ddr_test.h>
#include <drivers/st/stm32mp1_ddr.h>
#include <drivers/st/stm32mp1_ddr_helpers.h>
#include <drivers/st/stm32mp1_ram.h>
#include <lib/mmio.h>
-#define DDR_PATTERN 0xAAAAAAAAU
-#define DDR_ANTIPATTERN 0x55555555U
-
static struct ddr_info ddr_priv_data;
static bool ddr_self_refresh;
@@ -52,139 +50,6 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
return 0;
}
-/*******************************************************************************
- * This function tests a simple read/write access to the DDR.
- * Note that the previous content is restored after test.
- * Returns 0 if success, and address value else.
- ******************************************************************************/
-static uint32_t ddr_test_rw_access(void)
-{
- uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE);
-
- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
-
- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
- return (uint32_t)STM32MP_DDR_BASE;
- }
-
- mmio_write_32(STM32MP_DDR_BASE, saved_value);
-
- return 0;
-}
-
-/*******************************************************************************
- * This function tests the DDR data bus wiring.
- * This is inspired from the Data Bus Test algorithm written by Michael Barr
- * in "Programming Embedded Systems in C and C++" book.
- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
- * File: memtest.c - This source code belongs to Public Domain.
- * Returns 0 if success, and address value else.
- ******************************************************************************/
-static uint32_t ddr_test_data_bus(void)
-{
- uint32_t pattern;
-
- for (pattern = 1U; pattern != 0U; pattern <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE, pattern);
-
- if (mmio_read_32(STM32MP_DDR_BASE) != pattern) {
- return (uint32_t)STM32MP_DDR_BASE;
- }
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function tests the DDR address bus wiring.
- * This is inspired from the Data Bus Test algorithm written by Michael Barr
- * in "Programming Embedded Systems in C and C++" book.
- * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
- * File: memtest.c - This source code belongs to Public Domain.
- * Returns 0 if success, and address value else.
- ******************************************************************************/
-static uint32_t ddr_test_addr_bus(void)
-{
- uint64_t addressmask = (ddr_priv_data.info.size - 1U);
- uint64_t offset;
- uint64_t testoffset = 0;
-
- /* Write the default pattern at each of the power-of-two offsets. */
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset,
- DDR_PATTERN);
- }
-
- /* Check for address bits stuck high. */
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_ANTIPATTERN);
-
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) !=
- DDR_PATTERN) {
- return (uint32_t)(STM32MP_DDR_BASE + offset);
- }
- }
-
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
-
- /* Check for address bits stuck low or shorted. */
- for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
- testoffset <<= 1) {
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_ANTIPATTERN);
-
- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
- return STM32MP_DDR_BASE;
- }
-
- for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
- offset <<= 1) {
- if ((mmio_read_32(STM32MP_DDR_BASE +
- (uint32_t)offset) != DDR_PATTERN) &&
- (offset != testoffset)) {
- return (uint32_t)(STM32MP_DDR_BASE + offset);
- }
- }
-
- mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
- DDR_PATTERN);
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function checks the DDR size. It has to be run with Data Cache off.
- * This test is run before data have been put in DDR, and is only done for
- * cold boot. The DDR data can then be overwritten, and it is not useful to
- * restore its content.
- * Returns DDR computed size.
- ******************************************************************************/
-static uint32_t ddr_check_size(void)
-{
- uint32_t offset = sizeof(uint32_t);
-
- mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
-
- while (offset < STM32MP_DDR_MAX_SIZE) {
- mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
- dsb();
-
- if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
- break;
- }
-
- offset <<= 1;
- }
-
- INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U));
-
- return offset;
-}
-
static int stm32mp1_ddr_setup(void)
{
struct ddr_info *priv = &ddr_priv_data;
@@ -249,6 +114,17 @@ static int stm32mp1_ddr_setup(void)
INFO("RAM: %s\n", config.info.name);
for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
+ /* Check present field to avoid warning for optional properties */
+ if (param[idx].present != NULL) {
+ if (fdt_getprop(fdt, node, param[idx].name, NULL) == NULL) {
+ *(param[idx].present) = false;
+ VERBOSE("%s: %s[0x%x] = absent\n", __func__,
+ param[idx].name, param[idx].size);
+ continue;
+ }
+ /* Save presence of optional parameters */
+ *(param[idx].present) = true;
+ }
ret = fdt_read_uint32_array(fdt, node, param[idx].name,
param[idx].size,
(void *)((uintptr_t)&config +
@@ -256,20 +132,11 @@ static int stm32mp1_ddr_setup(void)
VERBOSE("%s: %s[0x%x] = %d\n", __func__,
param[idx].name, param[idx].size, ret);
- if ((ret != 0) &&
- ((ret != -FDT_ERR_NOTFOUND) ||
- (param[idx].present == NULL))) {
+ if (ret != 0) {
ERROR("%s: Cannot read %s, error=%d\n",
__func__, param[idx].name, ret);
return -EINVAL;
}
- if (param[idx].present != NULL) {
- /* save presence of optional parameters */
- *(param[idx].present) = true;
- if (ret == -FDT_ERR_NOTFOUND) {
- *(param[idx].present) = false;
- }
- }
}
config.self_refresh = false;
@@ -297,7 +164,7 @@ static int stm32mp1_ddr_setup(void)
}
if (config.self_refresh) {
- uret = ddr_test_rw_access();
+ uret = stm32mp_ddr_test_rw_access();
if (uret != 0U) {
ERROR("DDR rw test: Can't access memory @ 0x%x\n",
uret);
@@ -307,21 +174,21 @@ static int stm32mp1_ddr_setup(void)
/* Restore area overwritten by training */
stm32_restore_ddr_training_area();
} else {
- uret = ddr_test_data_bus();
+ uret = stm32mp_ddr_test_data_bus();
if (uret != 0U) {
ERROR("DDR data bus test: can't access memory @ 0x%x\n",
uret);
panic();
}
- uret = ddr_test_addr_bus();
+ uret = stm32mp_ddr_test_addr_bus(config.info.size);
if (uret != 0U) {
ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
uret);
panic();
}
- uret = ddr_check_size();
+ uret = stm32mp_ddr_check_size();
if (uret < config.info.size) {
ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
uret, config.info.size);
diff --git a/drivers/st/ddr/stm32mp_ddr_test.c b/drivers/st/ddr/stm32mp_ddr_test.c
new file mode 100644
index 0000000000..45920b7f80
--- /dev/null
+++ b/drivers/st/ddr/stm32mp_ddr_test.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/st/stm32mp_ddr_test.h>
+
+#include <lib/mmio.h>
+
+#define DDR_PATTERN 0xAAAAAAAAU
+#define DDR_ANTIPATTERN 0x55555555U
+
+/*******************************************************************************
+ * This function tests a simple read/write access to the DDR.
+ * Note that the previous content is restored after test.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_rw_access(void)
+{
+ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE);
+
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return (uint32_t)STM32MP_DDR_BASE;
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE, saved_value);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function tests the DDR data bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_data_bus(void)
+{
+ uint32_t pattern;
+
+ for (pattern = 1U; pattern != 0U; pattern <<= 1) {
+ mmio_write_32(STM32MP_DDR_BASE, pattern);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) {
+ return (uint32_t)STM32MP_DDR_BASE;
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function tests the DDR address bus wiring.
+ * This is inspired from the Data Bus Test algorithm written by Michael Barr
+ * in "Programming Embedded Systems in C and C++" book.
+ * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/
+ * File: memtest.c - This source code belongs to Public Domain.
+ * size: size in bytes of the DDR memory device.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_test_addr_bus(uint64_t size)
+{
+ uint64_t addressmask = size - 1U;
+ uint64_t offset;
+ uint64_t testoffset = 0;
+
+ /* Write the default pattern at each of the power-of-two offsets. */
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1) {
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset,
+ DDR_PATTERN);
+ }
+
+ /* Check for address bits stuck high. */
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_ANTIPATTERN);
+
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1) {
+ if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) !=
+ DDR_PATTERN) {
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
+ }
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
+
+ /* Check for address bits stuck low or shorted. */
+ for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
+ testoffset <<= 1) {
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_ANTIPATTERN);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return STM32MP_DDR_BASE;
+ }
+
+ for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
+ offset <<= 1) {
+ if ((mmio_read_32(STM32MP_DDR_BASE +
+ (uint32_t)offset) != DDR_PATTERN) &&
+ (offset != testoffset)) {
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
+ }
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
+ DDR_PATTERN);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function checks the DDR size. It has to be run with Data Cache off.
+ * This test is run before data have been put in DDR, and is only done for
+ * cold boot. The DDR data can then be overwritten, and it is not useful to
+ * restore its content.
+ * Returns DDR computed size.
+ ******************************************************************************/
+uint32_t stm32mp_ddr_check_size(void)
+{
+ uint32_t offset = sizeof(uint32_t);
+
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
+
+ while (offset < STM32MP_DDR_MAX_SIZE) {
+ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
+ dsb();
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ break;
+ }
+
+ offset <<= 1;
+ }
+
+ INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U));
+
+ return offset;
+}
diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c
index 503e259876..e9ab6dafd8 100644
--- a/drivers/st/fmc/stm32_fmc2_nand.c
+++ b/drivers/st/fmc/stm32_fmc2_nand.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -201,9 +201,6 @@ static void stm32_fmc2_nand_setup_timing(void)
if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) {
tset_mem = NAND_TCS_MIN - twait;
}
- if ((twait < NAND_TALS_MIN) && (tset_mem < (NAND_TALS_MIN - twait))) {
- tset_mem = NAND_TALS_MIN - twait;
- }
if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) &&
(tset_mem < (NAND_TDS_MIN - (twait - thiz)))) {
tset_mem = NAND_TDS_MIN - (twait - thiz);
@@ -245,12 +242,6 @@ static void stm32_fmc2_nand_setup_timing(void)
if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) {
tset_att = NAND_TCS_MIN - twait;
}
- if ((twait < NAND_TCLS_MIN) && (tset_att < (NAND_TCLS_MIN - twait))) {
- tset_att = NAND_TCLS_MIN - twait;
- }
- if ((twait < NAND_TALS_MIN) && (tset_att < (NAND_TALS_MIN - twait))) {
- tset_att = NAND_TALS_MIN - twait;
- }
if ((thold_mem < NAND_TRHW_MIN) &&
(tset_att < (NAND_TRHW_MIN - thold_mem))) {
tset_att = NAND_TRHW_MIN - thold_mem;
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index 75707e63a1..5c54762ecc 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -284,3 +284,10 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
clk_disable(clock);
}
+
+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin)
+{
+ set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_SPEED_LOW,
+ GPIO_NO_PULL, GPIO_ALTERNATE_(0), DT_DISABLED);
+ set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank));
+}
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 8c203a4c03..c516bdb3d4 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -186,9 +186,8 @@ static void stm32_sdmmc2_init(void)
freq = MIN(sdmmc2_params.max_freq, freq);
}
- if (sdmmc2_params.vmmc_regu.id != -1) {
- stm32mp_regulator_register(&sdmmc2_params.vmmc_regu);
- stm32mp_regulator_disable(&sdmmc2_params.vmmc_regu);
+ if (sdmmc2_params.vmmc_regu != NULL) {
+ regulator_disable(sdmmc2_params.vmmc_regu);
}
mdelay(VCC_POWER_OFF_DELAY);
@@ -197,8 +196,8 @@ static void stm32_sdmmc2_init(void)
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);
+ if (sdmmc2_params.vmmc_regu != NULL) {
+ regulator_enable(sdmmc2_params.vmmc_regu);
}
mdelay(VCC_POWER_ON_DELAY);
@@ -758,10 +757,7 @@ 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);
- }
+ sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc");
return 0;
}
@@ -783,7 +779,7 @@ 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;
+ sdmmc2_params.vmmc_regu = NULL;
if (stm32_sdmmc2_dt_get_config() != 0) {
ERROR("%s: DT error\n", __func__);
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 4e505debdf..e8cadcda0a 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,30 +13,21 @@
#include <common/debug.h>
#include <drivers/delay_timer.h>
+#include <drivers/regulator.h>
#include <drivers/st/stm32_i2c.h>
#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
+#include <lib/spinlock.h>
#include <lib/utils_def.h>
-#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
-#define STPMIC1_LDO12356_OUTPUT_SHIFT 2
-#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7))
-#define STPMIC1_LDO3_DDR_SEL 31U
-
-#define STPMIC1_BUCK_OUTPUT_SHIFT 2
-#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT)
-
-#define REGULATOR_MODE_STANDBY 8U
-
-#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
-
-#define CMD_GET_MIN_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;
+#if defined(IMAGE_BL32)
+static struct spinlock lock;
+#endif
+
+static int register_pmic(void);
static int dt_get_pmic_node(void *fdt)
{
@@ -84,235 +75,6 @@ static bool dt_pmic_is_secure(void)
(i2c_handle.dt_status == DT_SECURE);
}
-static int dt_pmic_get_regulator_voltage(void *fdt, int node,
- uint16_t *min_mv, uint16_t *max_mv)
-{
- const fdt32_t *cuint;
-
- cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- if (min_mv != NULL) {
- *min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
- }
-
- cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- if (max_mv != NULL) {
- *max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
- }
-
- return 0;
-}
-
-static int pmic_config_boot_on(void *fdt, int node, const char *regu_name)
-{
- uint16_t voltage = 0U;
- uint16_t voltage_min;
- uint16_t voltage_max;
- int status;
- int pmic_voltage;
-
- if ((fdt_getprop(fdt, node, "regulator-boot-on", NULL) == NULL) &&
- (fdt_getprop(fdt, node, "regulator-always-on", NULL) == NULL)) {
- return 0;
- }
-
- if (fdt_getprop(fdt, node, "regulator-pull-down", NULL) != NULL) {
-
- status = stpmic1_regulator_pull_down_set(regu_name);
- if (status < 0) {
- return status;
- }
- }
-
- if (fdt_getprop(fdt, node, "st,mask-reset", NULL) != NULL) {
-
- status = stpmic1_regulator_mask_reset_set(regu_name);
- if (status < 0) {
- return status;
- }
- }
-
- if (dt_pmic_get_regulator_voltage(fdt, node, &voltage_min,
- &voltage_max) < 0) {
- return 0;
- }
-
- pmic_voltage = stpmic1_regulator_voltage_get(regu_name);
- if (pmic_voltage < 0) {
- return pmic_voltage;
- }
-
- if ((uint16_t)pmic_voltage < voltage_min) {
- voltage = voltage_min;
- }
-
- if ((uint16_t)pmic_voltage > voltage_max) {
- voltage = voltage_max;
- }
-
- /* Only re-program voltage if not in the range provided in DT. */
- if (voltage != 0U) {
- status = stpmic1_regulator_voltage_set(regu_name, voltage);
- if (status < 0) {
- return status;
- }
- }
-
- if (!stpmic1_is_regulator_enabled(regu_name)) {
- status = stpmic1_regulator_enable(regu_name);
- if (status < 0) {
- return status;
- }
- }
-
- return 0;
-}
-
-#if defined(IMAGE_BL32)
-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;
- };
-
- /*
- * 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;
- }
-
- /* 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;
- }
- }
-
- 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;
- }
- }
-
- 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_lp_set_voltage(regu_name, voltage);
- if (status < 0) {
- return status;
- }
- }
-
- 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;
- }
- }
- }
-
- return 0;
-}
-#endif
-
-static int pmic_operate(uint8_t command, const char *node_name,
- uint16_t *voltage_mv)
-{
- int pmic_node, regulators_node, subnode;
- void *fdt;
- int ret = -EIO;
-
- if (fdt_get_address(&fdt) == 0) {
- return -ENOENT;
- }
-
- pmic_node = dt_get_pmic_node(fdt);
- if (pmic_node < 0) {
- return -ENOENT;
- }
-
- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
- if (regulators_node < 0) {
- return -ENOENT;
- }
-
- fdt_for_each_subnode(subnode, fdt, regulators_node) {
- const char *regu_name = fdt_get_name(fdt, subnode, NULL);
-
- switch (command) {
- case CMD_GET_MIN_VOLTAGE:
- assert(node_name != NULL);
- assert(voltage_mv != NULL);
-
- if (strcmp(regu_name, node_name) != 0) {
- continue;
- }
-
- ret = dt_pmic_get_regulator_voltage(fdt, subnode,
- voltage_mv, NULL);
- if (ret < 0) {
- return -ENXIO;
- }
-
- return ret;
-
- case CMD_CONFIG_BOOT_ON:
- ret = pmic_config_boot_on(fdt, subnode, regu_name);
- if (ret < 0) {
- return ret;
- }
- break;
-
-#if defined(IMAGE_BL32)
- case CMD_CONFIG_LP:
- assert(node_name != NULL);
-
- ret = pmic_config_lp(fdt, subnode, node_name,
- regu_name);
- if (ret < 0) {
- return ret;
- }
- break;
-#endif
-
- default:
- return -EINVAL;
- }
- }
-
- 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.
@@ -360,66 +122,6 @@ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
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);
-}
-
-int dt_pmic_find_supply(const char **supply_name, const char *regu_name)
-{
- int pmic_node, regulators_node, subnode;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- pmic_node = dt_get_pmic_node(fdt);
- if (pmic_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
- if (regulators_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- fdt_for_each_subnode(subnode, fdt, regulators_node) {
- const char *name;
-
- name = fdt_getprop(fdt, subnode, "regulator-name", NULL);
- if ((name != NULL) &&
- (strcmp(name, regu_name) == 0)) {
- *supply_name = fdt_get_name(fdt, subnode, NULL);
- return 0;
- }
- }
-
- return -FDT_ERR_NOTFOUND;
-}
-
-int pmic_set_regulator_min_voltage(const char *regu_name)
-{
- int rc = -ENOENT;
- const char *supply_name;
-
- if (dt_pmic_find_supply(&supply_name, regu_name) == 0) {
- uint16_t min_mv;
-
- rc = pmic_operate(CMD_GET_MIN_VOLTAGE, supply_name, &min_mv);
- if (rc == 0) {
- rc = stpmic1_regulator_voltage_set(supply_name, min_mv);
- }
- }
-
- return rc;
-}
-
bool initialize_pmic_i2c(void)
{
int ret;
@@ -483,62 +185,6 @@ static void register_pmic_shared_peripherals(void)
}
}
-static int pmic_regulator_enable(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_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()) {
@@ -547,13 +193,15 @@ void initialize_pmic(void)
}
register_pmic_shared_peripherals();
-}
-void configure_pmic(void)
-{
- if (pmic_configure_boot_on_regulators() < 0) {
+ if (register_pmic() < 0) {
panic();
- };
+ }
+
+ if (stpmic1_powerctrl_on() < 0) {
+ panic();
+ }
+
}
#if DEBUG
@@ -567,65 +215,61 @@ void print_pmic_info_and_debug(void)
}
INFO("PMIC version = 0x%02lx\n", pmic_version);
- stpmic1_dump_regulators();
+#if defined(IMAGE_BL32)
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ regulator_core_dump();
+#endif
+#endif
}
#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;
+ uint16_t buck3_min_mv;
+ struct rdev *buck2, *buck3, *ldo3, *vref;
- if (pmic_operate(CMD_GET_MIN_VOLTAGE, "buck2", &buck2_mv) != 0) {
- return -EPERM;
+ buck2 = regulator_get_by_name("buck2");
+ if (buck2 == NULL) {
+ return -ENOENT;
}
- switch (ddr_type) {
- case STM32MP_DDR3:
- /* Set LDO3 to sync mode */
- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
+ ldo3 = regulator_get_by_name("ldo3");
+ if (ldo3 == NULL) {
+ return -ENOENT;
+ }
- read_val &= ~STPMIC1_LDO3_MODE;
- read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
- read_val |= STPMIC1_LDO3_DDR_SEL <<
- STPMIC1_LDO12356_OUTPUT_SHIFT;
+ vref = regulator_get_by_name("vref_ddr");
+ if (vref == NULL) {
+ return -ENOENT;
+ }
- status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+ switch (ddr_type) {
+ case STM32MP_DDR3:
+ status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE);
if (status != 0) {
return status;
}
- status = stpmic1_regulator_voltage_set("buck2", buck2_mv);
+ status = regulator_set_min_voltage(buck2);
if (status != 0) {
return status;
}
- status = stpmic1_regulator_enable("buck2");
+ status = regulator_enable(buck2);
if (status != 0) {
return status;
}
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmic1_regulator_enable("vref_ddr");
+ status = regulator_enable(vref);
if (status != 0) {
return status;
}
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmic1_regulator_enable("ldo3");
+ status = regulator_enable(ldo3);
if (status != 0) {
return status;
}
-
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
break;
case STM32MP_LPDDR2:
@@ -635,70 +279,280 @@ int pmic_ddr_power_init(enum ddr_type ddr_type)
* Set LDO3 to bypass mode if BUCK3 = 1.8V
* Set LDO3 to normal mode if BUCK3 != 1.8V
*/
- status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
-
- if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
- buck3_at_1v8 = true;
+ buck3 = regulator_get_by_name("buck3");
+ if (buck3 == NULL) {
+ return -ENOENT;
}
- status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
+ regulator_get_range(buck3, &buck3_min_mv, NULL);
- read_val &= ~STPMIC1_LDO3_MODE;
- read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
- if (buck3_at_1v8) {
- read_val |= STPMIC1_LDO3_MODE;
+ if (buck3_min_mv != 1800) {
+ status = regulator_set_min_voltage(ldo3);
+ if (status != 0) {
+ return status;
+ }
+ } else {
+ status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS);
+ if (status != 0) {
+ return status;
+ }
}
- status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+ status = regulator_set_min_voltage(buck2);
if (status != 0) {
return status;
}
- if (pmic_operate(CMD_GET_MIN_VOLTAGE, "ldo3", &ldo3_mv) != 0) {
- return -EPERM;
- }
-
- status = stpmic1_regulator_voltage_set("ldo3", ldo3_mv);
+ status = regulator_enable(ldo3);
if (status != 0) {
return status;
}
- status = stpmic1_regulator_voltage_set("buck2", buck2_mv);
+ status = regulator_enable(buck2);
if (status != 0) {
return status;
}
- status = stpmic1_regulator_enable("ldo3");
+ status = regulator_enable(vref);
if (status != 0) {
return status;
}
+ break;
+
+ default:
+ break;
+ };
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+ return 0;
+}
- status = stpmic1_regulator_enable("buck2");
- if (status != 0) {
- return status;
+void pmic_switch_off(void)
+{
+ stpmic1_switch_off();
+ udelay(100);
+
+ /* Shouldn't be reached */
+ panic();
+}
+
+enum {
+ STPMIC1_BUCK1 = 0,
+ STPMIC1_BUCK2,
+ STPMIC1_BUCK3,
+ STPMIC1_BUCK4,
+ STPMIC1_LDO1,
+ STPMIC1_LDO2,
+ STPMIC1_LDO3,
+ STPMIC1_LDO4,
+ STPMIC1_LDO5,
+ STPMIC1_LDO6,
+ STPMIC1_VREF_DDR,
+ STPMIC1_BOOST,
+ STPMIC1_VBUS_OTG,
+ STPMIC1_SW_OUT,
+};
+
+static int pmic_set_state(const struct regul_description *desc, bool enable)
+{
+ VERBOSE("%s: set state to %u\n", desc->node_name, enable);
+
+ if (enable == STATE_ENABLE) {
+ return stpmic1_regulator_enable(desc->node_name);
+ } else {
+ return stpmic1_regulator_disable(desc->node_name);
+ }
+}
+
+static int pmic_get_state(const struct regul_description *desc)
+{
+ VERBOSE("%s: get state\n", desc->node_name);
+
+ return stpmic1_is_regulator_enabled(desc->node_name);
+}
+
+static int pmic_get_voltage(const struct regul_description *desc)
+{
+ VERBOSE("%s: get volt\n", desc->node_name);
+
+ return stpmic1_regulator_voltage_get(desc->node_name);
+}
+
+static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv)
+{
+ VERBOSE("%s: get volt\n", desc->node_name);
+
+ return stpmic1_regulator_voltage_set(desc->node_name, mv);
+}
+
+static int pmic_list_voltages(const struct regul_description *desc,
+ const uint16_t **levels, size_t *count)
+{
+ VERBOSE("%s: list volt\n", desc->node_name);
+
+ return stpmic1_regulator_levels_mv(desc->node_name, levels, count);
+}
+
+static int pmic_set_flag(const struct regul_description *desc, uint16_t flag)
+{
+ VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag);
+
+ switch (flag) {
+ case REGUL_OCP:
+ return stpmic1_regulator_icc_set(desc->node_name);
+
+ case REGUL_ACTIVE_DISCHARGE:
+ return stpmic1_active_discharge_mode_set(desc->node_name);
+
+ case REGUL_PULL_DOWN:
+ return stpmic1_regulator_pull_down_set(desc->node_name);
+
+ case REGUL_MASK_RESET:
+ return stpmic1_regulator_mask_reset_set(desc->node_name);
+
+ case REGUL_SINK_SOURCE:
+ return stpmic1_regulator_sink_mode_set(desc->node_name);
+
+ case REGUL_ENABLE_BYPASS:
+ return stpmic1_regulator_bypass_mode_set(desc->node_name);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+#if defined(IMAGE_BL32)
+static int driver_suspend(const struct regul_description *desc, uint8_t state, uint16_t mv)
+{
+ int ret;
+
+ VERBOSE("%s: suspend state:%d volt:%d\n", desc->node_name, (int)state, mv);
+
+ ret = stpmic1_lp_copy_reg(desc->node_name);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if ((state & LP_STATE_OFF) != 0U) {
+ ret = stpmic1_lp_reg_on_off(desc->node_name, 0);
+ if (ret != 0) {
+ return ret;
}
+ }
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+ if ((state & LP_STATE_ON) != 0U) {
+ ret = stpmic1_lp_reg_on_off(desc->node_name, 1);
+ if (ret != 0) {
+ return ret;
+ }
+ }
- status = stpmic1_regulator_enable("vref_ddr");
- if (status != 0) {
- return status;
+ if ((state & LP_STATE_SET_VOLT) != 0U) {
+ ret = stpmic1_lp_set_voltage(desc->node_name, mv);
+ if (ret != 0) {
+ return ret;
}
+ }
- mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
- break;
+ return 0;
+}
- default:
- break;
- };
+static void driver_lock(const struct regul_description *desc)
+{
+ if (stm32mp_lock_available()) {
+ spin_lock(&lock);
+ }
+}
+
+static void driver_unlock(const struct regul_description *desc)
+{
+ if (stm32mp_lock_available()) {
+ spin_unlock(&lock);
+ }
+}
+#endif
+
+struct regul_ops pmic_ops = {
+ .set_state = pmic_set_state,
+ .get_state = pmic_get_state,
+ .set_voltage = pmic_set_voltage,
+ .get_voltage = pmic_get_voltage,
+ .list_voltages = pmic_list_voltages,
+ .set_flag = pmic_set_flag,
+#if defined(IMAGE_BL32)
+ .lock = driver_lock,
+ .unlock = driver_unlock,
+ .suspend = driver_suspend,
+#endif
+};
+
+#define DEFINE_REGU(name) { \
+ .node_name = name, \
+ .ops = &pmic_ops, \
+ .driver_data = NULL, \
+ .enable_ramp_delay = 1000, \
+}
+
+static const struct regul_description pmic_regs[] = {
+ [STPMIC1_BUCK1] = DEFINE_REGU("buck1"),
+ [STPMIC1_BUCK2] = DEFINE_REGU("buck2"),
+ [STPMIC1_BUCK3] = DEFINE_REGU("buck3"),
+ [STPMIC1_BUCK4] = DEFINE_REGU("buck4"),
+ [STPMIC1_LDO1] = DEFINE_REGU("ldo1"),
+ [STPMIC1_LDO2] = DEFINE_REGU("ldo2"),
+ [STPMIC1_LDO3] = DEFINE_REGU("ldo3"),
+ [STPMIC1_LDO4] = DEFINE_REGU("ldo4"),
+ [STPMIC1_LDO5] = DEFINE_REGU("ldo5"),
+ [STPMIC1_LDO6] = DEFINE_REGU("ldo6"),
+ [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"),
+ [STPMIC1_BOOST] = DEFINE_REGU("boost"),
+ [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"),
+ [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"),
+};
+
+#define NB_REG ARRAY_SIZE(pmic_regs)
+
+static int register_pmic(void)
+{
+ void *fdt;
+ int pmic_node, regulators_node, subnode;
+
+ VERBOSE("Register pmic\n");
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ pmic_node = dt_get_pmic_node(fdt);
+ if (pmic_node < 0) {
+ return pmic_node;
+ }
+
+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
+ if (regulators_node < 0) {
+ return -ENOENT;
+ }
+
+ fdt_for_each_subnode(subnode, fdt, regulators_node) {
+ const char *reg_name = fdt_get_name(fdt, subnode, NULL);
+ const struct regul_description *desc;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < NB_REG; i++) {
+ desc = &pmic_regs[i];
+ if (strcmp(desc->node_name, reg_name) == 0) {
+ break;
+ }
+ }
+ assert(i < NB_REG);
+
+ ret = regulator_register(desc, subnode);
+ if (ret != 0) {
+ WARN("%s:%d failed to register %s\n", __func__,
+ __LINE__, reg_name);
+ return ret;
+ }
+ }
return 0;
}
diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c
index a1db120dc1..c33ef47944 100644
--- a/drivers/st/pmic/stpmic1.c
+++ b/drivers/st/pmic/stpmic1.c
@@ -17,15 +17,23 @@ struct regul_struct {
const uint16_t *voltage_table;
uint8_t voltage_table_size;
uint8_t control_reg;
+ uint8_t enable_mask;
uint8_t low_power_reg;
uint8_t pull_down_reg;
uint8_t pull_down;
uint8_t mask_reset_reg;
uint8_t mask_reset;
+ uint8_t icc_reg;
+ uint8_t icc_mask;
};
static struct i2c_handle_s *pmic_i2c_handle;
static uint16_t pmic_i2c_addr;
+/*
+ * Special mode corresponds to LDO3 in sink source mode or in bypass mode.
+ * LDO3 doesn't switch back from special to normal mode.
+ */
+static bool ldo3_special_mode;
/* Voltage tables in mV */
static const uint16_t buck1_voltage_table[] = {
@@ -346,8 +354,11 @@ static const uint16_t ldo3_voltage_table[] = {
3300,
3300,
3300,
- 500,
- 0xFFFF, /* VREFDDR */
+};
+
+/* Special mode table is used for sink source OR bypass mode */
+static const uint16_t ldo3_special_mode_table[] = {
+ 0,
};
static const uint16_t ldo5_voltage_table[] = {
@@ -431,104 +442,135 @@ static const struct regul_struct regulators_table[] = {
.voltage_table = buck1_voltage_table,
.voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
.control_reg = BUCK1_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = BUCK1_PWRCTRL_REG,
.pull_down_reg = BUCK_PULL_DOWN_REG,
.pull_down = BUCK1_PULL_DOWN_SHIFT,
.mask_reset_reg = MASK_RESET_BUCK_REG,
.mask_reset = BUCK1_MASK_RESET,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = BUCK1_ICC_SHIFT,
},
{
.dt_node_name = "buck2",
.voltage_table = buck2_voltage_table,
.voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
.control_reg = BUCK2_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = BUCK2_PWRCTRL_REG,
.pull_down_reg = BUCK_PULL_DOWN_REG,
.pull_down = BUCK2_PULL_DOWN_SHIFT,
.mask_reset_reg = MASK_RESET_BUCK_REG,
.mask_reset = BUCK2_MASK_RESET,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = BUCK2_ICC_SHIFT,
},
{
.dt_node_name = "buck3",
.voltage_table = buck3_voltage_table,
.voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
.control_reg = BUCK3_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = BUCK3_PWRCTRL_REG,
.pull_down_reg = BUCK_PULL_DOWN_REG,
.pull_down = BUCK3_PULL_DOWN_SHIFT,
.mask_reset_reg = MASK_RESET_BUCK_REG,
.mask_reset = BUCK3_MASK_RESET,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = BUCK3_ICC_SHIFT,
},
{
.dt_node_name = "buck4",
.voltage_table = buck4_voltage_table,
.voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
.control_reg = BUCK4_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = BUCK4_PWRCTRL_REG,
.pull_down_reg = BUCK_PULL_DOWN_REG,
.pull_down = BUCK4_PULL_DOWN_SHIFT,
.mask_reset_reg = MASK_RESET_BUCK_REG,
.mask_reset = BUCK4_MASK_RESET,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = BUCK4_ICC_SHIFT,
},
{
.dt_node_name = "ldo1",
.voltage_table = ldo1_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
.control_reg = LDO1_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO1_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO1_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO1_ICC_SHIFT,
},
{
.dt_node_name = "ldo2",
.voltage_table = ldo2_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
.control_reg = LDO2_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO2_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO2_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO2_ICC_SHIFT,
},
{
.dt_node_name = "ldo3",
.voltage_table = ldo3_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
.control_reg = LDO3_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO3_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO3_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO3_ICC_SHIFT,
},
{
.dt_node_name = "ldo4",
.voltage_table = ldo4_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
.control_reg = LDO4_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO4_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO4_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO4_ICC_SHIFT,
},
{
.dt_node_name = "ldo5",
.voltage_table = ldo5_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
.control_reg = LDO5_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO5_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO5_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO5_ICC_SHIFT,
},
{
.dt_node_name = "ldo6",
.voltage_table = ldo6_voltage_table,
.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
.control_reg = LDO6_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = LDO6_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = LDO6_MASK_RESET,
+ .icc_reg = LDO_ICC_TURNOFF_REG,
+ .icc_mask = LDO6_ICC_SHIFT,
},
{
.dt_node_name = "vref_ddr",
.voltage_table = vref_ddr_voltage_table,
.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
.control_reg = VREF_DDR_CONTROL_REG,
+ .enable_mask = LDO_BUCK_ENABLE_MASK,
.low_power_reg = VREF_DDR_PWRCTRL_REG,
.mask_reset_reg = MASK_RESET_LDO_REG,
.mask_reset = VREF_DDR_MASK_RESET,
@@ -538,21 +580,27 @@ static const struct regul_struct regulators_table[] = {
.voltage_table = fixed_5v_voltage_table,
.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
.control_reg = USB_CONTROL_REG,
- .mask_reset = BOOST_ENABLED,
+ .enable_mask = BOOST_ENABLED,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = BOOST_ICC_SHIFT,
},
{
.dt_node_name = "pwr_sw1",
.voltage_table = fixed_5v_voltage_table,
.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
.control_reg = USB_CONTROL_REG,
- .mask_reset = USBSW_OTG_SWITCH_ENABLED,
+ .enable_mask = USBSW_OTG_SWITCH_ENABLED,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = PWR_SW1_ICC_SHIFT,
},
{
.dt_node_name = "pwr_sw2",
.voltage_table = fixed_5v_voltage_table,
.voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table),
.control_reg = USB_CONTROL_REG,
- .mask_reset = SWIN_SWOUT_ENABLED,
+ .enable_mask = SWIN_SWOUT_ENABLED,
+ .icc_reg = BUCK_ICC_TURNOFF_REG,
+ .icc_mask = PWR_SW2_ICC_SHIFT,
},
};
@@ -607,8 +655,8 @@ int stpmic1_regulator_enable(const char *name)
{
const struct regul_struct *regul = get_regulator_data(name);
- return stpmic1_register_update(regul->control_reg, LDO_BUCK_ENABLE_MASK,
- LDO_BUCK_ENABLE_MASK);
+ return stpmic1_register_update(regul->control_reg, regul->enable_mask,
+ regul->enable_mask);
}
int stpmic1_regulator_disable(const char *name)
@@ -616,7 +664,7 @@ int stpmic1_regulator_disable(const char *name)
const struct regul_struct *regul = get_regulator_data(name);
return stpmic1_register_update(regul->control_reg, 0,
- LDO_BUCK_ENABLE_MASK);
+ regul->enable_mask);
}
bool stpmic1_is_regulator_enabled(const char *name)
@@ -628,7 +676,7 @@ bool stpmic1_is_regulator_enabled(const char *name)
panic();
}
- return (val & LDO_BUCK_ENABLE_MASK) == LDO_BUCK_ENABLE_MASK;
+ return (val & regul->enable_mask) == regul->enable_mask;
}
int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
@@ -637,6 +685,16 @@ int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
const struct regul_struct *regul = get_regulator_data(name);
uint8_t mask;
+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) {
+ /*
+ * when the LDO3 is in special mode, we do not change voltage,
+ * because by setting voltage, the LDO would leaves sink-source
+ * mode. There is obviously no reason to leave sink-source mode
+ * at runtime.
+ */
+ return 0;
+ }
+
/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
if (strncmp(name, "buck", 4) == 0) {
mask = BUCK_VOLTAGE_MASK;
@@ -670,12 +728,74 @@ int stpmic1_regulator_mask_reset_set(const char *name)
{
const struct regul_struct *regul = get_regulator_data(name);
+ if (regul->mask_reset_reg == 0U) {
+ return -EPERM;
+ }
+
return stpmic1_register_update(regul->mask_reset_reg,
BIT(regul->mask_reset),
LDO_BUCK_RESET_MASK <<
regul->mask_reset);
}
+int stpmic1_regulator_icc_set(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ if (regul->mask_reset_reg == 0U) {
+ return -EPERM;
+ }
+
+ return stpmic1_register_update(regul->icc_reg,
+ BIT(regul->icc_mask),
+ BIT(regul->icc_mask));
+}
+
+int stpmic1_regulator_sink_mode_set(const char *name)
+{
+ if (strncmp(name, "ldo3", 4) != 0) {
+ return -EPERM;
+ }
+
+ ldo3_special_mode = true;
+
+ /* disable bypass mode, enable sink mode */
+ return stpmic1_register_update(LDO3_CONTROL_REG,
+ LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT,
+ LDO3_BYPASS | LDO_VOLTAGE_MASK);
+}
+
+int stpmic1_regulator_bypass_mode_set(const char *name)
+{
+ if (strncmp(name, "ldo3", 4) != 0) {
+ return -EPERM;
+ }
+
+ ldo3_special_mode = true;
+
+ /* enable bypass mode, disable sink mode */
+ return stpmic1_register_update(LDO3_CONTROL_REG,
+ LDO3_BYPASS,
+ LDO3_BYPASS | LDO_VOLTAGE_MASK);
+}
+
+int stpmic1_active_discharge_mode_set(const char *name)
+{
+ if (strncmp(name, "pwr_sw1", 7) == 0) {
+ return stpmic1_register_update(USB_CONTROL_REG,
+ VBUS_OTG_DISCHARGE,
+ VBUS_OTG_DISCHARGE);
+ }
+
+ if (strncmp(name, "pwr_sw2", 7) == 0) {
+ return stpmic1_register_update(USB_CONTROL_REG,
+ SW_OUT_DISCHARGE,
+ SW_OUT_DISCHARGE);
+ }
+
+ return -EPERM;
+}
+
/* Low-power functions */
int stpmic1_lp_copy_reg(const char *name)
{
@@ -732,6 +852,22 @@ int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts)
mask);
}
+int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels,
+ size_t *levels_count)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) {
+ *levels_count = ARRAY_SIZE(ldo3_special_mode_table);
+ *levels = ldo3_special_mode_table;
+ } else {
+ *levels_count = regul->voltage_table_size;
+ *levels = regul->voltage_table;
+ }
+
+ return 0;
+}
+
int stpmic1_regulator_voltage_get(const char *name)
{
const struct regul_struct *regul = get_regulator_data(name);
@@ -739,6 +875,10 @@ int stpmic1_regulator_voltage_get(const char *name)
uint8_t mask;
int status;
+ if ((strncmp(name, "ldo3", 4) == 0) && ldo3_special_mode) {
+ return 0;
+ }
+
/* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
if (strncmp(name, "buck", 4) == 0) {
mask = BUCK_VOLTAGE_MASK;
diff --git a/drivers/st/regulator/regulator_fixed.c b/drivers/st/regulator/regulator_fixed.c
new file mode 100644
index 0000000000..56593717f6
--- /dev/null
+++ b/drivers/st/regulator/regulator_fixed.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <drivers/regulator.h>
+#include <drivers/st/regulator_fixed.h>
+
+#ifndef PLAT_NB_FIXED_REGS
+#error "Missing PLAT_NB_FIXED_REGS"
+#endif
+
+#define FIXED_NAME_LEN 32U
+
+struct fixed_data {
+ char name[FIXED_NAME_LEN];
+ uint16_t volt;
+ struct regul_description desc;
+};
+
+static struct fixed_data data[PLAT_NB_FIXED_REGS];
+
+static int fixed_set_state(const struct regul_description *desc, bool state)
+{
+ return 0;
+}
+
+static int fixed_get_state(const struct regul_description *desc)
+{
+ return 1;
+}
+
+static struct regul_ops fixed_ops = {
+ .set_state = fixed_set_state,
+ .get_state = fixed_get_state,
+};
+
+int fixed_regulator_register(void)
+{
+ uint32_t count = 0;
+ void *fdt;
+ int node = 0;
+
+ VERBOSE("fixed reg init!\n");
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ do {
+ size_t len __unused;
+ int ret;
+ struct fixed_data *d = &data[count];
+ const char *reg_name;
+
+ node = fdt_node_offset_by_compatible(fdt, node, "regulator-fixed");
+ if (node < 0) {
+ break;
+ }
+
+ reg_name = fdt_get_name(fdt, node, NULL);
+
+ VERBOSE("register fixed reg %s!\n", reg_name);
+
+ len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name);
+ assert((len > 0) && (len < (FIXED_NAME_LEN - 1)));
+
+ d->desc.node_name = d->name;
+ d->desc.driver_data = d;
+ d->desc.ops = &fixed_ops;
+
+ ret = regulator_register(&d->desc, node);
+ if (ret != 0) {
+ WARN("%s:%d failed to register %s\n", __func__,
+ __LINE__, reg_name);
+ return ret;
+ }
+
+ count++;
+ assert(count <= PLAT_NB_FIXED_REGS);
+
+ } while (node > 0);
+
+ return 0;
+}
diff --git a/drivers/st/regulator/stm32mp_dummy_regulator.c b/drivers/st/regulator/stm32mp_dummy_regulator.c
deleted file mode 100644
index 1003aba054..0000000000
--- a/drivers/st/regulator/stm32mp_dummy_regulator.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <drivers/st/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
deleted file mode 100644
index f0e4a4ae5c..0000000000
--- a/drivers/st/regulator/stm32mp_regulator.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c
index c9a9e9aef8..5a4dde38cd 100644
--- a/drivers/st/tamper/stm32_tamp.c
+++ b/drivers/st/tamper/stm32_tamp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,8 +11,10 @@
#include <platform_def.h>
+#include <drivers/arm/gicv2.h>
#include <drivers/clk.h>
#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32mp_reset.h>
#include <drivers/st/stm32_rng.h>
#include <drivers/st/stm32_rtc.h>
#include <drivers/st/stm32_tamp.h>
@@ -20,98 +22,190 @@
#define DT_TAMP_COMPAT "st,stm32-tamp"
/* STM32 Registers */
-#define STM32_TAMP_CR1 0x00U
-#define STM32_TAMP_CR2 0x04U
-#define STM32_TAMP_FLTCR 0x0CU
-#define STM32_TAMP_ATCR 0x10U
-#define STM32_TAMP_ATSEEDR 0x14U
-#define STM32_TAMP_ATOR 0x18U
-#define STM32_TAMP_SMCR 0x20U
-#define STM32_TAMP_IER 0x2CU
-#define STM32_TAMP_SR 0x30U
-#define STM32_TAMP_SCR 0x3CU
-#define STM32_TAMP_COUNTR 0x40U
-#define STM32_TAMP_OR 0x50U
-#define STM32_TAMP_HWCFGR2 0x3ECU
-#define STM32_TAMP_HWCFGR1 0x3F0U
-#define STM32_TAMP_VERR 0x3F4U
-#define STM32_TAMP_IPIDR 0x3F8U
-#define STM32_TAMP_SIDR 0x3FCU
-
-/* STM32_TAMP_FLTCR bit fields */
-#define STM32_TAMP_FLTCR_TAMPFREQ GENMASK(2, 0)
-#define STM32_TAMP_FLTCR_TAMPFLT GENMASK(4, 3)
-#define STM32_TAMP_FLTCR_TAMPPRCH GENMASK(6, 5)
-#define STM32_TAMP_FLTCR_TAMPPUDIS BIT(7)
-
-/* STM32_TAMP_ATCR bit fields */
-#define STM32_TAMP_ATCR_ATCKSEL GENMASK(18, 16)
-#define STM32_TAMP_ATCR_ATPER GENMASK(26, 24)
-#define STM32_TAMP_ATCR_ATOSHARE BIT(30)
-#define STM32_TAMP_ATCR_FLTEN BIT(31)
-
-/* STM32_TAMP_ATOR bit fields */
-#define STM32_TAMP_PRNG GENMASK(7, 0)
-#define STM32_TAMP_SEEDF BIT(14)
-#define STM32_TAMP_INITS BIT(15)
-
-/* STM32_TAMP_IER bit fields */
-#define STM32_TAMP_IER_TAMPXIE_ALL GENMASK(7, 0)
-#define STM32_TAMP_IER_ITAMPXIE_ALL GENMASK(31, 16)
-
-/* STM32_TAMP_SR bit fields */
-#define STM32_TAMP_SR_TAMPXF_MASK GENMASK(7, 0)
-#define STM32_TAMP_SR_ITAMPXF_MASK GENMASK(31, 16)
-
-/* STM32_TAMP_SMCR but fields */
-#define STM32_TAMP_SMCR_DPROT BIT(31)
-
-/* STM32_TAMP_CFGR bit fields */
-#define STM32_TAMP_OR_OUT3RMP BIT(0)
-
-/* STM32_TAMP_HWCFGR2 bit fields */
-#define STM32_TAMP_HWCFGR2_TZ GENMASK(11, 8)
-#define STM32_TAMP_HWCFGR2_OR GENMASK(7, 0)
-
-/* STM32_TAMP_HWCFGR1 bit fields */
-#define STM32_TAMP_HWCFGR1_BKPREG GENMASK(7, 0)
-#define STM32_TAMP_HWCFGR1_TAMPER GENMASK(11, 8)
-#define STM32_TAMP_HWCFGR1_ACTIVE GENMASK(15, 12)
-#define STM32_TAMP_HWCFGR1_INTERN GENMASK(31, 16)
-
-/* STM32_TAMP_VERR bit fields */
-#define STM32_TAMP_VERR_MINREV GENMASK(3, 0)
-#define STM32_TAMP_VERR_MAJREV GENMASK(7, 4)
-
-#define STM32_TAMP_MAX_INTERNAL 16U
-#define STM32_TAMP_MAX_EXTERNAL 8U
+#define _TAMP_CR1 0x00U
+#define _TAMP_CR2 0x04U
+#define _TAMP_FLTCR 0x0CU
+#define _TAMP_ATCR1 0x10U
+#define _TAMP_ATSEEDR 0x14U
+#define _TAMP_ATOR 0x18U
+#define _TAMP_SMCR 0x20U
+#define _TAMP_IER 0x2CU
+#define _TAMP_SR 0x30U
+#define _TAMP_MISR 0x34U
+#define _TAMP_SMISR 0x38U
+#define _TAMP_SCR 0x3CU
+#define _TAMP_COUNTR 0x40U
+#define _TAMP_OR 0x50U
+#define _TAMP_HWCFGR2 0x3ECU
+#define _TAMP_HWCFGR1 0x3F0U
+#define _TAMP_VERR 0x3F4U
+#define _TAMP_IPIDR 0x3F8U
+#define _TAMP_SIDR 0x3FCU
+
+/* _TAMP_CR1 bit filds */
+#define _TAMP_CR1_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_CR1_ETAMP(id) BIT((id))
+
+/* _TAMP_CR2 bit filds */
+#define _TAMP_CR2_ETAMPTRG(id) BIT((id) + 24U)
+#define _TAMP_CR2_ETAMPMSK_MAX_ID 3U
+#define _TAMP_CR2_ETAMPMSK(id) BIT((id) + 16U)
+#define _TAMP_CR2_ETAMPNOER(id) BIT((id))
+
+/* _TAMP_FLTCR bit fields */
+#define _TAMP_FLTCR_TAMPFREQ GENMASK(2, 0)
+#define _TAMP_FLTCR_TAMPFLT GENMASK(4, 3)
+#define _TAMP_FLTCR_TAMPPRCH GENMASK(6, 5)
+#define _TAMP_FLTCR_TAMPPUDIS BIT(7)
+
+/* _TAMP_ATCR bit fields */
+#define _TAMP_ATCR1_ATCKSEL GENMASK(18, 16)
+#define _TAMP_ATCR1_ATPER GENMASK(26, 24)
+#define _TAMP_ATCR1_COMMON_MASK GENMASK(31, 16)
+#define _TAMP_ATCR1_ETAMPAM(id) BIT((id))
+#define _TAMP_ATCR1_ATOSEL_MASK(i) GENMASK(((i) + 1) * 2U + 7U, (i) * 2U + 8U)
+#define _TAMP_ATCR1_ATOSEL(i, o) (((o) - 1U) << ((i) * 2U + 8U))
+
+/* _TAMP_ATOR bit fields */
+#define _TAMP_PRNG GENMASK(7, 0)
+#define _TAMP_SEEDF BIT(14)
+#define _TAMP_INITS BIT(15)
+
+/* _TAMP_IER bit fields */
+#define _TAMP_IER_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_IER_ETAMP(id) BIT((id))
+
+/* _TAMP_SR bit fields */
+#define _TAMP_SR_ETAMPXF_MASK GENMASK(7, 0)
+#define _TAMP_SR_ITAMPXF_MASK GENMASK(31, 16)
+#define _TAMP_SR_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_SR_ETAMP(id) BIT((id))
+
+/* _TAMP_SCR bit fields */
+#define _TAMP_SCR_ITAMP(id) BIT((id) + 16U)
+#define _TAMP_SCR_ETAMP(id) BIT((id))
+
+/* _TAMP_SMCR bit fields */
+#define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK(7, 0)
+#define _TAMP_SMCR_BKPRWDPROT_SHIFT U(0)
+#define _TAMP_SMCR_BKPWDPROT_MASK GENMASK(23, 16)
+#define _TAMP_SMCR_BKPWDPROT_SHIFT U(16)
+#define _TAMP_SMCR_DPROT BIT(31)
+
+/* _TAMP_OR bit fields */
+#define _TAMP_OR_OUT3RMP_PI8 0U
+#define _TAMP_OR_OUT3RMP_PC13 BIT(0)
+
+/* _TAMP_HWCFGR2 bit fields */
+#define _TAMP_HWCFGR2_TZ GENMASK(11, 8)
+#define _TAMP_HWCFGR2_OR GENMASK(7, 0)
+
+/* _TAMP_HWCFGR1 bit fields */
+#define _TAMP_HWCFGR1_BKPREG GENMASK(7, 0)
+#define _TAMP_HWCFGR1_TAMPER GENMASK(11, 8)
+#define _TAMP_HWCFGR1_ACTIVE GENMASK(15, 12)
+#define _TAMP_HWCFGR1_INTERN GENMASK(31, 16)
+#define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U
+#define _TAMP_HWCFGR1_ITAMP(id) BIT((id) + 16U)
+
+/* _TAMP_VERR bit fields */
+#define _TAMP_VERR_MINREV GENMASK(3, 0)
+#define _TAMP_VERR_MAJREV GENMASK(7, 4)
+
+#define _TAMP_NB_MONOTONIC_COUNTER 0x1
+
+/*
+ * Macro to manage bit manipulation when we work on local variable
+ * before writing only once to the real register
+ */
+
+#define CLRBITS(v, bits) (v) &= ~(bits)
+#define SETBITS(v, bits) (v) |= (bits)
+#define CLRSETBITS(v, mask, bits) (v) = ((v) & ~(mask)) | (bits)
+
+struct stm32_tamp_int {
+ const uint32_t id;
+ uint32_t mode;
+ int (*func)(int id);
+};
+
+struct stm32_tamp_ext {
+ const uint32_t id;
+ uint32_t mode;
+ uint8_t out_pin;
+ int (*func)(int id);
+};
struct stm32_tamp_instance {
uintptr_t base;
uint32_t clock;
uint32_t hwconf1;
uint32_t hwconf2;
- uint16_t int_nbtamp;
- uint8_t ext_nbtamp;
- struct stm32_tamp_int *int_tamp;
- struct stm32_tamp_ext *ext_tamp;
+ uint32_t secret_list_conf;
+ uint32_t privilege_conf;
+ uint32_t secure_conf;
+ uint32_t passive_conf;
+ uint32_t active_conf;
+ struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT];
+ struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT];
};
-static struct stm32_tamp_instance stm32_tamp;
+/* 0 is the expected initial values for all fields but .id */
+static struct stm32_tamp_instance stm32_tamp = {
+ .int_tamp = {
+ {
+ .id = INT_TAMP1,
+ },
+ {
+ .id = INT_TAMP2,
+ },
+ {
+ .id = INT_TAMP3,
+ },
+ {
+ .id = INT_TAMP4,
+ },
+ {
+ .id = INT_TAMP5,
+ },
+ {
+ .id = INT_TAMP8,
+ },
+ },
+ .ext_tamp = {
+ {
+ .id = EXT_TAMP1,
+ },
+ {
+ .id = EXT_TAMP2,
+ },
+ {
+ .id = EXT_TAMP3,
+ },
+ }
+};
-static void stm32_tamp_set_secured(unsigned long base)
+static void stm32_tamp_set_secure(unsigned long base, uint32_t mode)
{
- mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT);
+ if (mode & TAMP_REGS_IT_SECURE) {
+ mmio_clrbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
+ } else {
+ mmio_setbits_32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
+ }
}
-static void stm32_tamp_configure_or(unsigned long base, uint32_t out3)
+static void stm32_tamp_set_privilege(unsigned long base __unused, uint32_t mode __unused)
{
- mmio_setbits_32(base + STM32_TAMP_OR, out3);
}
-static int stm32_tamp_seed_init(unsigned long base)
+static void stm32_tamp_set_output_pin(unsigned long base, uint32_t out)
{
- /* Need RNG access */
+ mmio_setbits_32(base + _TAMP_OR, out);
+}
+
+static int stm32_tamp_set_seed(unsigned long base)
+{
+ /* Need RNG access. */
uint32_t timeout = 100;
uint8_t idx;
@@ -123,11 +217,10 @@ static int stm32_tamp_seed_init(unsigned long base)
}
VERBOSE("Seed init %u\n", rnd);
- mmio_write_32(base + STM32_TAMP_ATSEEDR, rnd);
+ mmio_write_32(base + _TAMP_ATSEEDR, rnd);
}
- while (((mmio_read_32(base + STM32_TAMP_ATOR) &
- STM32_TAMP_SEEDF) != 0U) &&
+ while (((mmio_read_32(base + _TAMP_ATOR) & _TAMP_SEEDF) != 0U) &&
(timeout != 0U)) {
timeout--;
}
@@ -139,129 +232,334 @@ static int stm32_tamp_seed_init(unsigned long base)
return 0;
}
-static void stm32_tamp_reset_register(unsigned long base)
+static bool is_int_tamp_id_valid(uint32_t id)
{
- /* Disable all internal tamper */
- mmio_write_32(base + STM32_TAMP_CR1, 0U);
-
- /* Disable all external tamper */
- mmio_write_32(base + STM32_TAMP_CR2, 0U);
+ if (id > _TAMP_HWCFGR1_ITAMP_MAX_ID) {
+ return false;
+ }
- /* Clean configuration registers */
- mmio_write_32(base + STM32_TAMP_FLTCR, 0U);
- mmio_write_32(base + STM32_TAMP_ATCR, 0U);
- mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT);
+ return (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_ITAMP(id))
+ == _TAMP_HWCFGR1_ITAMP(id);
+}
- /* Clean Tamper IT */
- mmio_write_32(base + STM32_TAMP_IER, 0U);
- mmio_write_32(base + STM32_TAMP_SCR, ~0U);
+static bool is_ext_tamp_id_valid(uint32_t id)
+{
+ if (id > PLAT_MAX_TAMP_EXT) {
+ return false;
+ }
- mmio_clrbits_32(base + STM32_TAMP_OR, STM32_TAMP_OR_OUT3RMP);
+ return true;
}
-void stm32_tamp_write_mcounter(void)
+static int stm32_tamp_set_int_config(struct stm32_tamp_int *tamp_int,
+ uint32_t *cr1, uint32_t *cr3, uint32_t *ier)
{
- mmio_write_32(stm32_tamp.base + STM32_TAMP_COUNTR, 1U);
+ uint32_t id;
+
+ if (tamp_int == NULL) {
+ return -EINVAL;
+ }
+
+ id = tamp_int->id;
+
+ if (!is_int_tamp_id_valid(id)) {
+ return -EINVAL;
+ }
+
+ /* If etamp is disabled */
+ if ((tamp_int->mode & TAMP_ENABLE) != TAMP_ENABLE) {
+ CLRBITS(*cr1, _TAMP_CR1_ITAMP(id));
+ CLRBITS(*ier, _TAMP_IER_ITAMP(id));
+ return 0;
+ }
+
+ SETBITS(*cr1, _TAMP_CR1_ITAMP(id));
+ SETBITS(*ier, _TAMP_IER_ITAMP(id));
+
+ return 0;
}
-void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list,
- uint16_t nb_tamper)
+static int stm32_tamp_set_ext_config(struct stm32_tamp_ext *tamp_ext,
+ uint32_t *cr1, uint32_t *cr2,
+ uint32_t *atcr1, uint32_t *atcr2, uint32_t *ier)
{
- uint16_t i;
+ uint32_t id;
- assert(nb_tamper < STM32_TAMP_MAX_INTERNAL);
+ if (tamp_ext == NULL) {
+ return -EINVAL;
+ }
- for (i = 0; i < nb_tamper; i++) {
- int id = tamper_list[i].id;
- uint32_t u_id;
+ id = tamp_ext->id;
- if (id == -1) {
- continue;
- }
+ /* Exit if not a valid TAMP_ID */
+ if (!is_ext_tamp_id_valid(id)) {
+ return -EINVAL;
+ }
+
+ /* If etamp is disabled */
+ if ((tamp_ext->mode & TAMP_ENABLE) != TAMP_ENABLE) {
+ CLRBITS(*cr1, _TAMP_CR1_ETAMP(id));
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id));
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id));
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id));
+ CLRBITS(*ier, _TAMP_IER_ETAMP(id));
+ return 0;
+ }
+
+ SETBITS(*cr1, _TAMP_CR1_ETAMP(id));
+
+ if ((tamp_ext->mode & TAMP_TRIG_ON) == TAMP_TRIG_ON) {
+ SETBITS(*cr2, _TAMP_CR2_ETAMPTRG(id));
+ } else {
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPTRG(id));
+ }
+
+ if ((tamp_ext->mode & TAMP_ACTIVE) == TAMP_ACTIVE) {
+ SETBITS(*cr1, _TAMP_ATCR1_ETAMPAM(id));
+ } else {
+ CLRBITS(*cr1, _TAMP_ATCR1_ETAMPAM(id));
+ }
+
+ if ((tamp_ext->mode & TAMP_NOERASE) == TAMP_NOERASE) {
+ SETBITS(*cr2, _TAMP_CR2_ETAMPNOER(id));
+ } else {
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPNOER(id));
+ }
- u_id = (uint32_t)id;
+ /* Configure output pin:
+ * For the case out_pin = 0, we select same output pin than the input one.
+ */
+ if (tamp_ext->out_pin == TAMPOUTSEL_SAME_AS_INPUT) {
+ tamp_ext->out_pin = id + 1;
+ }
+
+ if (tamp_ext->out_pin < PLAT_MAX_TAMP_EXT + 1U) {
+ CLRSETBITS(*atcr1, _TAMP_ATCR1_ATOSEL_MASK(id),
+ _TAMP_ATCR1_ATOSEL(id, tamp_ext->out_pin));
+ }
- if ((stm32_tamp.hwconf1 & BIT(u_id + 16U)) != 0U) {
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1,
- BIT(u_id + 16U));
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER,
- BIT(u_id + 16U));
+ if (id < _TAMP_CR2_ETAMPMSK_MAX_ID) {
+ /*
+ * Only external TAMP 1, 2 and 3 can be masked
+ */
+ if ((tamp_ext->mode & TAMP_EVT_MASK) == TAMP_EVT_MASK) {
+ /*
+ * ETAMP(id) event generates a trigger event. This ETAMP(id) is masked
+ * and internally cleared by hardware. The backup registers are not erased.
+ */
+ CLRBITS(*ier, _TAMP_IER_ETAMP(id));
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id));
+ } else {
+ /*
+ * normal ETAMP interrupt:
+ * ETAMP(id) event generates a trigger event and TAMP(id)F must be cleared
+ * by software to * allow next tamper event detection.
+ */
+ CLRBITS(*cr2, _TAMP_CR2_ETAMPMSK(id));
+ CLRBITS(*ier, _TAMP_IER_ETAMP(id));
}
+ } else {
+ /* other than 1,2,3 external TAMP, we want its interruption */
+ CLRBITS(*ier, _TAMP_IER_ETAMP(id));
}
- stm32_tamp.int_tamp = tamper_list;
- stm32_tamp.int_nbtamp = nb_tamper;
+ return 0;
}
-void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list,
- uint8_t nb_tamper, uint32_t passive_conf,
- uint32_t active_conf)
+int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf)
{
- /* External configuration */
- uint8_t i, active_tamp = 0;
+ uint32_t first_z2;
+ uint32_t first_z3;
- assert(nb_tamper < STM32_TAMP_MAX_EXTERNAL);
+ if (bkpregs_conf == NULL) {
+ return -EINVAL;
+ }
- /* Enable external Tamp */
- for (i = 0; i < nb_tamper; i++) {
- int id = ext_tamper_list[i].id;
- uint32_t reg = 0, u_id;
+ first_z2 = bkpregs_conf->nb_zone1_regs;
+ first_z3 = bkpregs_conf->nb_zone1_regs + bkpregs_conf->nb_zone2_regs;
- if (id == -1) {
- continue;
- }
+ if ((first_z2 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
+ (first_z3 > (stm32_tamp.hwconf1 & _TAMP_HWCFGR1_BKPREG))) {
+ return -ENODEV;
+ }
+
+ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR,
+ _TAMP_SMCR_BKPRWDPROT_MASK,
+ (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) &
+ _TAMP_SMCR_BKPRWDPROT_MASK);
- u_id = (uint32_t)id;
+ mmio_clrsetbits_32(stm32_tamp.base + _TAMP_SMCR,
+ _TAMP_SMCR_BKPWDPROT_MASK,
+ (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) &
+ _TAMP_SMCR_BKPWDPROT_MASK);
+ return 0;
+}
+
+int stm32_tamp_set_config(void)
+{
+ int ret;
+ uint32_t i;
+ uint32_t cr1 = 0, cr2 = 0, cr3 = 0;
+ uint32_t atcr1 = 0, atcr2 = 0;
+ uint32_t fltcr = 0;
+ uint32_t ier = 0;
+
+ /* Select access in secure or unsecure */
+ stm32_tamp_set_secure(stm32_tamp.base, stm32_tamp.secure_conf);
+
+ /* Select acces in privileged mode or unprivileged mode */
+ stm32_tamp_set_privilege(stm32_tamp.base, stm32_tamp.privilege_conf);
+
+ if (stm32_tamp.passive_conf != 0U) {
+ /* Filter mode register set */
+ fltcr = stm32_tamp.passive_conf;
+ }
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1,
- BIT(u_id));
+ if (stm32_tamp.active_conf != 0U) {
+ /* Active mode configuration */
+ CLRSETBITS(atcr1, _TAMP_ATCR1_COMMON_MASK,
+ (stm32_tamp.active_conf & _TAMP_ATCR1_COMMON_MASK));
+ }
- if (ext_tamper_list[i].mode == TAMP_TRIG_ON) {
- reg |= BIT(u_id + 24U);
+ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) {
+ ret = stm32_tamp_set_int_config(&(stm32_tamp.int_tamp[i]),
+ &cr1, &cr3, &ier);
+ if (ret != 0) {
+ return ret;
}
+ }
- if (ext_tamper_list[i].mode == TAMP_ACTIVE) {
- active_tamp |= BIT(u_id);
+ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) {
+ ret = stm32_tamp_set_ext_config(&(stm32_tamp.ext_tamp[i]),
+ &cr1, &cr2, &atcr1, &atcr2, &ier);
+ if (ret != 0) {
+ return ret;
}
+ }
+
+ /*
+ * We apply configuration all in a row:
+ * As for active ext tamper "all the needed tampers must be enabled in the same write
+ * access".
+ */
+ mmio_write_32(stm32_tamp.base + _TAMP_FLTCR, fltcr);
+ /* Active filter configuration applied only if not already done. */
+ if (((mmio_read_32(stm32_tamp.base + _TAMP_ATOR) & _TAMP_INITS) != _TAMP_INITS)) {
+ mmio_write_32(stm32_tamp.base + _TAMP_ATCR1, atcr1);
+ }
- if (ext_tamper_list[i].erase != 0U) {
- reg |= BIT(u_id);
+ mmio_write_32(stm32_tamp.base + _TAMP_CR1, cr1);
+ mmio_write_32(stm32_tamp.base + _TAMP_CR2, cr2);
+ /* If active tamper we reinit the seed. */
+ if (stm32_tamp.active_conf != 0U) {
+ if (stm32_tamp_set_seed(stm32_tamp.base) != 0) {
+ ERROR("Active tamper: SEED not initialized\n");
+ return -EPERM;
}
+ }
- if (ext_tamper_list[i].evt_mask != 0U) {
- reg |= BIT(u_id + 16U);
- } else {
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER,
- BIT(u_id));
+ /* Ack all pending interrupt */
+ mmio_write_32(stm32_tamp.base + _TAMP_SCR, ~0U);
+ /* Enable interrupts. */
+ mmio_write_32(stm32_tamp.base + _TAMP_IER, ier);
+
+ return 0;
+}
+
+int stm32_tamp_write_mcounter(int counter_idx)
+{
+ mmio_write_32(stm32_tamp.base + _TAMP_COUNTR, 1U);
+
+ return 0;
+}
+
+uint32_t stm32_tamp_read_mcounter(int counter_idx)
+{
+ return mmio_read_32(stm32_tamp.base + _TAMP_COUNTR);
+}
+
+void stm32_tamp_configure_secret_list(uint32_t secret_list_conf)
+{
+ stm32_tamp.secret_list_conf = secret_list_conf;
+}
+
+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf)
+{
+ stm32_tamp.privilege_conf = privilege_conf;
+}
+
+void stm32_tamp_configure_secure_access(uint32_t secure_conf)
+{
+ stm32_tamp.secure_conf = secure_conf;
+}
+
+void stm32_tamp_configure_passive(uint32_t passive_conf)
+{
+ stm32_tamp.passive_conf = passive_conf;
+}
+
+void stm32_tamp_configure_active(uint32_t active_conf)
+{
+ stm32_tamp.active_conf = active_conf;
+}
+
+int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode, int (*callback)(int id))
+{
+ uint32_t i;
+ uint32_t itamp_id = id;
+ struct stm32_tamp_int *tamp_int = NULL;
+
+ /* Find internal Tamp struct*/
+ for (i = 0U; i < PLAT_MAX_TAMP_INT; i++) {
+ if (stm32_tamp.int_tamp[i].id == itamp_id) {
+ tamp_int = &(stm32_tamp.int_tamp[i]);
+ break;
}
+ }
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR2, reg);
+ if (tamp_int == NULL) {
+ return -EINVAL;
}
- /* Filter mode register set */
- mmio_write_32(stm32_tamp.base + STM32_TAMP_FLTCR, passive_conf);
+ tamp_int->mode = mode;
+ tamp_int->func = callback;
- /* Active mode configuration */
- if (active_tamp != 0U) {
- mmio_write_32(stm32_tamp.base + STM32_TAMP_ATCR,
- active_conf | active_tamp);
- if (stm32_tamp_seed_init(stm32_tamp.base) != 0) {
- ERROR("Active tamper: SEED not initialized\n");
- panic();
+ return 0;
+}
+
+int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode,
+ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id))
+{
+ uint32_t i;
+ uint32_t etamp_id = id;
+ struct stm32_tamp_ext *tamp_ext = NULL;
+
+ /* Find external Tamp struct */
+ for (i = 0U; i < PLAT_MAX_TAMP_EXT; i++) {
+ if (stm32_tamp.ext_tamp[i].id == etamp_id) {
+ tamp_ext = &(stm32_tamp.ext_tamp[i]);
+ break;
}
}
- stm32_tamp.ext_tamp = ext_tamper_list;
- stm32_tamp.ext_nbtamp = nb_tamper;
+ if (tamp_ext == NULL) {
+ return -EINVAL;
+ }
+
+ tamp_ext->mode = mode;
+ tamp_ext->out_pin = out_pin;
+ tamp_ext->func = callback;
+
+ return 0;
}
void stm32_tamp_it_handler(void)
{
- uint32_t it = mmio_read_32(stm32_tamp.base + STM32_TAMP_SR);
+ uint32_t it = mmio_read_32(stm32_tamp.base + _TAMP_SR);
+ uint32_t int_it = it & _TAMP_SR_ITAMPXF_MASK;
+ uint32_t ext_it = it & _TAMP_SR_ETAMPXF_MASK;
uint8_t tamp = 0;
struct stm32_rtc_time tamp_ts;
- struct stm32_tamp_int *int_list = stm32_tamp.int_tamp;
- struct stm32_tamp_ext *ext_list = stm32_tamp.ext_tamp;
if (stm32_rtc_is_timestamp_enable()) {
stm32_rtc_get_timestamp(&tamp_ts);
@@ -271,45 +569,53 @@ void stm32_tamp_it_handler(void)
tamp_ts.min, tamp_ts.sec);
}
- /* Internal tamper interrupt */
- if ((it & STM32_TAMP_IER_ITAMPXIE_ALL) == 0U) {
- goto tamp_ext;
- }
+ while ((int_it != 0U) && (tamp < PLAT_MAX_TAMP_INT)) {
+ int ret = -1;
+ uint32_t int_id = stm32_tamp.int_tamp[tamp].id;
- while ((it != 0U) && (tamp < stm32_tamp.int_nbtamp)) {
- uint32_t int_id = (uint32_t)int_list[tamp].id;
+ if ((it & _TAMP_SR_ITAMP(int_id)) != 0U) {
+ if (stm32_tamp.int_tamp[tamp].func != NULL) {
+ ret = stm32_tamp.int_tamp[tamp].func(int_id);
+ }
+
+ if (ret >= 0) {
+ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR,
+ _TAMP_SR_ITAMP(int_id));
+ ext_it &= ~_TAMP_SR_ITAMP(int_id);
- if ((it & BIT(int_id + 16U)) != 0U) {
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR, BIT(int_id + 16U));
- it &= ~BIT(int_id + 16U);
- if (int_list[tamp].func != NULL) {
- int_list[tamp].func(int_id);
+ if (ret > 0) {
+ stm32mp_system_reset();
+ }
}
}
tamp++;
}
-tamp_ext:
tamp = 0;
/* External tamper interrupt */
- if ((it == 0U) || ((it & STM32_TAMP_IER_TAMPXIE_ALL) == 0U)) {
- return;
- }
+ while ((ext_it != 0U) && (tamp < PLAT_MAX_TAMP_EXT)) {
+ int ret = -1;
+ uint32_t ext_id = stm32_tamp.ext_tamp[tamp].id;
- while ((it != 0U) && (tamp < stm32_tamp.ext_nbtamp)) {
- uint32_t ext_id = (uint32_t)ext_list[tamp].id;
-
- if ((it & BIT(ext_id)) != 0U) {
- if (ext_list[tamp].func != NULL) {
- ext_list[tamp].func(ext_id);
+ if ((ext_it & _TAMP_SR_ETAMP(ext_id)) != 0U) {
+ if (stm32_tamp.ext_tamp[tamp].func != NULL) {
+ ret = stm32_tamp.ext_tamp[tamp].func(ext_id);
}
- mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR,
- BIT(ext_id));
- it &= ~BIT(ext_id);
+ if (ret >= 0) {
+ mmio_setbits_32(stm32_tamp.base + _TAMP_SCR,
+ _TAMP_SCR_ETAMP(ext_id));
+ ext_it &= ~_TAMP_SR_ETAMP(ext_id);
+
+ if (ret > 0) {
+ stm32mp_system_reset();
+ }
+ }
}
tamp++;
}
+
+ gicv2_end_of_interrupt(STM32MP1_IRQ_TAMPSERRS);
}
int stm32_tamp_init(void)
@@ -325,7 +631,7 @@ int stm32_tamp_init(void)
node = dt_get_node(&dt_tamp, -1, DT_TAMP_COMPAT);
if (node < 0) {
- return -FDT_ERR_NOTFOUND;
+ return -EINVAL;
}
assert(dt_tamp.base != 0U);
@@ -337,37 +643,34 @@ int stm32_tamp_init(void)
/* Init Tamp clock */
clk_enable(stm32_tamp.clock);
- /* Reset Tamp register without modifying backup registers conf */
- stm32_tamp_reset_register(stm32_tamp.base);
-
/* Check if TAMP is enabled */
if ((dt_tamp.status != DT_SECURE) &&
(dt_tamp.status != DT_SHARED)) {
return 0;
}
- stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR1);
- stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR2);
+ stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR1);
+ stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + _TAMP_HWCFGR2);
- rev = mmio_read_32(stm32_tamp.base + STM32_TAMP_VERR);
- VERBOSE("STM32 TAMPER V%u.%u\n", (rev & STM32_TAMP_VERR_MAJREV) >> 4,
- rev & STM32_TAMP_VERR_MINREV);
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ rev = mmio_read_32(stm32_tamp.base + _TAMP_VERR);
+ VERBOSE("STM32 TAMPER V%u.%u\n", (rev & _TAMP_VERR_MAJREV) >> 4,
+ rev & _TAMP_VERR_MINREV);
+#endif
- if ((stm32_tamp.hwconf2 & STM32_TAMP_HWCFGR2_TZ) == 0U) {
+ if ((stm32_tamp.hwconf2 & _TAMP_HWCFGR2_TZ) == 0U) {
ERROR("Tamper IP doesn't support trustzone");
return -EPERM;
}
- stm32_tamp_set_secured(stm32_tamp.base);
-
if (dt_set_pinctrl_config(node) != -FDT_ERR_NOTFOUND) {
if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) {
- stm32_tamp_configure_or(stm32_tamp.base, 1);
+ stm32_tamp_set_output_pin(stm32_tamp.base, _TAMP_OR_OUT3RMP_PC13);
}
}
if (stm32_gic_enable_spi(node, NULL) < 0) {
- panic();
+ return -EPERM;
}
if (fdt_getprop(fdt, node, "wakeup-source", NULL) != NULL) {
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index 2cb04a88fc..5872157323 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -45,7 +45,12 @@ func console_stm32_core_init
/* Check the input base address */
cmp r0, #0
beq core_init_fail
-#if defined(IMAGE_BL2)
+#if !defined(IMAGE_BL2)
+ /* Skip UART initialization if it is already enabled */
+ ldr r3, [r0, #USART_CR1]
+ ands r3, r3, #USART_CR1_UE
+ bne 1f
+#endif /* IMAGE_BL2 */
/* Check baud rate and uart clock for sanity */
cmp r1, #0
beq core_init_fail
@@ -78,7 +83,7 @@ teack_loop:
ldr r3, [r0, #USART_ISR]
tst r3, #USART_ISR_TEACK
beq teack_loop
-#endif /* IMAGE_BL2 */
+1:
mov r0, #1
bx lr
core_init_fail:
diff --git a/fdts/stm32mp15-ddr-512m-fw-config.dts b/fdts/stm32mp15-ddr-512m-fw-config.dts
deleted file mode 100644
index 3d0722181a..0000000000
--- a/fdts/stm32mp15-ddr-512m-fw-config.dts
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/*
- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
- */
-
-#include <platform_def.h>
-
-#include <common/tbbr/tbbr_img_def.h>
-#include <dt-bindings/soc/stm32mp1-tzc400.h>
-
-/dts-v1/;
-
-/ {
- dtb-registry {
- compatible = "fconf,dyn_cfg-dtb_registry";
-
- hw-config {
- load-address = <0x0 STM32MP_HW_CONFIG_BASE>;
- max-size = <STM32MP_HW_CONFIG_MAX_SIZE>;
- id = <HW_CONFIG_ID>;
- };
-
- nt_fw {
- load-address = <0x0 STM32MP_BL33_BASE>;
- max-size = <STM32MP_BL33_MAX_SIZE>;
- id = <BL33_IMAGE_ID>;
- };
-
-#ifdef AARCH32_SP_OPTEE
- tos_fw {
- load-address = <0x0 0x2FFC0000>;
- max-size = <0x0001F000>;
- id = <BL32_IMAGE_ID>;
- };
-#else
- tos_fw {
- load-address = <0x0 STM32MP_BL32_BASE>;
- max-size = <STM32MP_BL32_SIZE>;
- id = <BL32_IMAGE_ID>;
- };
-
- tos_fw-config {
- load-address = <0x0 STM32MP_BL32_DTB_BASE>;
- max-size = <STM32MP_BL32_DTB_SIZE>;
- id = <TOS_FW_CONFIG_ID>;
- };
-#endif
- };
-
- st-mem-firewall {
- compatible = "st,mem-firewall";
-#ifdef AARCH32_SP_OPTEE
- memory-ranges = <
- 0xc0000000 0x1e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR
- 0xde000000 0x01e00000 TZC_REGION_S_RDWR 0
- 0xdfe00000 0x00200000 TZC_REGION_S_NONE
- TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>;
-#else
- memory-ranges = <
- 0xc0000000 0x20000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>;
-#endif
- };
-};
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
index 734943c0ea..43424a0079 100644
--- a/fdts/stm32mp15-ddr.dtsi
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -1,165 +1,129 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
*/
-/ {
- soc {
- ddr: ddr@5a003000{
+&ddr {
+ st,mem-name = DDR_MEM_NAME;
+ st,mem-speed = <DDR_MEM_SPEED>;
+ st,mem-size = <DDR_MEM_SIZE>;
- compatible = "st,stm32mp1-ddr";
+ st,ctl-reg = <
+ DDR_MSTR
+ DDR_MRCTRL0
+ DDR_MRCTRL1
+ DDR_DERATEEN
+ DDR_DERATEINT
+ DDR_PWRCTL
+ DDR_PWRTMG
+ DDR_HWLPCTL
+ DDR_RFSHCTL0
+ DDR_RFSHCTL3
+ DDR_CRCPARCTL0
+ DDR_ZQCTL0
+ DDR_DFITMG0
+ DDR_DFITMG1
+ DDR_DFILPCFG0
+ DDR_DFIUPD0
+ DDR_DFIUPD1
+ DDR_DFIUPD2
+ DDR_DFIPHYMSTR
+ DDR_ODTMAP
+ DDR_DBG0
+ DDR_DBG1
+ DDR_DBGCMD
+ DDR_POISONCFG
+ DDR_PCCFG
+ >;
- reg = <0x5A003000 0x550
- 0x5A004000 0x234>;
+ st,ctl-timing = <
+ DDR_RFSHTMG
+ DDR_DRAMTMG0
+ DDR_DRAMTMG1
+ DDR_DRAMTMG2
+ DDR_DRAMTMG3
+ DDR_DRAMTMG4
+ DDR_DRAMTMG5
+ DDR_DRAMTMG6
+ DDR_DRAMTMG7
+ DDR_DRAMTMG8
+ DDR_DRAMTMG14
+ DDR_ODTCFG
+ >;
- clocks = <&rcc AXIDCG>,
- <&rcc DDRC1>,
-#if STM32MP_DDR_DUAL_AXI_PORT
- <&rcc DDRC2>,
-#endif
- <&rcc DDRPHYC>,
- <&rcc DDRCAPB>,
- <&rcc DDRPHYCAPB>;
-
- clock-names = "axidcg",
- "ddrc1",
-#if STM32MP_DDR_DUAL_AXI_PORT
- "ddrc2",
-#endif
- "ddrphyc",
- "ddrcapb",
- "ddrphycapb";
+ st,ctl-map = <
+ DDR_ADDRMAP1
+ DDR_ADDRMAP2
+ DDR_ADDRMAP3
+ DDR_ADDRMAP4
+ DDR_ADDRMAP5
+ DDR_ADDRMAP6
+ DDR_ADDRMAP9
+ DDR_ADDRMAP10
+ DDR_ADDRMAP11
+ >;
- st,mem-name = DDR_MEM_NAME;
- st,mem-speed = <DDR_MEM_SPEED>;
- st,mem-size = <DDR_MEM_SIZE>;
+ st,ctl-perf = <
+ DDR_SCHED
+ DDR_SCHED1
+ DDR_PERFHPR1
+ DDR_PERFLPR1
+ DDR_PERFWR1
+ DDR_PCFGR_0
+ DDR_PCFGW_0
+ DDR_PCFGQOS0_0
+ DDR_PCFGQOS1_0
+ DDR_PCFGWQOS0_0
+ DDR_PCFGWQOS1_0
+ DDR_PCFGR_1
+ DDR_PCFGW_1
+ DDR_PCFGQOS0_1
+ DDR_PCFGQOS1_1
+ DDR_PCFGWQOS0_1
+ DDR_PCFGWQOS1_1
+ >;
- st,ctl-reg = <
- DDR_MSTR
- DDR_MRCTRL0
- DDR_MRCTRL1
- DDR_DERATEEN
- DDR_DERATEINT
- DDR_PWRCTL
- DDR_PWRTMG
- DDR_HWLPCTL
- DDR_RFSHCTL0
- DDR_RFSHCTL3
- DDR_CRCPARCTL0
- DDR_ZQCTL0
- DDR_DFITMG0
- DDR_DFITMG1
- DDR_DFILPCFG0
- DDR_DFIUPD0
- DDR_DFIUPD1
- DDR_DFIUPD2
- DDR_DFIPHYMSTR
- DDR_ODTMAP
- DDR_DBG0
- DDR_DBG1
- DDR_DBGCMD
- DDR_POISONCFG
- DDR_PCCFG
- >;
+ st,phy-reg = <
+ DDR_PGCR
+ DDR_ACIOCR
+ DDR_DXCCR
+ DDR_DSGCR
+ DDR_DCR
+ DDR_ODTCR
+ DDR_ZQ0CR1
+ DDR_DX0GCR
+ DDR_DX1GCR
+ DDR_DX2GCR
+ DDR_DX3GCR
+ >;
- st,ctl-timing = <
- DDR_RFSHTMG
- DDR_DRAMTMG0
- DDR_DRAMTMG1
- DDR_DRAMTMG2
- DDR_DRAMTMG3
- DDR_DRAMTMG4
- DDR_DRAMTMG5
- DDR_DRAMTMG6
- DDR_DRAMTMG7
- DDR_DRAMTMG8
- DDR_DRAMTMG14
- DDR_ODTCFG
- >;
-
- st,ctl-map = <
- DDR_ADDRMAP1
- DDR_ADDRMAP2
- DDR_ADDRMAP3
- DDR_ADDRMAP4
- DDR_ADDRMAP5
- DDR_ADDRMAP6
- DDR_ADDRMAP9
- DDR_ADDRMAP10
- DDR_ADDRMAP11
- >;
-
- st,ctl-perf = <
- DDR_SCHED
- DDR_SCHED1
- DDR_PERFHPR1
- DDR_PERFLPR1
- DDR_PERFWR1
- DDR_PCFGR_0
- DDR_PCFGW_0
- DDR_PCFGQOS0_0
- DDR_PCFGQOS1_0
- DDR_PCFGWQOS0_0
- DDR_PCFGWQOS1_0
-#if STM32MP_DDR_DUAL_AXI_PORT
- DDR_PCFGR_1
- DDR_PCFGW_1
- DDR_PCFGQOS0_1
- DDR_PCFGQOS1_1
- DDR_PCFGWQOS0_1
- DDR_PCFGWQOS1_1
-#endif
- >;
-
- st,phy-reg = <
- DDR_PGCR
- DDR_ACIOCR
- DDR_DXCCR
- DDR_DSGCR
- DDR_DCR
- DDR_ODTCR
- DDR_ZQ0CR1
- DDR_DX0GCR
- DDR_DX1GCR
-#if STM32MP_DDR_DUAL_AXI_PORT
- DDR_DX2GCR
- DDR_DX3GCR
-#endif
- >;
-
- st,phy-timing = <
- DDR_PTR0
- DDR_PTR1
- DDR_PTR2
- DDR_DTPR0
- DDR_DTPR1
- DDR_DTPR2
- DDR_MR0
- DDR_MR1
- DDR_MR2
- DDR_MR3
- >;
+ st,phy-timing = <
+ DDR_PTR0
+ DDR_PTR1
+ DDR_PTR2
+ DDR_DTPR0
+ DDR_DTPR1
+ DDR_DTPR2
+ DDR_MR0
+ DDR_MR1
+ DDR_MR2
+ DDR_MR3
+ >;
#ifdef DDR_PHY_CAL_SKIP
- st,phy-cal = <
- DDR_DX0DLLCR
- DDR_DX0DQTR
- DDR_DX0DQSTR
- DDR_DX1DLLCR
- DDR_DX1DQTR
- DDR_DX1DQSTR
-#if STM32MP_DDR_DUAL_AXI_PORT
- DDR_DX2DLLCR
- DDR_DX2DQTR
- DDR_DX2DQSTR
- DDR_DX3DLLCR
- DDR_DX3DQTR
- DDR_DX3DQSTR
+ st,phy-cal = <
+ DDR_DX0DLLCR
+ DDR_DX0DQTR
+ DDR_DX0DQSTR
+ DDR_DX1DLLCR
+ DDR_DX1DQTR
+ DDR_DX1DQSTR
+ DDR_DX2DLLCR
+ DDR_DX2DQTR
+ DDR_DX2DQSTR
+ DDR_DX3DLLCR
+ DDR_DX3DQTR
+ DDR_DX3DQSTR
+ >;
#endif
- >;
-#endif
-
- status = "okay";
- };
- };
};
diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
index 127053b86a..6ca6293d4c 100644
--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
@@ -15,7 +15,7 @@
* Save Date: 2020.02.20, save Time: 18:45:20
*/
-#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000Khz"
+#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000kHz"
#define DDR_MEM_SPEED 533000
#define DDR_MEM_SIZE 0x20000000
@@ -61,13 +61,13 @@
#define DDR_DBGCMD 0x00000000
#define DDR_POISONCFG 0x00000000
#define DDR_PCCFG 0x00000010
-#define DDR_PCFGR_0 0x00000000
+#define DDR_PCFGR_0 0x00010000
#define DDR_PCFGW_0 0x00000000
#define DDR_PCFGQOS0_0 0x02100C03
#define DDR_PCFGQOS1_0 0x00800100
#define DDR_PCFGWQOS0_0 0x01100C03
#define DDR_PCFGWQOS1_0 0x01000200
-#define DDR_PCFGR_1 0x00000000
+#define DDR_PCFGR_1 0x00010000
#define DDR_PCFGW_1 0x00000000
#define DDR_PCFGQOS0_1 0x02100C03
#define DDR_PCFGQOS1_1 0x00800040
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
index 5ae861fee1..548f69a197 100644
--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -15,7 +15,7 @@
* Save Date: 2020.02.20, save Time: 18:49:33
*/
-#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000Khz"
+#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000kHz"
#define DDR_MEM_SPEED 533000
#define DDR_MEM_SIZE 0x40000000
@@ -61,13 +61,13 @@
#define DDR_DBGCMD 0x00000000
#define DDR_POISONCFG 0x00000000
#define DDR_PCCFG 0x00000010
-#define DDR_PCFGR_0 0x00000000
+#define DDR_PCFGR_0 0x00010000
#define DDR_PCFGW_0 0x00000000
#define DDR_PCFGQOS0_0 0x02100C03
#define DDR_PCFGQOS1_0 0x00800100
#define DDR_PCFGWQOS0_0 0x01100C03
#define DDR_PCFGWQOS1_0 0x01000200
-#define DDR_PCFGR_1 0x00000000
+#define DDR_PCFGR_1 0x00010000
#define DDR_PCFGW_1 0x00000000
#define DDR_PCFGQOS0_1 0x02100C03
#define DDR_PCFGQOS1_1 0x00800040
diff --git a/fdts/stm32mp15-ddr-1g-fw-config.dts b/fdts/stm32mp15-fw-config.dts
similarity index 60%
rename from fdts/stm32mp15-ddr-1g-fw-config.dts
rename to fdts/stm32mp15-fw-config.dts
index c871463062..f5c4972061 100644
--- a/fdts/stm32mp15-ddr-1g-fw-config.dts
+++ b/fdts/stm32mp15-fw-config.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
*/
#include <platform_def.h>
@@ -8,6 +8,21 @@
#include <common/tbbr/tbbr_img_def.h>
#include <dt-bindings/soc/stm32mp1-tzc400.h>
+#ifndef DDR_SIZE
+#error "DDR_SIZE is not defined"
+#endif
+
+#define DDR_NS_BASE STM32MP_DDR_BASE
+#ifdef AARCH32_SP_OPTEE
+#define DDR_SHARE_SIZE 0x00200000
+#define DDR_SHARE_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE))
+#define DDR_SEC_SIZE 0x01e00000
+#define DDR_SEC_BASE (DDR_SHARE_BASE - DDR_SEC_SIZE)
+#define DDR_NS_SIZE (DDR_SEC_BASE - DDR_NS_BASE)
+#else
+#define DDR_NS_SIZE DDR_SIZE
+#endif
+
/dts-v1/;
/ {
@@ -51,13 +66,13 @@
compatible = "st,mem-firewall";
#ifdef AARCH32_SP_OPTEE
memory-ranges = <
- 0xc0000000 0x3e000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR
- 0xfe000000 0x01e00000 TZC_REGION_S_RDWR 0
- 0xffe00000 0x00200000 TZC_REGION_S_NONE
+ DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR
+ DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0
+ DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>;
#else
memory-ranges = <
- 0xc0000000 0x40000000 TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>;
+ DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>;
#endif
};
};
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index 714d94710f..90b93387a6 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -382,6 +382,24 @@
secure-status = "disabled";
};
+ ddr: ddr@5a003000{
+ compatible = "st,stm32mp1-ddr";
+ reg = <0x5A003000 0x550 0x5A004000 0x234>;
+ clocks = <&rcc AXIDCG>,
+ <&rcc DDRC1>,
+ <&rcc DDRC2>,
+ <&rcc DDRPHYC>,
+ <&rcc DDRCAPB>,
+ <&rcc DDRPHYCAPB>;
+ clock-names = "axidcg",
+ "ddrc1",
+ "ddrc2",
+ "ddrphyc",
+ "ddrcapb",
+ "ddrphycapb";
+ status = "okay";
+ };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/fdts/stm32mp157a-avenger96-fw-config.dts b/fdts/stm32mp157a-avenger96-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157a-avenger96-fw-config.dts
+++ b/fdts/stm32mp157a-avenger96-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157a-dk1-fw-config.dts b/fdts/stm32mp157a-dk1-fw-config.dts
index 256d0db935..d2be11aab2 100644
--- a/fdts/stm32mp157a-dk1-fw-config.dts
+++ b/fdts/stm32mp157a-dk1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-512m-fw-config.dts"
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157a-ed1-fw-config.dts b/fdts/stm32mp157a-ed1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157a-ed1-fw-config.dts
+++ b/fdts/stm32mp157a-ed1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157a-ev1-fw-config.dts b/fdts/stm32mp157a-ev1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157a-ev1-fw-config.dts
+++ b/fdts/stm32mp157a-ev1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157c-dk2-fw-config.dts b/fdts/stm32mp157c-dk2-fw-config.dts
index 256d0db935..d2be11aab2 100644
--- a/fdts/stm32mp157c-dk2-fw-config.dts
+++ b/fdts/stm32mp157c-dk2-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-512m-fw-config.dts"
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157c-ed1-fw-config.dts b/fdts/stm32mp157c-ed1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157c-ed1-fw-config.dts
+++ b/fdts/stm32mp157c-ed1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157c-ev1-fw-config.dts b/fdts/stm32mp157c-ev1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157c-ev1-fw-config.dts
+++ b/fdts/stm32mp157c-ev1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157d-dk1-fw-config.dts b/fdts/stm32mp157d-dk1-fw-config.dts
index 256d0db935..d2be11aab2 100644
--- a/fdts/stm32mp157d-dk1-fw-config.dts
+++ b/fdts/stm32mp157d-dk1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-512m-fw-config.dts"
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157d-ed1-fw-config.dts b/fdts/stm32mp157d-ed1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157d-ed1-fw-config.dts
+++ b/fdts/stm32mp157d-ed1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157d-ev1-fw-config.dts b/fdts/stm32mp157d-ev1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157d-ev1-fw-config.dts
+++ b/fdts/stm32mp157d-ev1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157f-dk2-fw-config.dts b/fdts/stm32mp157f-dk2-fw-config.dts
index 256d0db935..d2be11aab2 100644
--- a/fdts/stm32mp157f-dk2-fw-config.dts
+++ b/fdts/stm32mp157f-dk2-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-512m-fw-config.dts"
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157f-ed1-fw-config.dts b/fdts/stm32mp157f-ed1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157f-ed1-fw-config.dts
+++ b/fdts/stm32mp157f-ed1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp157f-ev1-fw-config.dts b/fdts/stm32mp157f-ev1-fw-config.dts
index 10f9402c4a..275406410e 100644
--- a/fdts/stm32mp157f-ev1-fw-config.dts
+++ b/fdts/stm32mp157f-ev1-fw-config.dts
@@ -3,4 +3,5 @@
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*/
-#include "stm32mp15-ddr-1g-fw-config.dts"
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dts"
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index e5166706ee..fa1a4baaca 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -134,14 +134,15 @@
vtt_ddr: ldo3 {
regulator-name = "vtt_ddr";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <750000>;
regulator-always-on;
regulator-over-current-protection;
+ st,regulator-sink-source;
};
vdd_usb: ldo4 {
regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
};
vdda: ldo5 {
@@ -161,7 +162,6 @@
vref_ddr: vref_ddr {
regulator-name = "vref_ddr";
regulator-always-on;
- regulator-over-current-protection;
};
bst_out: boost {
@@ -254,7 +254,7 @@
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
- CLK_ETH_DISABLED
+ CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi
index 540f5b9d97..cccf3e3595 100644
--- a/fdts/stm32mp15xx-edx.dtsi
+++ b/fdts/stm32mp15xx-edx.dtsi
@@ -136,14 +136,15 @@
vtt_ddr: ldo3 {
regulator-name = "vtt_ddr";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <750000>;
regulator-always-on;
regulator-over-current-protection;
+ st,regulator-sink-source;
};
vdd_usb: ldo4 {
regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
};
vdd_sd: ldo5 {
@@ -162,7 +163,6 @@
vref_ddr: vref_ddr {
regulator-name = "vref_ddr";
regulator-always-on;
- regulator-over-current-protection;
};
bst_out: boost {
@@ -256,7 +256,7 @@
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
- CLK_ETH_DISABLED
+ CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S
index 6bbcde2e0a..ed4ca273e9 100644
--- a/include/arch/aarch32/el3_common_macros.S
+++ b/include/arch/aarch32/el3_common_macros.S
@@ -351,10 +351,21 @@
* includes the data and NOBITS sections. This is done to
* safeguard against possible corruption of this memory by
* dirty cache lines in a system cache as a result of use by
- * an earlier boot loader stage.
+ * an earlier boot loader stage. If PIE is enabled however,
+ * RO sections including the GOT may be modified during
+ * pie fixup. Therefore, to be on the safe side, invalidate
+ * the entire image region if PIE is enabled.
* -----------------------------------------------------------------
*/
+#if ENABLE_PIE
+#if SEPARATE_CODE_AND_RODATA
+ ldr r0, =__TEXT_START__
+#else
+ ldr r0, =__RO_START__
+#endif /* SEPARATE_CODE_AND_RODATA */
+#else
ldr r0, =__RW_START__
+#endif /* ENABLE_PIE */
ldr r1, =__RW_END__
sub r1, r1, r0
bl inv_dcache_range
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 6f4143c5f5..20adcac2fd 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -375,11 +375,24 @@
* includes the data and NOBITS sections. This is done to
* safeguard against possible corruption of this memory by
* dirty cache lines in a system cache as a result of use by
- * an earlier boot loader stage.
+ * an earlier boot loader stage. If PIE is enabled however,
+ * RO sections including the GOT may be modified during
+ * pie fixup. Therefore, to be on the safe side, invalidate
+ * the entire image region if PIE is enabled.
* -------------------------------------------------------------
*/
+#if ENABLE_PIE
+#if SEPARATE_CODE_AND_RODATA
+ adrp x0, __TEXT_START__
+ add x0, x0, :lo12:__TEXT_START__
+#else
+ adrp x0, __RO_START__
+ add x0, x0, :lo12:__RO_START__
+#endif /* SEPARATE_CODE_AND_RODATA */
+#else
adrp x0, __RW_START__
add x0, x0, :lo12:__RW_START__
+#endif /* ENABLE_PIE */
adrp x1, __RW_END__
add x1, x1, :lo12:__RW_END__
sub x1, x1, x0
diff --git a/include/drivers/regulator.h b/include/drivers/regulator.h
new file mode 100644
index 0000000000..392051f96e
--- /dev/null
+++ b/include/drivers/regulator.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef REGULATOR_H
+#define REGULATOR_H
+
+#include <platform_def.h>
+
+#ifndef PLAT_NB_RDEVS
+#error "Missing PLAT_NB_RDEVS"
+#endif
+
+#ifndef PLAT_NB_SUSPEND_MODES
+#error "Missing PLAT_NB_SUSPEND_MODES"
+#endif
+
+const char *plat_get_lp_mode_name(int mode);
+
+/*
+ * Consumer interface
+ */
+
+/* regulator-always-on : regulator should never be disabled */
+#define REGUL_ALWAYS_ON BIT(0)
+/*
+ * regulator-boot-on:
+ * It's expected that this regulator was left on by the bootloader.
+ * The core shouldn't prevent it from being turned off later.
+ * The regulator is needed to exit from suspend so it is turned on during suspend entry.
+ */
+#define REGUL_BOOT_ON BIT(1)
+/* regulator-over-current-protection: Enable over current protection. */
+#define REGUL_OCP BIT(2)
+/* regulator-active-discharge: enable active discharge. */
+#define REGUL_ACTIVE_DISCHARGE BIT(3)
+/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */
+#define REGUL_PULL_DOWN BIT(4)
+/*
+ * st,mask-reset: set mask reset for the regulator, meaning that the regulator
+ * setting is maintained during pmic reset.
+ */
+#define REGUL_MASK_RESET BIT(5)
+/* st,regulator-sink-source: set the regulator in sink source mode */
+#define REGUL_SINK_SOURCE BIT(6)
+/* st,regulator-bypass: set the regulator in bypass mode */
+#define REGUL_ENABLE_BYPASS BIT(7)
+
+struct rdev *regulator_get_by_name(const char *node_name);
+
+#if defined(IMAGE_BL32)
+struct rdev *regulator_get_by_regulator_name(const char *reg_name);
+#endif
+
+struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name);
+
+int regulator_enable(struct rdev *rdev);
+int regulator_disable(struct rdev *rdev);
+int regulator_is_enabled(const struct rdev *rdev);
+
+int regulator_set_voltage(struct rdev *rdev, uint16_t volt);
+int regulator_set_min_voltage(struct rdev *rdev);
+int regulator_get_voltage(const struct rdev *rdev);
+
+int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count);
+void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv);
+int regulator_set_flag(struct rdev *rdev, uint16_t flag);
+
+/*
+ * Driver Interface
+ */
+
+/* set_state() arguments */
+#define STATE_DISABLE false
+#define STATE_ENABLE true
+
+/* suspend() arguments */
+#define LP_STATE_OFF BIT(0)
+#define LP_STATE_ON BIT(1)
+#define LP_STATE_UNCHANGED BIT(2)
+#define LP_STATE_SET_VOLT BIT(3)
+
+struct regul_description {
+ const char *node_name;
+ const struct regul_ops *ops;
+ const void *driver_data;
+ const char *supply_name;
+ const uint32_t enable_ramp_delay;
+};
+
+struct regul_ops {
+ int (*set_state)(const struct regul_description *desc, bool state);
+ int (*get_state)(const struct regul_description *desc);
+ int (*set_voltage)(const struct regul_description *desc, uint16_t mv);
+ int (*get_voltage)(const struct regul_description *desc);
+ int (*list_voltages)(const struct regul_description *desc,
+ const uint16_t **levels, size_t *count);
+ int (*set_flag)(const struct regul_description *desc, uint16_t flag);
+#if defined(IMAGE_BL32)
+ void (*lock)(const struct regul_description *desc);
+ void (*unlock)(const struct regul_description *desc);
+ int (*suspend)(const struct regul_description *desc, uint8_t state,
+ uint16_t mv);
+#endif
+};
+
+int regulator_register(const struct regul_description *desc, int node);
+
+/*
+ * Internal regulator structure
+ * The structure is internal to the core, and the content should not be used
+ * by a consumer nor a driver.
+ */
+struct rdev {
+ const struct regul_description *desc;
+
+ int32_t phandle;
+
+ uint16_t min_mv;
+ uint16_t max_mv;
+
+ uint16_t flags;
+
+ uint32_t enable_ramp_delay;
+#if defined(IMAGE_BL32)
+ const char *reg_name;
+
+ uint8_t use_count;
+
+ int32_t supply_phandle;
+ struct rdev *supply_dev;
+
+ uint8_t lp_state[PLAT_NB_SUSPEND_MODES];
+ uint16_t lp_mv[PLAT_NB_SUSPEND_MODES];
+#endif
+};
+
+#if defined(IMAGE_BL32)
+
+/* Boot and init */
+int regulator_core_config(void);
+int regulator_core_cleanup(void);
+
+/* Suspend resume operations */
+#define PLAT_BACKUP_REGULATOR_SIZE (sizeof(int8_t) * PLAT_NB_RDEVS)
+
+int regulator_core_suspend(int mode);
+int regulator_core_resume(void);
+
+void regulator_core_backup_context(void *backup_area, size_t backup_size);
+void regulator_core_restore_context(void *backup_area, size_t backup_size);
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+void regulator_core_dump(void);
+#endif
+
+#endif
+
+#endif /* REGULATOR_H */
diff --git a/include/drivers/st/regulator_fixed.h b/include/drivers/st/regulator_fixed.h
new file mode 100644
index 0000000000..b03c6e38c6
--- /dev/null
+++ b/include/drivers/st/regulator_fixed.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef REGULATOR_FIXED_H
+#define REGULATOR_FIXED_H
+
+int fixed_regulator_register(void);
+
+#endif /* REGULATOR_FIXED_H */
diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h
index e241f584f7..b072345159 100644
--- a/include/drivers/st/stm32_gpio.h
+++ b/include/drivers/st/stm32_gpio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -52,6 +52,7 @@ int dt_set_pinctrl_config(int node);
void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
uint32_t pull, uint32_t alternate, uint8_t status);
void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure);
+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin);
#endif /*__ASSEMBLER__*/
#endif /* STM32_GPIO_H */
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
index 5b4bd0e167..af02b91ea5 100644
--- a/include/drivers/st/stm32_sdmmc2.h
+++ b/include/drivers/st/stm32_sdmmc2.h
@@ -10,7 +10,7 @@
#include <stdbool.h>
#include <drivers/mmc.h>
-#include <drivers/st/stm32mp_regulator.h>
+#include <drivers/regulator.h>
struct stm32_sdmmc2_params {
uintptr_t reg_base;
@@ -25,7 +25,7 @@ struct stm32_sdmmc2_params {
unsigned int reset_id;
unsigned int max_freq;
bool use_dma;
- struct stm32mp_regulator vmmc_regu;
+ struct rdev *vmmc_regu;
};
unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
diff --git a/include/drivers/st/stm32_tamp.h b/include/drivers/st/stm32_tamp.h
index 424cbb205a..11dc96df69 100644
--- a/include/drivers/st/stm32_tamp.h
+++ b/include/drivers/st/stm32_tamp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,22 +9,22 @@
/* Internal Tamper */
enum stm32_tamp_int_id {
- ITAMP1 = 0,
- ITAMP2,
- ITAMP3,
- ITAMP4,
- ITAMP5,
- ITAMP6,
- ITAMP7,
- ITAMP8,
- ITAMP9,
- ITAMP10,
- ITAMP11,
- ITAMP12,
- ITAMP13,
- ITAMP14,
- ITAMP15,
- ITAMP16
+ INT_TAMP1 = 0,
+ INT_TAMP2,
+ INT_TAMP3,
+ INT_TAMP4,
+ INT_TAMP5,
+ INT_TAMP6,
+ INT_TAMP7,
+ INT_TAMP8,
+ INT_TAMP9,
+ INT_TAMP10,
+ INT_TAMP11,
+ INT_TAMP12,
+ INT_TAMP13,
+ INT_TAMP14,
+ INT_TAMP15,
+ INT_TAMP16
};
/* External Tamper */
@@ -39,95 +39,111 @@ enum stm32_tamp_ext_id {
EXT_TAMP8
};
-enum stm32_tamp_state {
- TAMP_DISABLE = 0,
- TAMP_ENABLE
+/* Out pin to compare for external Tamper */
+enum stm32_tamp_ext_out_id {
+ TAMPOUTSEL_SAME_AS_INPUT = 0,
+ TAMPOUTSEL1 = 1,
+ TAMPOUTSEL2,
+ TAMPOUTSEL3,
+ TAMPOUTSEL4,
+ TAMPOUTSEL5,
+ TAMPOUTSEL6,
+ TAMPOUTSEL7,
+ TAMPOUTSEL8,
};
-#define TAMP_UNUSED {.id = -1}
+/* Define number of backup registers in zone 1 and zone 2 (remaining are in
+ * zone 3)
+ *
+ * backup registers in zone 1 : read/write only in secure mode
+ * zone 2 : write only in secure mode, read in secure
+ * and non-secure mode
+ * zone 3 : read/write in secure and non-secure mode
+ *
+ * Protection zone 1 if nb_zone1_regs == 0 no backup register are in zone 1
+ * else backup registers from TAMP_BKP0R to TAMP_BKPxR
+ * with x = nb_zone1_regs - 1 are in zone 1.
+ * Protection zone 2 if nb_zone2_regs == 0 no backup register are in zone 2
+ * else backup registers from TAMP_BKPyR with y = nb_zone1_regs
+ * to TAMP_BKPzR with z = (nb_zone1_regs1 + nb_zone2_regs - 1)
+ * are in zone 2.
+ * Protection zone 3 backup registers from TAMP_BKPtR
+ * with t = nb_zone1_regs1 + nb_zone2_regs to last backup
+ * register are in zone 3.
+ */
+struct bkpregs_conf {
+ uint32_t nb_zone1_regs;
+ uint32_t nb_zone2_regs;
+};
-/* define TAMPER modes */
+/* Define TAMPER modes */
+#define TAMP_DISABLE 0x0U
+#define TAMP_ENABLE 0x1U
#define TAMP_TRIG_OFF 0x0U
-#define TAMP_TRIG_ON 0x1U
-#define TAMP_ACTIVE 0x2U
+#define TAMP_TRIG_ON 0x2U
+#define TAMP_ACTIVE 0x4U
#define TAMP_ERASE 0x0U
-#define TAMP_NOERASE 0x1U
+#define TAMP_NOERASE 0x8U
#define TAMP_NO_EVT_MASK 0x0U
-#define TAMP_EVT_MASK 0x1U
-
-/* define Passive FILTER mode */
-#define TAMP_FILTER_PRECHARGE 0x0U
-#define TAMP_FILTER_PULL_UP_DISABLE 0x1U
-#define TAMP_FILTER_DURATION_1_CYCLE 0x0U
-#define TAMP_FILTER_DURATION_2_CYCLES 0x1U
-#define TAMP_FILTER_DURATION_3_CYCLES 0x2U
-#define TAMP_FILTER_DURATION_4_CYCLES 0x3U
-#define TAMP_FILTER_COUNT_1 0x0U
-#define TAMP_FILTER_COUNT_2 0x1U
-#define TAMP_FILTER_COUNT_4 0x2U
-#define TAMP_FILTER_COUNT_8 0x3U
-#define TAMP_FILTER_SAMPLING_32768 0x0U
-#define TAMP_FILTER_SAMPLING_16384 0x1U
-#define TAMP_FILTER_SAMPLING_8192 0x2U
-#define TAMP_FILTER_SAMPLING_4096 0x3U
-#define TAMP_FILTER_SAMPLING_2048 0x4U
-#define TAMP_FILTER_SAMPLING_1024 0x5U
-#define TAMP_FILTER_SAMPLING_512 0x6U
-#define TAMP_FILTER_SAMPLING_256 0x7U
-
-/* define active filter */
-#define TAMP_ACTIVE_FILTER_OFF 0x0U
-#define TAMP_ACTIVE_FILTER_ON 0x1U
-#define TAMP_ACTIVE_ATO_DEDICATED 0x0U
-#define TAMP_ACTIVE_ATO_TAMPOUTSEL 0x1U
-#define TAMP_ACTIVE_APER_1_OUTPUT 0x0U
-#define TAMP_ACTIVE_APER_2_OUTPUTS 0x1U
-#define TAMP_ACTIVE_APER_3_4_OUTPUTS 0x2U
-#define TAMP_ACTIVE_APER_5_OUTPUTS 0x3U
-#define TAMP_ACTIVE_CKSEL_DIV_0 0x0U
-#define TAMP_ACTIVE_CKSEL_DIV_2 0x1U
-#define TAMP_ACTIVE_CKSEL_DIV_4 0x2U
-#define TAMP_ACTIVE_CKSEL_DIV_8 0x3U
-#define TAMP_ACTIVE_CKSEL_DIV_16 0x4U
-#define TAMP_ACTIVE_CKSEL_DIV_32 0x5U
-#define TAMP_ACTIVE_CKSEL_DIV_64 0x6U
-#define TAMP_ACTIVE_CKSEL_DIV_128 0x7U
-#define TAMP_ACTIVE_ATOSEL_OUT1_(X) (0x0U << ((X) * 2))
-#define TAMP_ACTIVE_ATOSEL_OUT2_(X) (0x1U << ((X) * 2))
-#define TAMP_ACTIVE_ATOSEL_OUT3_(X) (0x2U << ((X) * 2))
-#define TAMP_ACTIVE_ATOSEL_OUT4_(X) (0x3U << ((X) * 2))
-
-#define TAMP_EXT(tamp_id, trig, erase, mask) (((tamp_id) << 3) | ((trig) << 2)\
- | ((erase) << 1) | (mask))
-
-#define TAMP_FLTCR(precharge, duration, count, sample) (((precharge) << 7) |\
- ((duration) << 5) |\
- ((count) << 3) |\
- (sample))
-
-#define TAMP_ACT(filter, ato, aper, atcksel, atosel) (((filter) << 31) |\
- ((ato) << 30) |\
- ((aper) << 24) |\
- ((atcksel) << 16) |\
- (atosel) << 8)
-
-struct stm32_tamp_int {
- int id;
- void (*func)(int id);
-};
-
-struct stm32_tamp_ext {
- int id;
- uint8_t mode;
- uint8_t erase;
- uint8_t evt_mask;
- void (*func)(int id);
-};
+#define TAMP_EVT_MASK 0x10U
+
+/* Define Passive FILTER mode */
+#define TAMP_FILTER_TAMPPUDIS_OFFSET 7U
+#define TAMP_FILTER_PRECHARGE (0x0U << TAMP_FILTER_TAMPPUDIS_OFFSET)
+#define TAMP_FILTER_PULL_UP_DISABLE (0x1U << TAMP_FILTER_TAMPPUDIS_OFFSET)
+#define TAMP_FILTER_TAMPPRCH_OFFSET 5U
+#define TAMP_FILTER_DURATION_1_CYCLE (0x0U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_DURATION_2_CYCLES (0x1U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_DURATION_4_CYCLES (0x2U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_DURATION_8_CYCLES (0x3U << TAMP_FILTER_TAMPPRCH_OFFSET)
+#define TAMP_FILTER_TAMPFLT_OFFSET 3U
+#define TAMP_FILTER_COUNT_1 (0x0U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_COUNT_2 (0x1U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_COUNT_4 (0x2U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_COUNT_8 (0x3U << TAMP_FILTER_TAMPFLT_OFFSET)
+#define TAMP_FILTER_TAMPFREQ_OFFSET 0U
+#define TAMP_FILTER_SAMPLING_32768 (0x0U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_16384 (0x1U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_8192 (0x2U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_4096 (0x3U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_2048 (0x4U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_1024 (0x5U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_512 (0x6U << TAMP_FILTER_TAMPFREQ_OFFSET)
+#define TAMP_FILTER_SAMPLING_256 (0x7U << TAMP_FILTER_TAMPFREQ_OFFSET)
+
+/* Define active filter */
+#define TAMP_ACTIVE_FLTEN_OFFSET 31U
+#define TAMP_ACTIVE_FILTER_OFF (0x0U << TAMP_ACTIVE_FLTEN_OFFSET)
+#define TAMP_ACTIVE_FILTER_ON (0x1U << TAMP_ACTIVE_FLTEN_OFFSET)
+#define TAMP_FILTER_ATOSHARE_OFFSET 30U
+#define TAMP_FILTER_USE_DEDICATED_OUT (0x0U << TAMP_FILTER_ATOSHARE_OFFSET)
+#define TAMP_FILTER_SELECT_OUT (0x1U << TAMP_FILTER_ATOSHARE_OFFSET)
+#define TAMP_ACTIVE_ATPER_OFFSET 24U
+#define TAMP_ACTIVE_ATPER_1_OUTPUT (0x0U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_2_OUTPUTS (0x1U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_3_4_OUTPUTS (0x2U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATPER_5_OUTPUTS (0x3U << TAMP_ACTIVE_ATPER_OFFSET)
+#define TAMP_ACTIVE_ATCKSEL_OFFSET 16U
+#define TAMP_ACTIVE_CKSEL_DIV_0 (0x0U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_2 (0x1U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_4 (0x2U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_8 (0x3U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_16 (0x4U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_32 (0x5U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_64 (0x6U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+#define TAMP_ACTIVE_CKSEL_DIV_128 (0x7U << TAMP_ACTIVE_ATCKSEL_OFFSET)
+
+/* Define secure mode acces */
+/* Tamper configuration and interrupt can be written when the APB access is secure or nonsecure.*/
+#define TAMP_REGS_IT_UNSECURE 0U
+/* Tamper configuration and interrupt can be written only when the APB access is secure.*/
+#define TAMP_REGS_IT_SECURE BIT(31)
/*
- * stm32_tamp_write_mcounter : Increase monotonic counter
+ * stm32_tamp_write_mcounter : Increase monotonic counter[counter_idx]
*/
-void stm32_tamp_write_mcounter(void);
+int stm32_tamp_write_mcounter(int counter_idx);
+uint32_t stm32_tamp_read_mcounter(int counter_idx);
/*
* stm32_tamp_it_handler : Interrupt handler
@@ -135,24 +151,69 @@ void stm32_tamp_write_mcounter(void);
void stm32_tamp_it_handler(void);
/*
- * stm32_tamp_configure_internal: Configure internal tamper
- * tamper_list: List of tamper to enable
- * nb_tamper: Number of tamper in list
+ * stm32_tamp_configure_secure_access: Configure which registers can be
+ * read/write from unsecure world
+ * secure_conf is a bit field from TAMP_.*_{UN,}SECURE define
+ */
+void stm32_tamp_configure_secure_access(uint32_t secure_conf);
+
+/*
+ * stm32_tamp_configure_privilege_access: Configure which registers can be
+ * read/write from unpriviliged world
+ * privilege_conf is a bit field from TAMP_.*_{UN,}PRIVILEGE define
+ */
+void stm32_tamp_configure_privilege_access(uint32_t privilege_conf);
+
+/*
+ * stm32_tamp_configure_passive: Configure passive mode
+ * passive_conf is a bit field from TAMP_FILTER_* define
+ */
+void stm32_tamp_configure_passive(uint32_t passive_conf);
+
+/*
+ * stm32_tamp_configure_ctive: Configure active mode
+ * passive_conf is a bit field from TAMP_ACTIVE_* define
+ */
+void stm32_tamp_configure_active(uint32_t active_conf);
+
+/*
+ * stm32_tamp_configure_internal: Configure one internal tamper
+ * id: internal tamper id
+ * mode: bitmask from TAMPER modes define
+ * callback: function to call when tamper is raised (can be NULL),
+ * called in interrupt context,
+ * if callback returns negative value, blocked secrets stay blocked
+ * (driver doesn't release this specific tamper).
+ * if callback returns 0 this specific tamp is ack (in case of no-erase
+ * tamper, blocked secret are unblocked)
+ * if callback returns positive value, this specific tamp is ack (in
+ * case of no-erase tamper, blocked secret are unblocked) and system is
+ * rebooted).
+ *
+ * return: -EINVAL if 'id' is not a valid internal tamp id, else 0
*/
-void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list,
- uint16_t nb_tamper);
+int stm32_tamp_configure_internal(enum stm32_tamp_int_id id, uint32_t mode,
+ int (*callback)(int id));
/*
- * stm32_tamp_configure_external: Configure external tamper and associated
- * configuration for filtering
- * ext_tamp_list: List of external tamper to configure
- * nb_tamper: Number of tamper in list
- * passive_conf: Filter configuration
- * active_conf: Configuration for active tamper
+ * stm32_tamp_configure_external: Configure one external tamper
+ * id: external tamper id
+ * mode: bitmask from TAMPER modes define
+ * pin_out; output pin connected to input pin (linekd with selected ext tamp id)
+ * callback: function to call when tamper is raised (can be NULL),
+ * called in interrupt context,
+ * if callback returns negative value, blocked secrets stay blocked
+ * (driver doesn't release this specific tamper).
+ * if callback returns 0 this specific tamp is ack (in case of no-erase
+ * tamper, blocked secret are unblocked)
+ * if callback returns positive value, this specific tamp is ack (in
+ * case of no-erase tamper, blocked secret are unblocked) and system is
+ * rebooted).
+ *
+ * return: -EINVAL if 'id' is not a valid external tamp id, else 0
*/
-void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list,
- uint8_t nb_tamper, uint32_t passive_conf,
- uint32_t active_conf);
+int stm32_tamp_configure_external(enum stm32_tamp_ext_id id, uint32_t mode,
+ enum stm32_tamp_ext_out_id out_pin, int (*callback)(int id));
/*
* stm32_tamp_init: Initialize tamper from DT
@@ -160,4 +221,32 @@ void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list,
*/
int stm32_tamp_init(void);
+/*
+ * stm32_tamp_set_secure_bkprwregs : Configure backup registers zone.
+ * registers in zone 1 : read/write only in secure mode
+ * zone 2 : write only in secure mode, read in secure and non-secure mode
+ * zone 3 : read/write in secure and non-secure mode
+ *
+ * bkpregs_conf : a pointer to struct bkpregs_conf that define the number of registers in zone 1
+ * and zone 2 (remaining backup registers will be in zone 3).
+ *
+ * return 0 if OK, -ENODEV if zone 1 and/or zone 2 definition are out of range.
+ */
+int stm32_tamp_set_secure_bkpregs(struct bkpregs_conf *bkpregs_conf);
+
+/*
+ * stm32_tamp_set_config: apply configuration
+ * default one if no previous call to any of :
+ * stm32_tamp_configure_passive()
+ * stm32_tamp_configure_active()
+ * stm32_tamp_configure_internal()
+ * stm32_tamp_configure_external()
+ * stm32_tamp_configure_secret_list()
+ * stm32_tamp_configure_secure_access()
+ * stm32_tamp_configure_privilige_access()
+ *
+ * return: < 0 if unable to apply configuration, else 0
+ */
+int stm32_tamp_set_config(void);
+
#endif /* STM32_TAMP_H */
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
index e298fcf77b..1ccefc4fca 100644
--- a/include/drivers/st/stm32mp1_ddr_regs.h
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
@@ -361,6 +361,7 @@ struct stm32mp1_ddrphy {
#define DDRPHYC_PIR_DRAMRST BIT(5)
#define DDRPHYC_PIR_DRAMINIT BIT(6)
#define DDRPHYC_PIR_QSTRN BIT(7)
+#define DDRPHYC_PIR_RVTRN BIT(8)
#define DDRPHYC_PIR_ICPC BIT(16)
#define DDRPHYC_PIR_ZCALBYP BIT(30)
#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7)
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index 616051e772..ec6b485046 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -306,6 +306,8 @@
/* Fields of RCC_RDLSICR register */
#define RCC_RDLSICR_LSION BIT(0)
#define RCC_RDLSICR_LSIRDY BIT(1)
+#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16)
+#define RCC_RDLSICR_MRD_SHIFT 16
/* Used for all RCC_PLL<n>CR registers */
#define RCC_PLLNCR_PLLON BIT(0)
diff --git a/include/drivers/st/stm32mp_ddr_test.h b/include/drivers/st/stm32mp_ddr_test.h
new file mode 100644
index 0000000000..fe4c8c08e0
--- /dev/null
+++ b/include/drivers/st/stm32mp_ddr_test.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_DDR_TEST_H
+#define STM32MP_DDR_TEST_H
+
+uint32_t stm32mp_ddr_test_rw_access(void);
+uint32_t stm32mp_ddr_test_data_bus(void);
+uint32_t stm32mp_ddr_test_addr_bus(uint64_t size);
+uint32_t stm32mp_ddr_check_size(void);
+
+#endif /* STM32MP_DDR_TEST_H */
diff --git a/include/drivers/st/stm32mp_dummy_regulator.h b/include/drivers/st/stm32mp_dummy_regulator.h
deleted file mode 100644
index 6804192ba0..0000000000
--- a/include/drivers/st/stm32mp_dummy_regulator.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef STM32MP_DUMMY_REGULATOR_H
-#define STM32MP_DUMMY_REGULATOR_H
-
-#include <drivers/st/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 898a28b44c..dd91d5eebc 100644
--- a/include/drivers/st/stm32mp_pmic.h
+++ b/include/drivers/st/stm32mp_pmic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,8 +11,6 @@
#include <platform_def.h>
-#include <drivers/st/stm32mp_regulator.h>
-
/*
* dt_pmic_status - Check PMIC status from device tree
*
@@ -21,31 +19,6 @@
*/
int dt_pmic_status(void);
-/*
- * dt_pmic_configure_boot_on_regulators - Configure boot-on and always-on
- * regulators from device tree configuration
- *
- * Returns 0 on success, and negative values on errors
- */
-int pmic_configure_boot_on_regulators(void);
-
-int pmic_set_lp_config(const char *node_name);
-
-/*
- * dt_pmic_find_supply - Find the supply name related to a regulator name
- *
- * Returns 0 on success, and negative values on errors
- */
-int dt_pmic_find_supply(const char **supply_name, const char *regu_name);
-
-/*
- * pmic_set_regulator_min_voltage - Set target supply to its device tree
- * "regulator-min-microvolt" value.
- *
- * Returns 0 on success, and negative values on errors
- */
-int pmic_set_regulator_min_voltage(const char *regu_name);
-
/*
* initialize_pmic_i2c - Initialize I2C for the PMIC control
*
@@ -60,13 +33,6 @@ bool initialize_pmic_i2c(void);
*/
void initialize_pmic(void);
-/*
- * configure_pmic - PMIC configuration function, called at platform init
- *
- * Panics on errors
- */
-void configure_pmic(void);
-
#if DEBUG
void print_pmic_info_and_debug(void);
#else
@@ -75,9 +41,6 @@ static inline void print_pmic_info_and_debug(void)
}
#endif
-bool is_pmic_regulator(struct stm32mp_regulator *regu);
-void bind_pmic_regulator(struct stm32mp_regulator *regu);
-
/*
* pmic_ddr_power_init - Initialize regulators required for DDR
*
@@ -85,4 +48,11 @@ void bind_pmic_regulator(struct stm32mp_regulator *regu);
*/
int pmic_ddr_power_init(enum ddr_type ddr_type);
+/*
+ * pmic_switch_off - switch off the platform with PMIC
+ *
+ * Panics on errors
+ */
+void pmic_switch_off(void);
+
#endif /* STM32MP_PMIC_H */
diff --git a/include/drivers/st/stm32mp_regulator.h b/include/drivers/st/stm32mp_regulator.h
deleted file mode 100644
index 7a66b97ba7..0000000000
--- a/include/drivers/st/stm32mp_regulator.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 5c8933d84d..4e19ba3e5c 100644
--- a/include/drivers/st/stpmic1.h
+++ b/include/drivers/st/stpmic1.h
@@ -103,6 +103,22 @@
#define BUCK4_PULL_DOWN_SHIFT 6
#define VREF_DDR_PULL_DOWN_SHIFT 4
+/* ICC register */
+#define BUCK1_ICC_SHIFT 0
+#define BUCK2_ICC_SHIFT 1
+#define BUCK3_ICC_SHIFT 2
+#define BUCK4_ICC_SHIFT 3
+#define PWR_SW1_ICC_SHIFT 4
+#define PWR_SW2_ICC_SHIFT 5
+#define BOOST_ICC_SHIFT 6
+
+#define LDO1_ICC_SHIFT 0
+#define LDO2_ICC_SHIFT 1
+#define LDO3_ICC_SHIFT 2
+#define LDO4_ICC_SHIFT 3
+#define LDO5_ICC_SHIFT 4
+#define LDO6_ICC_SHIFT 5
+
/* Buck Mask reset register */
#define BUCK1_MASK_RESET 0
#define BUCK2_MASK_RESET 1
@@ -118,6 +134,10 @@
#define LDO6_MASK_RESET 5
#define VREF_DDR_MASK_RESET 6
+/* LDO3 Special modes */
+#define LDO3_BYPASS BIT(7)
+#define LDO3_DDR_SEL 31U
+
/* Main PMIC Control Register (MAIN_CONTROL_REG) */
#define ICC_EVENT_ENABLED BIT(4)
#define PWRCTRL_POLARITY_HIGH BIT(3)
@@ -145,6 +165,8 @@
/* USB Control Register */
#define BOOST_OVP_DISABLED BIT(7)
#define VBUS_OTG_DETECTION_DISABLED BIT(6)
+#define SW_OUT_DISCHARGE BIT(5)
+#define VBUS_OTG_DISCHARGE BIT(4)
#define OCP_LIMIT_HIGH BIT(3)
#define SWIN_SWOUT_ENABLED BIT(2)
#define USBSW_OTG_SWITCH_ENABLED BIT(1)
@@ -159,9 +181,15 @@ int stpmic1_regulator_enable(const char *name);
int stpmic1_regulator_disable(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_levels_mv(const char *name, const uint16_t **levels,
+ size_t *levels_count);
int stpmic1_regulator_voltage_get(const char *name);
int stpmic1_regulator_pull_down_set(const char *name);
int stpmic1_regulator_mask_reset_set(const char *name);
+int stpmic1_regulator_icc_set(const char *name);
+int stpmic1_regulator_sink_mode_set(const char *name);
+int stpmic1_regulator_bypass_mode_set(const char *name);
+int stpmic1_active_discharge_mode_set(const char *name);
int stpmic1_lp_copy_reg(const char *name);
int stpmic1_lp_reg_on_off(const char *name, uint8_t enable);
int stpmic1_lp_set_mode(const char *name, uint8_t hplp);
diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h
index aa9158cb1b..881159c7fc 100644
--- a/include/dt-bindings/interrupt-controller/arm-gic.h
+++ b/include/dt-bindings/interrupt-controller/arm-gic.h
@@ -1,21 +1,26 @@
-/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
/*
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
* This header provides constants for the ARM GIC.
*/
#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
+#include <dt-bindings/interrupt-controller/irq.h>
+
/* interrupt specifier cell 0 */
#define GIC_SPI 0
#define GIC_PPI 1
-#define IRQ_TYPE_NONE 0
-#define IRQ_TYPE_EDGE_RISING 1
-#define IRQ_TYPE_EDGE_FALLING 2
-#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
-#define IRQ_TYPE_LEVEL_HIGH 4
-#define IRQ_TYPE_LEVEL_LOW 8
+/*
+ * Interrupt specifier cell 2.
+ * The flags in irq.h are valid, plus those below.
+ */
+#define GIC_CPU_MASK_RAW(x) ((x) << 8)
+#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1)
#endif
diff --git a/include/dt-bindings/interrupt-controller/irq.h b/include/dt-bindings/interrupt-controller/irq.h
new file mode 100644
index 0000000000..1ff6681e24
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/irq.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This header provides constants for most IRQ bindings.
+ *
+ * Most IRQ bindings include a flags cell as part of the IRQ specifier.
+ * In most cases, the format of the flags cell uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H
+
+#define IRQ_TYPE_NONE 0
+#define IRQ_TYPE_EDGE_RISING 1
+#define IRQ_TYPE_EDGE_FALLING 2
+#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define IRQ_TYPE_LEVEL_LOW 8
+
+#endif
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index aea975c0ad..1cd8e236cf 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -301,9 +301,9 @@ func fixup_gdt_reloc
cmp r4, r6
blo 2f
- /* Skip adding offset if address is >= upper limit */
+ /* Skip adding offset if address is > upper limit */
cmp r4, r7
- bhs 2f
+ bhi 2f
add r4, r0, r4
str r4, [r3]
diff --git a/licenses/LICENSE.MIT b/licenses/LICENSE.MIT
new file mode 100644
index 0000000000..8aa26455d2
--- /dev/null
+++ b/licenses/LICENSE.MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) [year] [fullname]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index 23794db963..2ea9f627ec 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <arch_helpers.h>
#include <common/debug.h>
+#include <common/desc_image_load.h>
#include <drivers/io/io_block.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_fip.h>
@@ -48,7 +49,7 @@ static uint32_t nand_bkp_offset;
#if STM32MP_SDMMC || STM32MP_EMMC
static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
-static const io_block_dev_spec_t mmc_block_dev_spec = {
+static io_block_dev_spec_t mmc_block_dev_spec = {
/* It's used as temp buffer in block driver */
.buffer = {
.offset = (size_t)&block_buffer,
@@ -412,6 +413,11 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id)
image_block_spec.length = entry->length;
gpt_init_done = true;
+ } else {
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
+ mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
}
break;
diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h
index 947ad43aea..db5dfbf4f4 100644
--- a/plat/st/common/include/stm32cubeprogrammer.h
+++ b/plat/st/common/include/stm32cubeprogrammer.h
@@ -31,9 +31,6 @@
#define NACK_BYTE 0x1FU
#define ABORT 0x5FU
-#define DEVICE_ID_BYTE1 0x05U
-#define DEVICE_ID_BYTE2 0x00U
-
/* Functions provided by plat */
uint8_t usb_dfu_get_phase(uint8_t alt);
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 022e22742a..40291c43ed 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,12 +7,12 @@
#ifndef STM32MP_COMMON_H
#define STM32MP_COMMON_H
-#include <cdefs.h>
#include <stdbool.h>
#include <platform_def.h>
-void __dead2 stm32mp_plat_reset(int cpu);
+#define JEDEC_ST_BKID U(0x0)
+#define JEDEC_ST_MFID U(0x20)
/* Functions to save and get boot context address given by ROM code */
void stm32mp_save_boot_ctx_address(uintptr_t address);
@@ -24,10 +24,6 @@ bool stm32mp_is_single_core(void);
bool stm32mp_is_closed_device(void);
bool stm32mp_is_auth_supported(void);
-const char *stm32mp_get_cpu_supply_name(void);
-const char *stm32mp_get_vdd_supply_name(void);
-const char *stm32mp_get_usb_phy_supply_name(void);
-
/* Return the base address of the DDR controller */
uintptr_t stm32mp_ddrctrl_base(void);
@@ -88,12 +84,15 @@ uintptr_t get_uart_address(uint32_t instance_nb);
uintptr_t stm32_get_gpio_bank_base(unsigned int bank);
unsigned long stm32_get_gpio_bank_clock(unsigned int bank);
uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
+bool stm32_gpio_is_secure_at_reset(unsigned int bank);
/* Return node offset for target GPIO bank ID @bank or a FDT error code */
int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank);
/* Get the chip revision */
-int stm32mp_get_chip_version(uint32_t *chip_version);
+uint32_t stm32mp_get_chip_version(void);
+/* Get the chip device ID */
+uint32_t stm32mp_get_chip_dev_id(void);
/* Get SOC name */
#define STM32_SOC_NAME_SIZE 20
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index 0ff30a3827..0414014c2f 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -44,9 +44,9 @@ 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);
-const char *dt_get_vdd_regulator_name(void);
-const char *dt_get_cpu_regulator_name(void);
-const char *dt_get_usb_phy_regulator_name(void);
+struct rdev *dt_get_vdd_regulator(void);
+struct rdev *dt_get_cpu_regulator(void);
+struct rdev *dt_get_usb_phy_regulator(void);
const char *dt_get_board_model(void);
int fdt_get_gpio_bank_pin_count(unsigned int bank);
diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c
index 3fd16aa39c..7a6e02463f 100644
--- a/plat/st/common/stm32cubeprogrammer_uart.c
+++ b/plat/st/common/stm32cubeprogrammer_uart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -203,13 +203,20 @@ static int get_version_command(void)
static int get_id_command(void)
{
- const uint8_t msg[3] = {
- sizeof(msg) - 1,
- DEVICE_ID_BYTE1,
- DEVICE_ID_BYTE2
- };
+ uint32_t id = stm32mp_get_chip_dev_id();
+ int ret;
+
+ ret = uart_write_8(2U); /* Length of command */
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = uart_write_8((id & 0xFF00) >> 8); /* device ID byte 1 */
+ if (ret != 0) {
+ return ret;
+ }
- return uart_write(msg, sizeof(msg));
+ return uart_write_8(id & 0xFF); /* device ID byte 2 */
}
static int uart_send_phase(uint32_t address)
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index 3f385ca317..04219677cc 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,10 +13,12 @@
#include <common/debug.h>
#include <drivers/st/stm32mp_clkfunc.h>
#include <drivers/st/stm32mp_pmic.h>
+#include <lib/smccc.h>
#include <lib/spinlock.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
#define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16)
@@ -32,12 +34,6 @@ unsigned int plat_get_syscnt_freq2(void)
return read_cntfrq_el0();
}
-#pragma weak stm32mp_plat_reset
-void __dead2 stm32mp_plat_reset(int cpu)
-{
- panic();
-}
-
static uintptr_t boot_ctx_address;
static uint16_t boot_itf_selected;
static uint32_t boot_action_saved;
@@ -147,58 +143,6 @@ int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer)
}
#endif
-/* Return CPU supply name */
-const char *stm32mp_get_cpu_supply_name(void)
-{
- const char *regulator;
- const char *supply = NULL;
-
- regulator = dt_get_cpu_regulator_name();
- if (regulator == NULL) {
- return NULL;
- }
-
- if (dt_pmic_status() > 0) {
- if (dt_pmic_find_supply(&supply, regulator) != 0) {
- return NULL;
- }
- }
-
- return supply;
-}
-
-/* Return VDD supply name */
-const char *stm32mp_get_vdd_supply_name(void)
-{
- const char *supply = NULL;
-
- if (dt_pmic_status() > 0) {
- const char *regulator = dt_get_vdd_regulator_name();
-
- if (regulator != NULL) {
- dt_pmic_find_supply(&supply, regulator);
- }
- }
-
- return supply;
-}
-
-/* Return USB phy supply name */
-const char *stm32mp_get_usb_phy_supply_name(void)
-{
- const char *supply = NULL;
-
- if (dt_pmic_status() > 0) {
- const char *regulator = dt_get_usb_phy_regulator_name();
-
- if (regulator != NULL) {
- dt_pmic_find_supply(&supply, regulator);
- }
- }
-
- return supply;
-}
-
#if TRUSTED_BOARD_BOOT && STM32MP_USE_STM32IMAGE
/* Save pointer to last loaded header */
static boot_api_image_header_t *latest_stm32_header;
@@ -243,3 +187,35 @@ int stm32mp_unmap_ddr(void)
return mmap_remove_dynamic_region(STM32MP_DDR_BASE,
STM32MP_DDR_MAX_SIZE);
}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ uint32_t manfid = (JEDEC_ST_BKID << 24U) | (JEDEC_ST_MFID << 16U);
+
+ return (int32_t)(manfid | (stm32mp_get_chip_dev_id() & 0xFFFFU));
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ return (int32_t)stm32mp_get_chip_version();
+}
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index a3584cbc12..fd25c93fca 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,7 @@
#include <common/debug.h>
#include <common/fdt_wrappers.h>
+#include <drivers/regulator.h>
#include <drivers/st/stm32_gpio.h>
#include <stm32mp_dt.h>
@@ -71,21 +72,20 @@ bool fdt_check_node(int node)
uint8_t fdt_get_status(int node)
{
uint8_t status = DT_DISABLED;
- int len;
const char *cchar;
- cchar = fdt_getprop(fdt, node, "status", &len);
+ cchar = fdt_getprop(fdt, node, "status", NULL);
if ((cchar == NULL) ||
- (strncmp(cchar, "okay", (size_t)len) == 0)) {
+ (strncmp(cchar, "okay", strlen("okay")) == 0)) {
status |= DT_NON_SECURE;
}
- cchar = fdt_getprop(fdt, node, "secure-status", &len);
+ cchar = fdt_getprop(fdt, node, "secure-status", NULL);
if (cchar == NULL) {
if (status == DT_NON_SECURE) {
status |= DT_SECURE;
}
- } else if (strncmp(cchar, "okay", (size_t)len) == 0) {
+ } else if (strncmp(cchar, "okay", strlen("okay")) == 0) {
status |= DT_SECURE;
}
@@ -458,61 +458,23 @@ int dt_get_all_opp_freqvolt(uint32_t *count, uint32_t *freq_khz_array,
******************************************************************************/
uint32_t dt_get_pwr_vdd_voltage(void)
{
- int node;
- const fdt32_t *cuint;
+ struct rdev *regul = dt_get_vdd_regulator();
+ uint16_t min;
- node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
- if (node < 0) {
+ if (regul == NULL) {
return 0;
}
- cuint = fdt_getprop(fdt, node, "vdd-supply", NULL);
- if (cuint == NULL) {
- return 0;
- }
+ regulator_get_range(regul, &min, NULL);
- node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
- if (node < 0) {
- return 0;
- }
-
- cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
- if (cuint == NULL) {
- return 0;
- }
-
- return fdt32_to_cpu(*cuint);
+ return (uint32_t)min * 1000U;
}
/*******************************************************************************
- * This function return the real regulator name from DT.
+ * This function retrieves VDD supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
******************************************************************************/
-static const char *dt_get_regulator_name(int node, const char *regu_name)
-{
- const fdt32_t *cuint;
-
- if ((node < 0) || (regu_name == NULL)) {
- return NULL;
- }
-
- cuint = fdt_getprop(fdt, node, regu_name, NULL);
- if (cuint == NULL) {
- return NULL;
- }
-
- node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
- if (node < 0) {
- return NULL;
- }
-
- return (const char *)fdt_getprop(fdt, node, "regulator-name", NULL);
-}
-
-/*******************************************************************************
- * This function retrieves VDD regulator name from DT.
- * Returns string taken from supply node, NULL otherwise.
- ******************************************************************************/
-const char *dt_get_vdd_regulator_name(void)
+struct rdev *dt_get_vdd_regulator(void)
{
int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
@@ -520,14 +482,14 @@ const char *dt_get_vdd_regulator_name(void)
return NULL;
}
- return dt_get_regulator_name(node, "vdd-supply");
+ return regulator_get_by_supply_name(fdt, node, "vdd");
}
/*******************************************************************************
- * This function retrieves CPU regulator name from DT.
- * Returns string taken from supply node, NULL otherwise.
+ * This function retrieves CPU supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
******************************************************************************/
-const char *dt_get_cpu_regulator_name(void)
+struct rdev *dt_get_cpu_regulator(void)
{
int node = fdt_path_offset(fdt, "/cpus/cpu@0");
@@ -535,27 +497,27 @@ const char *dt_get_cpu_regulator_name(void)
return NULL;
}
- return dt_get_regulator_name(node, "cpu-supply");
+ return regulator_get_by_supply_name(fdt, node, "cpu");
}
/*******************************************************************************
* This function retrieves USB phy regulator name from DT.
* Returns string taken from supply node, NULL otherwise.
******************************************************************************/
-const char *dt_get_usb_phy_regulator_name(void)
+struct rdev *dt_get_usb_phy_regulator(void)
{
int node = fdt_node_offset_by_compatible(fdt, -1, DT_USBPHYC_COMPAT);
int subnode;
- const char *reg_name = NULL;
if (node < 0) {
return NULL;
}
fdt_for_each_subnode(subnode, fdt, node) {
- reg_name = dt_get_regulator_name(subnode, "phy-supply");
- if (reg_name != NULL) {
- return reg_name;
+ struct rdev *supply = regulator_get_by_supply_name(fdt, node, "phy");
+
+ if (supply != NULL) {
+ return supply;
}
}
diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c
index 1ea30abf9b..6bc77e2440 100644
--- a/plat/st/common/stm32mp_trusted_boot.c
+++ b/plat/st/common/stm32mp_trusted_boot.c
@@ -85,7 +85,7 @@ int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
memcpy(&res, proot_pk, sizeof(uint32_t));
if ((res == 0U) || (res == 0xFFFFFFFFU)) {
while (idx < ARRAY_SIZE(root_pk_hash)) {
- memcpy(&rootpk, (proot_pk + idx), sizeof(uint32_t));
+ memcpy(&rootpk, root_pk_hash + idx, sizeof(uint32_t));
if (res != rootpk) {
return 0;
}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 13ce3042a5..642138a1dd 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -17,6 +17,8 @@
#include <drivers/clk.h>
#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/regulator.h>
#include <drivers/st/bsec.h>
#include <drivers/st/stm32_console.h>
#include <drivers/st/stm32_iwdg.h>
@@ -189,10 +191,6 @@ void bl2_platform_setup(void)
/* Clear the context in BKPSRAM */
stm32_clean_context();
-
- if (dt_pmic_status() > 0) {
- configure_pmic();
- }
}
/* Map DDR for binary load, now with cacheable attribute */
@@ -269,21 +267,21 @@ static void initialize_clock(void)
if (dt_pmic_status() > 0) {
int read_voltage;
- const char *name;
+ struct rdev *regul;
- name = stm32mp_get_cpu_supply_name();
- if (name == NULL) {
+ regul = dt_get_cpu_regulator();
+ if (regul == NULL) {
panic();
}
- read_voltage = stpmic1_regulator_voltage_get(name);
+ read_voltage = regulator_get_voltage(regul);
if (read_voltage < 0) {
panic();
}
if (voltage_mv != (uint32_t)read_voltage) {
- if (stpmic1_regulator_voltage_set(name,
- (uint16_t)voltage_mv) != 0) {
+ if (regulator_set_voltage(regul,
+ (uint16_t)voltage_mv) != 0) {
panic();
}
}
@@ -380,10 +378,11 @@ void bl2_el3_plat_arch_setup(void)
mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
}
- /* Enable BKP Register protection */
- mmio_write_32(TAMP_SMCR,
- TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_WDPROT_SHIFT |
- TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_RWDPROT_SHIFT);
+ /* Set minimum reset pulse duration to 31ms for discrete power supplied boards */
+ if (dt_pmic_status() <= 0) {
+ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR, RCC_RDLSICR_MRD_MASK,
+ 31U << RCC_RDLSICR_MRD_SHIFT);
+ }
generic_delay_timer_init();
@@ -411,6 +410,11 @@ void bl2_el3_plat_arch_setup(void)
initialize_clock();
+#if STM32MP_USB_PROGRAMMER
+ /* Deconfigure all UART RX pins configured by ROM code */
+ stm32mp1_deconfigure_uart_pins();
+#endif
+
result = dt_get_stdout_uart_info(&dt_uart_info);
if ((result <= 0) ||
@@ -455,13 +459,11 @@ void bl2_el3_plat_arch_setup(void)
stm32mp_print_boardinfo();
-#if TRUSTED_BOARD_BOOT
if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
NOTICE("Bootrom authentication %s\n",
(boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
"failed" : "succeeded");
}
-#endif
skip_console_init:
#if !TRUSTED_BOARD_BOOT
@@ -506,7 +508,7 @@ skip_console_init:
stm32mp1_syscfg_enable_io_compensation_finish();
if (dt_pmic_status() > 0) {
- initialize_pmic();
+ initialize_pmic_i2c();
print_pmic_info_and_debug();
}
@@ -718,6 +720,19 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
break;
}
+#if STM32MP_SDMMC || STM32MP_EMMC
+ /*
+ * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+ * We take the worst case which is 2 MMC blocks.
+ */
+ if ((image_id != FW_CONFIG_ID) &&
+ ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+ inv_dcache_range(bl_mem_params->image_info.image_base +
+ bl_mem_params->image_info.image_size,
+ 2U * MMC_BLOCK_SIZE);
+ }
+#endif
+
return err;
}
diff --git a/plat/st/stm32mp1/include/stm32mp1_critic_power.h b/plat/st/stm32mp1/include/stm32mp1_critic_power.h
index cd7099c444..7563406b4e 100644
--- a/plat/st/stm32mp1/include/stm32mp1_critic_power.h
+++ b/plat/st/stm32mp1/include/stm32mp1_critic_power.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,11 +12,11 @@
*/
#if defined(IMAGE_BL32)
#if STM32MP_SP_MIN_IN_DDR
-extern void (*stm32_pwr_down_wfi)(bool is_cstop);
+extern void (*stm32_pwr_down_wfi)(bool is_cstop, uint32_t mode);
#else
-extern void stm32_pwr_down_wfi(bool is_cstop);
+extern void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode);
#endif
#endif
-extern void stm32_pwr_down_wfi_wrapper(bool is_cstop);
+extern void stm32_pwr_down_wfi_wrapper(bool is_cstop, uint32_t mode);
#endif /* STM32MP1_CRITIC_POWER_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index ebf9e52bc9..cbcd2c8bd5 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,6 +40,8 @@ void stm32mp1_syscfg_enable_io_compensation_start(void);
void stm32mp1_syscfg_enable_io_compensation_finish(void);
void stm32mp1_syscfg_disable_io_compensation(void);
+void stm32mp1_deconfigure_uart_pins(void);
+
#if STM32MP_USE_STM32IMAGE
uint32_t stm32mp_get_ddr_ns_size(void);
#endif
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index d322da0090..6092db2b95 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -21,18 +21,18 @@
static bl_mem_params_node_t bl2_mem_params_descs[] = {
/* Fill FW_CONFIG related information if it exists */
{
- .image_id = FW_CONFIG_ID,
- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
- VERSION_2, entry_point_info_t,
- SECURE | NON_EXECUTABLE),
- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
- VERSION_2, image_info_t,
- IMAGE_ATTRIB_PLAT_SETUP),
-
- .image_info.image_base = STM32MP_FW_CONFIG_BASE,
- .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
-
- .next_handoff_image_id = INVALID_IMAGE_ID,
+ .image_id = FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+
+ .image_info.image_base = STM32MP_FW_CONFIG_BASE,
+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
},
/* Fill BL32 related information */
@@ -85,27 +85,28 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
/* Fill HW_CONFIG related information if it exists */
{
- .image_id = HW_CONFIG_ID,
- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
- VERSION_2, entry_point_info_t,
- NON_SECURE | NON_EXECUTABLE),
- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
- VERSION_2, image_info_t,
- IMAGE_ATTRIB_SKIP_LOADING),
-
- .next_handoff_image_id = INVALID_IMAGE_ID,
+ .image_id = HW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
},
+ /* Fill TOS_FW_CONFIG related information if it exists */
{
- .image_id = TOS_FW_CONFIG_ID,
- SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
- VERSION_2, entry_point_info_t,
- SECURE | NON_EXECUTABLE),
- SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
- VERSION_2, image_info_t,
- IMAGE_ATTRIB_SKIP_LOADING),
-
- .next_handoff_image_id = INVALID_IMAGE_ID,
+ .image_id = TOS_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
},
/* Fill BL33 related information */
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 067e1fff9f..55acd67422 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -15,7 +15,7 @@ USE_COHERENT_MEM := 0
STM32MP_USE_STM32IMAGE ?= 0
# Add specific ST version
-ST_VERSION := r1.0
+ST_VERSION := r2.0
ifeq ($(STM32MP_USE_STM32IMAGE),1)
ST_VERSION := ${ST_VERSION}-nofip
endif
@@ -107,8 +107,14 @@ BL32_DTSI := stm32mp15-bl32.dtsi
FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
endif
endif
+
+$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
+$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g")))
DTC_CPPFLAGS += ${INCLUDES}
DTC_FLAGS += -Wno-unit_address_vs_reg
+ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0)
+DTC_FLAGS += -Wno-interrupt_provider
+endif
# Macros and rules to build TF binary
STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
@@ -129,7 +135,7 @@ STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
ifneq (${STM32MP_USE_STM32IMAGE},1)
FIP_DEPS += dtbs
-STM32MP_NT_FW_CONFIG := ${BL33_CFG}
+STM32MP_HW_CONFIG := ${BL33_CFG}
STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
ifneq (${AARCH32_SP},none)
@@ -137,8 +143,8 @@ FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NA
endif
# Add the FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
-# Add the NT_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_NT_FW_CONFIG},--hw-config))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
ifeq (${GENERATE_COT},1)
$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
endif
@@ -212,6 +218,8 @@ PLAT_BL_COMMON_SOURCES := common/fdt_wrappers.c \
plat/st/common/stm32mp_common.c \
plat/st/stm32mp1/stm32mp1_private.c
+PLAT_BL_COMMON_SOURCES += drivers/regulator/regulator_core.c
+
PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S
ifneq (${ENABLE_STACK_PROTECTOR},0)
@@ -236,8 +244,6 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
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 \
@@ -363,7 +369,8 @@ BL2_SOURCES += drivers/st/usb_dwc2/usb_dwc2.c \
plat/st/stm32mp1/stm32mp1_usb.c
endif
-BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \
+BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \
+ drivers/st/ddr/stm32mp1_ddr.c \
drivers/st/ddr/stm32mp1_ram.c
BL2_SOURCES += common/desc_image_load.c \
@@ -409,8 +416,6 @@ clean_stm32image:
${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
check_dtc_version:
- $(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
- $(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g")))
@if [ ${DTC_VERSION} -lt 10404 ]; then \
echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
false; \
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
index e3d845d2ec..633e63eb31 100644
--- a/plat/st/stm32mp1/services/bsec_svc.c
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -12,6 +12,7 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
+#include <drivers/regulator.h>
#include <drivers/st/bsec.h>
#include <drivers/st/bsec2_reg.h>
#include <drivers/st/stm32mp_pmic.h>
@@ -87,16 +88,18 @@ static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update)
sizeof(boot_api_ssp_config_t));
#endif
if (dt_pmic_status() > 0) {
- const char *name;
+ struct rdev *regul;
initialize_pmic();
- name = stm32mp_get_cpu_supply_name();
- if (name == NULL) {
+ regul = dt_get_cpu_regulator();
+ if (regul == NULL) {
return BSEC_SSP_ERROR;
}
- stpmic1_regulator_mask_reset_set(name);
+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) {
+ return BSEC_SSP_ERROR;
+ }
}
return BSEC_SSP_SET;
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index dd81d13a08..99575f5666 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -17,6 +17,7 @@ BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES
BL32_SOURCES += drivers/st/clk/stm32mp1_calib.c \
drivers/st/etzpc/etzpc.c \
+ drivers/st/regulator/regulator_fixed.c \
drivers/st/rng/stm32_rng.c \
drivers/st/rtc/stm32_rtc.c \
drivers/st/tamper/stm32_tamp.c \
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 0065be44fd..d408b76523 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,8 +18,10 @@
#include <drivers/arm/tzc400.h>
#include <drivers/clk.h>
#include <drivers/generic_delay_timer.h>
+#include <drivers/regulator.h>
#include <drivers/st/bsec.h>
#include <drivers/st/etzpc.h>
+#include <drivers/st/regulator_fixed.h>
#include <drivers/st/stm32_console.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_iwdg.h>
@@ -51,43 +53,26 @@
static entry_point_info_t bl33_image_ep_info;
static console_t console;
-static void stm32mp1_tamper_action(int id);
-
-static const char *tamper_name[PLAT_MAX_TAMP_INT] = {
- "RTC power domain",
- "Temperature monitoring",
- "LSE monitoring",
- "HSE monitoring",
- "RTC calendar overflow",
- "Monotonic counter"
-};
+static struct dt_node_info dt_uart_info;
-static struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT] = {
- {
- .id = ITAMP1,
- .func = stm32mp1_tamper_action,
- },
- {
- .id = ITAMP2,
- .func = stm32mp1_tamper_action,
- },
- {
- .id = ITAMP3,
- .func = stm32mp1_tamper_action,
- },
- {
- .id = ITAMP4,
- .func = stm32mp1_tamper_action,
- },
- TAMP_UNUSED,
- TAMP_UNUSED,
+static const char * const tamper_name[] = {
+ [INT_TAMP1] = "RTC power domain",
+ [INT_TAMP2] = "Temperature monitoring",
+ [INT_TAMP3] = "LSE monitoring",
+ [INT_TAMP4] = "HSE monitoring",
};
-static struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT] = {
- TAMP_UNUSED,
- TAMP_UNUSED,
- TAMP_UNUSED,
-};
+static int stm32mp1_tamper_action(int id)
+{
+ const char *tamp_name = NULL;
+
+ if ((id >= 0) && ((size_t)id < ARRAY_SIZE(tamper_name))) {
+ tamp_name = tamper_name[id];
+ }
+ ERROR("Tamper %u (%s) occurs\n", id, tamp_name);
+
+ return 1; /* ack TAMPER and reset system */
+}
static void stm32_sgi1_it_handler(void)
{
@@ -114,12 +99,6 @@ static void stm32_sgi1_it_handler(void)
stm32mp_wait_cpu_reset();
}
-static void stm32mp1_tamper_action(int id)
-{
- ERROR("Tamper %s occurs\n", tamper_name[id]);
- stm32mp_system_reset();
-}
-
static void configure_wakeup_interrupt(void)
{
int irq_num = fdt_rcc_enable_it("wakeup");
@@ -141,14 +120,15 @@ static void initialize_pll1_settings(void)
}
if (dt_pmic_status() > 0) {
- const char *name = stm32mp_get_cpu_supply_name();
+ struct rdev *regul;
int ret;
- if (name == NULL) {
+ regul = dt_get_cpu_regulator();
+ if (regul == NULL) {
panic();
}
- ret = stpmic1_regulator_voltage_get(name);
+ ret = regulator_get_voltage(regul);
if (ret < 0) {
panic();
}
@@ -164,16 +144,18 @@ static void initialize_pll1_settings(void)
static void disable_usb_phy_regulator(void)
{
if (dt_pmic_status() > 0) {
- const char *name = stm32mp_get_usb_phy_supply_name();
+ struct rdev *regul = dt_get_usb_phy_regulator();
int ret;
- if (name == NULL) {
+ if (regul == NULL) {
return;
}
- ret = stpmic1_regulator_disable(name);
- if (ret < 0) {
- WARN("USBPHYC phy-supply (%s) disable failed\n", name);
+ if (regulator_is_enabled(regul) == 1) {
+ ret = regulator_disable(regul);
+ if (ret < 0) {
+ WARN("USBPHYC phy-supply (%s) disable failed\n", regul->reg_name);
+ }
}
}
}
@@ -262,6 +244,7 @@ static uintptr_t get_saved_pc(void)
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
{
entry_point_info_t *next_image_info = &bl33_image_ep_info;
+ unsigned int console_flags;
/*
* PC is set to 0 when resetting after STANDBY
@@ -276,6 +259,16 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
panic();
}
+ console_flags = CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF;
+ if ((clk_is_enabled(dt_uart_info.clock)) &&
+ (clk_get_rate(dt_uart_info.clock) != 0U)) {
+ console_flags |= CONSOLE_FLAG_BOOT;
+#ifdef DEBUG
+ console_flags |= CONSOLE_FLAG_RUNTIME;
+#endif
+ }
+ console_set_scope(&console, console_flags);
+
cpu_context = cm_get_context(NON_SECURE);
next_image_info->spsr = read_ctx_reg(get_regs_ctx(cpu_context),
@@ -291,6 +284,8 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
next_image_info->pc =
read_ctx_reg(get_regs_ctx(cpu_context), CTX_LR);
}
+
+ regulator_core_resume();
}
return next_image_info;
@@ -327,17 +322,12 @@ static void stm32mp1_etzpc_early_setup(void)
etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
}
-#if !STM32MP_USE_STM32IMAGE
+#if STM32MP_SP_MIN_IN_DDR
static void populate_ns_dt(u_register_t ns_dt_addr, uintptr_t sec_base, size_t sec_size)
{
void *external_fdt = (void *)ns_dt_addr;
int ret;
- if (sec_base < STM32MP_DDR_BASE) {
- /* No need to reserve memory if secure monitor is not in DDR */
- return;
- }
-
/* Map Base Non Secure DDR for Non secure DT update */
ret = mmap_add_dynamic_region(ns_dt_addr, ns_dt_addr, STM32MP_HW_CONFIG_MAX_SIZE,
MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_RW | MT_NS);
@@ -377,7 +367,6 @@ out:
******************************************************************************/
static void setup_uart_console(void)
{
- struct dt_node_info dt_uart_info;
unsigned int console_flags;
int result;
uint32_t boot_itf;
@@ -419,10 +408,9 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
uintptr_t dt_addr = STM32MP_DTB_BASE;
#else
uintptr_t dt_addr = arg1;
- uintptr_t sec_base = 0U;
- size_t sec_size = 0U;
#endif
#if STM32MP_SP_MIN_IN_DDR
+ uintptr_t sec_base = 0U;
uintptr_t bl2_code_base = 0U;
uintptr_t bl2_code_end = 0U;
uintptr_t bl2_end = 0U;
@@ -511,36 +499,41 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
}
}
-#if !STM32MP_USE_STM32IMAGE
+#if STM32MP_SP_MIN_IN_DDR
if (bl_params->image_id == BL32_IMAGE_ID) {
sec_base = bl_params->image_info->image_base;
- sec_size = bl_params->image_info->image_max_size;
}
#endif
bl_params = bl_params->next_params_info;
}
-#if !STM32MP_USE_STM32IMAGE
+#if STM32MP_SP_MIN_IN_DDR
if (arg2 != 0U) {
/* This will expect the BL32 DT and BL32 are grouped */
if (dt_addr < sec_base) {
- sec_size = sec_size + sec_base - dt_addr;
sec_base = dt_addr;
- } else {
- sec_size = dt_addr - sec_base + STM32MP_BL32_DTB_SIZE;
}
- populate_ns_dt(arg2, sec_base, sec_size);
+ populate_ns_dt(arg2, sec_base, DDR_SEC_SIZE);
} else {
INFO("Non-secure device tree not found\n");
}
#endif
+ generic_delay_timer_init();
+
if (dt_pmic_status() > 0) {
initialize_pmic();
}
+ fixed_regulator_register();
+
+ if (regulator_core_config() != 0) {
+ ERROR("Regulator core config error\n");
+ panic();
+ }
+
disable_usb_phy_regulator();
initialize_pll1_settings();
@@ -550,8 +543,6 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
static void init_sec_peripherals(void)
{
- uint32_t filter_conf = 0;
- uint32_t active_conf = 0;
int ret;
/* Disable MCU subsystem protection */
@@ -571,9 +562,28 @@ static void init_sec_peripherals(void)
/* Init tamper */
if (stm32_tamp_init() > 0) {
- stm32_tamp_configure_internal(int_tamp, PLAT_MAX_TAMP_INT);
- stm32_tamp_configure_external(ext_tamp, PLAT_MAX_TAMP_EXT,
- filter_conf, active_conf);
+ struct bkpregs_conf bkpregs_conf = {
+ .nb_zone1_regs = TAMP_BKP_SEC_NUMBER,
+ .nb_zone2_regs = 0 /* no register in zone 2 */
+ /* zone3 all remaining */
+ };
+
+ /* Enable BKP Register protection */
+ if (stm32_tamp_set_secure_bkpregs(&bkpregs_conf) < 0) {
+ panic();
+ }
+
+ stm32_tamp_configure_secure_access(TAMP_REGS_IT_SECURE);
+
+ stm32_tamp_configure_internal(INT_TAMP1, TAMP_ENABLE, stm32mp1_tamper_action);
+ stm32_tamp_configure_internal(INT_TAMP2, TAMP_ENABLE, stm32mp1_tamper_action);
+ stm32_tamp_configure_internal(INT_TAMP3, TAMP_ENABLE, stm32mp1_tamper_action);
+ stm32_tamp_configure_internal(INT_TAMP4, TAMP_ENABLE, stm32mp1_tamper_action);
+
+ ret = stm32_tamp_set_config();
+ if (ret < 0) {
+ panic();
+ }
/* Enable timestamp for tamper */
stm32_rtc_set_tamper_timestamp();
@@ -593,8 +603,6 @@ void sp_min_platform_setup(void)
ddr_save_sr_mode();
- generic_delay_timer_init();
-
stm32_gic_init();
init_sec_peripherals();
@@ -608,6 +616,11 @@ void sp_min_platform_setup(void)
stm32mp_lock_periph_registering();
stm32mp1_init_scmi_server();
+
+ /* Cold boot: clean-up regulators state */
+ if (get_saved_pc() == 0U) {
+ regulator_core_cleanup();
+ }
}
void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
index 027475ed40..1705c15258 100644
--- a/plat/st/stm32mp1/stm32mp1_context.c
+++ b/plat/st/stm32mp1/stm32mp1_context.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,7 @@
#include <common/bl_common.h>
#include <context.h>
#include <drivers/clk.h>
+#include <drivers/regulator.h>
#include <drivers/st/stm32_rtc.h>
#include <drivers/st/stm32mp_clkfunc.h>
#include <drivers/st/stm32mp1_ddr_regs.h>
@@ -92,6 +93,7 @@ struct backup_bl32_data_s {
unsigned long long stgen;
uint8_t clock_cfg[CLOCK_CONTEXT_SIZE];
uint8_t scmi_context[SCMI_CONTEXT_SIZE];
+ uint8_t regul_context[PLAT_BACKUP_REGULATOR_SIZE];
};
static struct backup_bl32_data_s *get_bl32_backup_data(void)
@@ -101,7 +103,7 @@ static struct backup_bl32_data_s *get_bl32_backup_data(void)
}
#if STM32MP_SP_MIN_IN_DDR
-void (*stm32_pwr_down_wfi)(bool is_cstop);
+void (*stm32_pwr_down_wfi)(bool is_cstop, uint32_t mode);
#endif
#endif
@@ -227,6 +229,9 @@ int stm32_save_context(uint32_t zq0cr0_zdata,
save_clock_pm_context();
+ regulator_core_backup_context(backup_bl32_data->regul_context,
+ sizeof(backup_bl32_data->regul_context));
+
clk_disable(BKPSRAM);
return 0;
@@ -279,6 +284,9 @@ int stm32_restore_context(void)
&backup_bl32_data->rtc);
stm32mp_stgen_restore_counter(backup_bl32_data->stgen, stdby_time_in_ms);
+ regulator_core_restore_context(backup_bl32_data->regul_context,
+ sizeof(backup_bl32_data->regul_context));
+
clk_disable(BKPSRAM);
stm32mp1_clock_resume();
@@ -317,7 +325,7 @@ void stm32_context_get_bl2_low_power_params(uintptr_t *bl2_code_base,
}
#if STM32MP_SP_MIN_IN_DDR
- stm32_pwr_down_wfi = (void (*)(bool))backup_data->low_power_ep;
+ stm32_pwr_down_wfi = (void (*)(bool, uint32_t))backup_data->low_power_ep;
#endif
*bl2_code_base = (uintptr_t)backup_data->bl2_code_base;
*bl2_code_end = (uintptr_t)backup_data->bl2_code_end;
@@ -463,6 +471,8 @@ void stm32_save_ddr_training_area(void)
PAGE_SIZE, MT_MEMORY | MT_RW | MT_NS);
assert(ret == 0);
+ flush_dcache_range(STM32MP_DDR_BASE, TRAINING_AREA_SIZE);
+
memcpy(&backup_data->ddr_training_backup,
(const uint32_t *)STM32MP_DDR_BASE,
TRAINING_AREA_SIZE);
diff --git a/plat/st/stm32mp1/stm32mp1_critic_power.c b/plat/st/stm32mp1/stm32mp1_critic_power.c
index 583cf93fad..aad11fa508 100644
--- a/plat/st/stm32mp1/stm32mp1_critic_power.c
+++ b/plat/st/stm32mp1/stm32mp1_critic_power.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,19 +10,38 @@
#include <common/debug.h>
#include <drivers/arm/gicv2.h>
#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32mp1_ddr_helpers.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <stm32mp1_context.h>
#include <stm32mp1_critic_power.h>
-static void cstop_critic_enter(void)
+static void cstop_critic_enter(uint32_t mode)
{
+ /* Switch to Software Self-Refresh mode */
+ ddr_set_sr_mode(DDR_SSR_MODE);
+
/*
* Set DDR in Self-refresh,.
* This is also the procedure awaited when switching off power supply.
*/
if (ddr_standby_sr_entry() != 0) {
ERROR("Unable to put DDR in SR\n");
- panic();
+ if (mode != STM32_PM_SHUTDOWN) {
+ panic();
+ }
+ }
+}
+
+static void shutdown_critic_enter(void)
+{
+ if (dt_pmic_status() > 0) {
+ if (!initialize_pmic_i2c()) {
+ panic();
+ }
+
+ pmic_switch_off();
}
}
@@ -36,10 +55,18 @@ static void cstop_critic_exit(void)
}
}
-void stm32_pwr_down_wfi_load(bool is_cstop)
+void stm32_pwr_down_wfi_load(bool is_cstop, uint32_t mode)
{
+ if (mode != STM32_PM_CSLEEP_RUN) {
+ dcsw_op_all(DC_OP_CISW);
+ }
+
if (is_cstop) {
- cstop_critic_enter();
+ cstop_critic_enter(mode);
+ }
+
+ if (mode == STM32_PM_SHUTDOWN) {
+ shutdown_critic_enter();
}
/*
@@ -61,12 +88,20 @@ void stm32_pwr_down_wfi_load(bool is_cstop)
extern void wfi_svc_int_enable(uintptr_t stack_addr);
static uint32_t int_stack[STM32MP_INT_STACK_SIZE];
-void stm32_pwr_down_wfi(bool is_cstop)
+void stm32_pwr_down_wfi(bool is_cstop, uint32_t mode)
{
uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
+ if (mode != STM32_PM_CSLEEP_RUN) {
+ dcsw_op_all(DC_OP_CISW);
+ }
+
if (is_cstop) {
- cstop_critic_enter();
+ cstop_critic_enter(mode);
+ }
+
+ if (mode == STM32_PM_SHUTDOWN) {
+ shutdown_critic_enter();
}
stm32mp1_calib_set_wakeup(false);
diff --git a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S
index 2c4dd844d2..514def2fc4 100644
--- a/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S
+++ b/plat/st/stm32mp1/stm32mp1_critic_power_wrapper.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,9 @@
func stm32_pwr_down_wfi_wrapper
push {r4,r5,r6,lr}
+ # Save r0 and r1 in r2 and r3, as they are used in disable_mmu_secure
+ mov r2, r0
+ mov r3, r1
# Save current sp in r4
mov r4, sp
# Save current VBAR in r5
@@ -34,20 +37,21 @@ func stm32_pwr_down_wfi_wrapper
stcopr r1, MVBAR
# Set sp to BL2 STACK (as BL2 is not using it anymore)
- ldr sp, =__STACKS_END__
+ ldr sp, =__STACKS_END__
# Disable MMU as TLB are still stored in DDR,
# and in few instructions DDR won't be readable
- bl disable_mmu_secure
+ bl disable_mmu_secure
# dsb is done in disable mmu
# isb is done in disable mmu
- # We didn't change R0 to keep it as first parameter
- bl stm32_pwr_down_wfi_load
+ mov r0, r2
+ mov r1, r3
+ bl stm32_pwr_down_wfi_load
# Restore stack
- mov sp, r4
+ mov sp, r4
# Restore VBAR
stcopr r5, VBAR
# Restore MVBAR
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 326b227842..780d124d17 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -162,8 +162,8 @@ enum ddr_type {
#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */
#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */
#else
-#define STM32MP_BL2_RO_SIZE U(0x00010000) /* 64 KB */
-#define STM32MP_BL2_SIZE U(0x00015000) /* 84 KB for BL2 */
+#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */
+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
#endif
#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \
@@ -182,7 +182,7 @@ enum ddr_type {
#if STM32MP_SP_MIN_IN_DDR
#define STM32MP_BL32_SIZE U(0x00025000) /* 148 KB for BL32 */
#else
-#define STM32MP_BL32_SIZE U(0x0001A000) /* 100 KB for BL32 */
+#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */
#endif
#endif /* STM32MP_USE_STM32IMAGE */
#endif /* STM32MP_SSP */
@@ -265,10 +265,14 @@ enum ddr_type {
STM32MP_BL2_DTB_SIZE)
#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#if STM32MP_SP_MIN_IN_DDR
+#define DDR_SEC_SIZE U(0x02000000) /* 32MB */
+#else
#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE
#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \
STM32MP_BL32_DTB_SIZE)
+#endif
#if defined(IMAGE_BL2)
#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE
@@ -581,11 +585,8 @@ enum ddr_type {
#define PLAT_MAX_TAMP_INT U(6)
#define PLAT_MAX_TAMP_EXT U(3)
#define TAMP_BASE U(0x5C00A000)
-#define TAMP_SMCR (TAMP_BASE + U(0x20))
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
#define TAMP_BKP_SEC_NUMBER U(10)
-#define TAMP_BKP_SEC_WDPROT_SHIFT U(16)
-#define TAMP_BKP_SEC_RWDPROT_SHIFT U(0)
#if !(defined(__LINKER__) || defined(__ASSEMBLER__))
@@ -650,6 +651,16 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
#define PLAT_MAX_OPP_NB U(2)
#define PLAT_MAX_PLLCFG_NB U(6)
+/*******************************************************************************
+ * REGULATORS
+ ******************************************************************************/
+/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
+#define PLAT_NB_RDEVS U(19)
+/* Number of low power modes defined in the device tree */
+#define PLAT_NB_SUSPEND_MODES 7
+/* 1 FIXED */
+#define PLAT_NB_FIXED_REGS U(1)
+
/*******************************************************************************
* DEBUG
******************************************************************************/
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
index 315a67f2cf..da3ab1562b 100644
--- a/plat/st/stm32mp1/stm32mp1_helper.S
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -251,12 +251,12 @@ func plat_crash_console_init
str r2, [r1]
1:
ldr r0, [r1]
- ands r0, r2
+ ands r2, r0, r2
beq 1b
str r2, [r1, #4] /* RSTCLR register */
2:
ldr r0, [r1]
- ands r0, r2
+ ands r2, r0, r2
bne 2b
/* Enable GPIOs for UART TX */
ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c
index ae6fd88c88..82e2de710c 100644
--- a/plat/st/stm32mp1/stm32mp1_low_power.c
+++ b/plat/st/stm32mp1/stm32mp1_low_power.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,7 @@
#include <drivers/arm/gicv2.h>
#include <drivers/clk.h>
#include <drivers/delay_timer.h>
+#include <drivers/regulator.h>
#include <drivers/st/stm32_iwdg.h>
#include <drivers/st/stm32_rtc.h>
#include <drivers/st/stm32mp_clkfunc.h>
@@ -104,6 +105,11 @@ static struct spinlock lp_lock;
static volatile int cpu0_state = STATE_NONE;
static volatile int cpu1_state = STATE_NONE;
+const char *plat_get_lp_mode_name(int mode)
+{
+ return config_pwr[mode].regul_suspend_node_name;
+}
+
void stm32_apply_pmic_suspend_config(uint32_t mode)
{
const char *node_name;
@@ -116,14 +122,6 @@ void stm32_apply_pmic_suspend_config(uint32_t mode)
if (!initialize_pmic_i2c()) {
panic();
}
-
- if (pmic_set_lp_config(node_name) < 0) {
- panic();
- }
-
- if (pmic_configure_boot_on_regulators() < 0) {
- panic();
- }
}
}
@@ -147,11 +145,6 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
stm32mp1_syscfg_disable_io_compensation();
- /* Switch to Software Self-Refresh mode */
- ddr_set_sr_mode(DDR_SSR_MODE);
-
- dcsw_op_all(DC_OP_CISW);
-
stm32_clean_context();
if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) {
@@ -170,6 +163,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
}
}
+ regulator_core_suspend(mode);
+
/* Clear RCC interrupt before enabling it */
mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF);
@@ -289,6 +284,8 @@ void stm32_exit_cstop(void)
panic();
}
+ regulator_core_resume();
+
stm32mp1_syscfg_enable_io_compensation_finish();
}
@@ -348,7 +345,7 @@ static void stm32_auto_stop_cpu0(void)
enter_cstop(STM32_PM_CSTOP_ALLOW_LP_STOP, 0);
- stm32_pwr_down_wfi(true);
+ stm32_pwr_down_wfi(true, STM32_PM_CSTOP_ALLOW_LP_STOP);
stm32_exit_cstop();
@@ -380,27 +377,6 @@ void stm32_auto_stop(void)
}
}
-static void enter_shutdown(void)
-{
- /* Set DDR in Self-refresh before shutting down the platform */
- if (ddr_standby_sr_entry() != 0) {
- WARN("DDR can't be set in Self-refresh mode\n");
- }
-
- if (dt_pmic_status() > 0) {
- if (!initialize_pmic_i2c()) {
- panic();
- }
-
- stpmic1_switch_off();
-
- udelay(100);
-
- /* Shouldn't be reached */
- panic();
- }
-}
-
static void enter_csleep(void)
{
uintptr_t pwr_base = stm32mp_pwr_base();
@@ -410,14 +386,13 @@ static void enter_csleep(void)
mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK,
config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1);
- stm32_pwr_down_wfi(false);
+ stm32_pwr_down_wfi(false, STM32_PM_CSLEEP_RUN);
}
void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr)
{
switch (mode) {
case STM32_PM_SHUTDOWN:
- enter_shutdown();
break;
case STM32_PM_CSLEEP_RUN:
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index 962a992243..e5f622a5be 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -169,7 +169,8 @@ static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
void (*warm_entrypoint)(void) =
(void (*)(void))stm32_sec_entrypoint;
- stm32_pwr_down_wfi(stm32_is_cstop_done());
+ stm32_pwr_down_wfi(stm32_is_cstop_done(),
+ stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND));
stm32_exit_cstop();
@@ -207,7 +208,7 @@ static void __dead2 stm32_system_off(void)
stm32_enter_low_power(soc_mode, 0);
- stm32_pwr_down_wfi(false);
+ stm32_pwr_down_wfi(true, soc_mode);
/* This shouldn't be reached */
panic();
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 09afe1a6ea..0451efe72f 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,11 +13,9 @@
#include <arch_helpers.h>
#include <drivers/arm/gicv2.h>
#include <drivers/clk.h>
+#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_iwdg.h>
-#include <drivers/st/stm32mp_dummy_regulator.h>
#include <drivers/st/stm32mp_pmic.h>
-#include <drivers/st/stm32mp_regulator.h>
-#include <drivers/st/stm32mp_reset.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -165,110 +163,6 @@ void __dead2 stm32mp_wait_cpu_reset(void)
}
}
-/*
- * tzc_source_ip contains the TZC transaction source IPs that need to be reset
- * before a C-A7 subsystem is reset (i.e. independent reset):
- * - C-A7 subsystem is reset separately later in the sequence,
- * - C-M4 subsystem is not concerned here,
- * - DAP is excluded for debug purpose,
- * - IPs are stored with their ETZPC IDs (STM32MP1_ETZPC_MAX_ID if not
- * applicable) because some of them need to be reset only if they are not
- * configured in MCU isolation mode inside ETZPC device tree.
- */
-struct tzc_source_ip {
- uint32_t reset_id;
- uint32_t clock_id;
- uint32_t decprot_id;
-};
-
-#define _TZC_FIXED(res, clk) \
- { \
- .reset_id = (res), \
- .clock_id = (clk), \
- .decprot_id = STM32MP1_ETZPC_MAX_ID, \
- }
-
-#define _TZC_COND(res, clk, decprot) \
- { \
- .reset_id = (res), \
- .clock_id = (clk), \
- .decprot_id = (decprot), \
- }
-
-static const struct tzc_source_ip tzc_source_ip[] = {
- _TZC_FIXED(LTDC_R, LTDC_PX),
- _TZC_FIXED(GPU_R, GPU),
- _TZC_FIXED(USBH_R, USBH),
- _TZC_FIXED(SDMMC1_R, SDMMC1_K),
- _TZC_FIXED(SDMMC2_R, SDMMC2_K),
- _TZC_FIXED(MDMA_R, MDMA),
- _TZC_COND(USBO_R, USBO_K, STM32MP1_ETZPC_OTG_ID),
- _TZC_COND(SDMMC3_R, SDMMC3_K, STM32MP1_ETZPC_SDMMC3_ID),
- _TZC_COND(ETHMAC_R, ETHMAC, STM32MP1_ETZPC_ETH_ID),
- _TZC_COND(DMA1_R, DMA1, STM32MP1_ETZPC_DMA1_ID),
- _TZC_COND(DMA2_R, DMA2, STM32MP1_ETZPC_DMA2_ID),
-};
-
-#define TIMEOUT_US_1MS U(1000)
-
-void __dead2 stm32mp_plat_reset(int cpu)
-{
- uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST;
- uint32_t id;
-
- /* Mask timer interrupts */
- stm32mp_mask_timer();
-
- for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) {
- if ((!clk_is_enabled(tzc_source_ip[id].clock_id)) ||
- ((tzc_source_ip[id].decprot_id != STM32MP1_ETZPC_MAX_ID) &&
- (etzpc_get_decprot(tzc_source_ip[id].decprot_id) ==
- ETZPC_DECPROT_MCU_ISOLATION))) {
- continue;
- }
-
- if (tzc_source_ip[id].reset_id != GPU_R) {
- uint32_t reset = tzc_source_ip[id].reset_id;
- int ret;
-
- ret = stm32mp_reset_assert(reset, TIMEOUT_US_1MS);
- if (ret != 0) {
- panic();
- }
- ret = stm32mp_reset_deassert(reset, TIMEOUT_US_1MS);
- if (ret != 0) {
- panic();
- }
- } else {
- /* GPU reset automatically cleared by hardware */
- mmio_setbits_32(stm32mp_rcc_base() + RCC_AHB6RSTSETR,
- RCC_AHB6RSTSETR_GPURST);
- }
- }
-
- if (!stm32mp_is_single_core()) {
- unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ?
- STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU;
-
- gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu);
- reg |= RCC_MP_GRSTCSETR_MPUP1RST;
- }
-
- do {
- id = plat_ic_get_pending_interrupt_id();
-
- if (id <= MAX_SPI_ID) {
- gicv2_end_of_interrupt(id);
-
- plat_ic_disable_interrupt(id);
- }
- } while (id <= MAX_SPI_ID);
-
- mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg);
-
- stm32mp_wait_cpu_reset();
-}
-
uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
{
if (bank == GPIO_BANK_Z) {
@@ -291,6 +185,15 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
return bank * GPIO_BANK_OFFSET;
}
+bool stm32_gpio_is_secure_at_reset(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return true;
+ }
+
+ return false;
+}
+
#if STM32MP_UART_PROGRAMMER || defined(IMAGE_BL32)
/*
* UART Management
@@ -317,6 +220,53 @@ uintptr_t get_uart_address(uint32_t instance_nb)
}
#endif
+#if STM32MP_USB_PROGRAMMER
+struct gpio_bank_pin_list {
+ uint32_t bank;
+ uint32_t pin;
+};
+
+static const struct gpio_bank_pin_list gpio_list[] = {
+ { /* USART2_RX: GPIOA3 */
+ .bank = 0,
+ .pin = 3,
+ },
+ { /* USART3_RX: GPIOB12 */
+ .bank = 1,
+ .pin = 12,
+ },
+ { /* UART4_RX: GPIOB2 */
+ .bank = 1,
+ .pin = 2,
+ },
+ { /* UART5_RX: GPIOB4 */
+ .bank = 1,
+ .pin = 5,
+ },
+ { /* USART6_RX: GPIOC7 */
+ .bank = 2,
+ .pin = 7,
+ },
+ { /* UART7_RX: GPIOF6 */
+ .bank = 5,
+ .pin = 6,
+ },
+ { /* UART8_RX: GPIOE0 */
+ .bank = 4,
+ .pin = 0,
+ },
+};
+
+void stm32mp1_deconfigure_uart_pins(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
+ set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin);
+ }
+}
+#endif
+
unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
{
if (bank == GPIO_BANK_Z) {
@@ -403,25 +353,38 @@ int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val)
return 0;
}
-int stm32mp_get_chip_version(uint32_t *chip_version)
+uint32_t stm32mp_get_chip_version(void)
{
- return stm32mp1_dbgmcu_get_chip_version(chip_version);
+ uint32_t version = 0U;
+
+ if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) {
+ INFO("Cannot get CPU version, debug disabled\n");
+ return 0U;
+ }
+
+ return version;
}
-static uint32_t get_part_number(void)
+uint32_t stm32mp_get_chip_dev_id(void)
{
- static uint32_t part_number;
uint32_t dev_id;
- if (part_number != 0U) {
- return part_number;
- }
-
if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
INFO("Use default chip ID, debug disabled\n");
dev_id = STM32MP1_CHIP_ID;
}
+ return dev_id;
+}
+
+static uint32_t get_part_number(void)
+{
+ static uint32_t part_number;
+
+ if (part_number != 0U) {
+ return part_number;
+ }
+
if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
panic();
}
@@ -429,7 +392,7 @@ static uint32_t get_part_number(void)
part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >>
PART_NUMBER_OTP_PART_SHIFT;
- part_number |= dev_id << 16;
+ part_number |= stm32mp_get_chip_dev_id() << 16;
return part_number;
}
@@ -477,8 +440,6 @@ bool stm32mp_supports_cpu_opp(uint32_t opp_id)
void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
{
char *cpu_s, *cpu_r, *pkg;
- uint32_t chip_dev_id;
- int ret;
/* MPUs Part Numbers */
switch (get_part_number()) {
@@ -543,12 +504,7 @@ void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
}
/* REVISION */
- ret = stm32mp_get_chip_version(&chip_dev_id);
- if (ret < 0) {
- INFO("Cannot get CPU version, debug disabled\n");
- }
-
- switch (chip_dev_id) {
+ switch (stm32mp_get_chip_version()) {
case STM32MP1_REV_B:
cpu_r = "B";
break;
@@ -732,29 +688,6 @@ enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode)
}
}
-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;
-}
-
#if STM32MP_USE_STM32IMAGE
/* Get the non-secure DDR size */
uint32_t stm32mp_get_ddr_ns_size(void)
@@ -789,9 +722,14 @@ bool stm32mp1_addr_inside_backupsram(uintptr_t addr)
bool stm32mp1_is_wakeup_from_standby(void)
{
+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
uint32_t bkpr_core1_addr = tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
uint32_t nsec_address;
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+ return false;
+ }
+
if (stm32mp_get_boot_action() != BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY) {
return false;
}
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.c b/plat/st/stm32mp1/stm32mp1_ssp.c
index bcbf374782..a60721691e 100644
--- a/plat/st/stm32mp1/stm32mp1_ssp.c
+++ b/plat/st/stm32mp1/stm32mp1_ssp.c
@@ -17,6 +17,7 @@
#include <drivers/clk.h>
#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
+#include <drivers/regulator.h>
#include <drivers/st/bsec.h>
#include <drivers/st/stm32_console.h>
#include <drivers/st/stm32_hash.h>
@@ -803,24 +804,24 @@ static void ssp_start(boot_api_context_t *boot_context)
* the required MPSYSRST.
*/
if (dt_pmic_status() > 0) {
- const char *name;
+ struct rdev *regul;
- name = stm32mp_get_cpu_supply_name();
- if (name == NULL) {
- goto out;
+ regul = dt_get_cpu_regulator();
+ if (regul == NULL) {
+ panic();
}
- if (stpmic1_regulator_mask_reset_set(name) != 0) {
- WARN("Failed to write %s reset mask\n", name);
+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) {
+ WARN("Failed to write cpu-supply reset mask\n");
}
- name = stm32mp_get_vdd_supply_name();
- if (name == NULL) {
+ regul = dt_get_vdd_regulator();
+ if (regul == NULL) {
goto out;
}
- if (stpmic1_regulator_mask_reset_set(name) != 0) {
- WARN("Failed to write %s reset mask\n", name);
+ if (regulator_set_flag(regul, REGUL_MASK_RESET) < 0) {
+ WARN("Failed to write vdd-supply reset mask\n");
}
} else {
static const char debug_msg[] = {
@@ -1028,7 +1029,7 @@ skip_console_init:
stm32_iwdg_refresh();
if (dt_pmic_status() > 0) {
- initialize_pmic();
+ initialize_pmic_i2c();
print_pmic_info_and_debug();
}
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
index 2c5fa082fc..b471be2096 100644
--- a/plat/st/stm32mp1/stm32mp1_syscfg.c
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,6 +26,9 @@
#define SYSCFG_CMPENSETR 0x24U
#define SYSCFG_CMPENCLRR 0x28U
+#define CMPCR_CMPENSETR_OFFSET 0x4U
+#define CMPCR_CMPENCLRR_OFFSET 0x8U
+
/*
* SYSCFG_BOOTR Register
*/
@@ -63,25 +66,61 @@
*/
#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
-void stm32mp1_syscfg_init(void)
+static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
+{
+ uint64_t start;
+
+ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
+
+ while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
+ if (timeout_elapsed(start)) {
+ /* Failure on IO compensation enable is not a issue: warn only. */
+ WARN("IO compensation cell not ready\n");
+ break;
+ }
+ }
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
+}
+
+static void disable_io_comp_cell(uintptr_t cmpcr_off)
+{
+ uint32_t value;
+
+ if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
+ ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
+ SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
+ return;
+ }
+
+ value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+
+ value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
+ value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
+
+ mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
+
+ mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
+}
+
+static void enable_high_speed_mode_low_voltage(void)
+{
+ mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+ SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+ SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+}
+
+static void stm32mp1_syscfg_set_hslv(void)
{
- uint32_t bootr;
uint32_t otp_value;
uint32_t vdd_voltage;
bool product_below_2v5;
- /*
- * Interconnect update : select master using the port 1.
- * LTDC = AXI_M9.
- */
- mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
-
- /* Disable Pull-Down for boot pin connected to VDD */
- bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
- SYSCFG_BOOTR_BOOT_MASK;
- mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
- bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
-
/*
* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
@@ -110,12 +149,7 @@ void stm32mp1_syscfg_init(void)
if (vdd_voltage == 0U) {
WARN("VDD unknown\n");
} else if (vdd_voltage < 2700000U) {
- mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
- SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
- SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
- SYSCFG_IOCTRLSETR_HSLVEN_ETH |
- SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
- SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+ enable_high_speed_mode_low_voltage();
if (!product_below_2v5) {
INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
@@ -128,6 +162,25 @@ void stm32mp1_syscfg_init(void)
panic();
}
}
+}
+
+void stm32mp1_syscfg_init(void)
+{
+ uint32_t bootr;
+
+ /*
+ * Interconnect update : select master using the port 1.
+ * LTDC = AXI_M9.
+ */
+ mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
+
+ /* Disable Pull-Down for boot pin connected to VDD */
+ bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
+ SYSCFG_BOOTR_BOOT_MASK;
+ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
+ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
+
+ stm32mp1_syscfg_set_hslv();
stm32mp1_syscfg_enable_io_compensation_start();
}
@@ -141,35 +194,17 @@ void stm32mp1_syscfg_enable_io_compensation_start(void)
*/
stm32mp1_clk_force_enable(SYSCFG);
- mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR,
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
SYSCFG_CMPENSETR_MPU_EN);
}
void stm32mp1_syscfg_enable_io_compensation_finish(void)
{
- uint64_t start;
-
- start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
-
- while ((mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) &
- SYSCFG_CMPCR_READY) == 0U) {
- if (timeout_elapsed(start)) {
- /*
- * 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);
+ enable_io_comp_cell_finish(SYSCFG_CMPCR);
}
void stm32mp1_syscfg_disable_io_compensation(void)
{
- uint32_t value;
-
stm32mp1_clk_force_enable(SYSCFG);
/*
@@ -178,18 +213,7 @@ void stm32mp1_syscfg_disable_io_compensation(void)
* requested for other usages and always OFF in STANDBY.
* Disable non-secure SYSCFG clock, we assume non-secure is suspended.
*/
- value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) >>
- SYSCFG_CMPCR_ANSRC_SHIFT;
-
- mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR,
- SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
-
- value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) |
- (value << SYSCFG_CMPCR_RANSRC_SHIFT);
-
- mmio_write_32(SYSCFG_BASE + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL);
-
- mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENCLRR, SYSCFG_CMPENSETR_MPU_EN);
+ disable_io_comp_cell(SYSCFG_CMPCR);
stm32mp1_clk_force_disable(SYSCFG);
}
diff --git a/plat/st/stm32mp1/stm32mp1_usb.c b/plat/st/stm32mp1/stm32mp1_usb.c
index c63db4a2ff..a205b64d34 100644
--- a/plat/st/stm32mp1/stm32mp1_usb.c
+++ b/plat/st/stm32mp1/stm32mp1_usb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -310,7 +310,7 @@ static uint8_t *stm32mp1_product_desc(uint16_t *length)
char str_chip_version[5];
stm32mp_get_soc_name(name);
- stm32mp_get_chip_version(&chip_version);
+ chip_version = stm32mp_get_chip_version();
int_to_str(STM32MP1_CHIP_ID, (uint8_t *)str_chip_id, 4);
int_to_str(chip_version, (uint8_t *)str_chip_version, 5);
--
2.17.1