8217 lines
227 KiB
Diff
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
|
|
|