meta-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp-ssp/0100-v2.2-stm32mp-ssp-r2-rc...

4417 lines
127 KiB
Diff

From 3e97529fe31f7f87396b2a58c17189d03e7f0c76 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Wed, 21 Oct 2020 12:11:57 +0200
Subject: [PATCH] v2.2-stm32mp-ssp-r2-rc2
---
.../bindings/clock/st,stm32mp1-rcc.txt | 10 +-
.../bindings/power/st,stm32mp1-pwr.txt | 1 +
drivers/mtd/nand/raw_nand.c | 6 +-
drivers/st/clk/stm32mp1_calib.c | 8 +-
drivers/st/clk/stm32mp1_clk.c | 10 +-
drivers/st/fmc/stm32_fmc2_nand.c | 94 ++-
drivers/st/gpio/stm32_gpio.c | 5 +-
drivers/st/io/io_mmc.c | 18 +-
drivers/st/io/io_programmer_st_usb.c | 92 ++-
drivers/st/iwdg/stm32_iwdg.c | 5 +-
drivers/st/mmc/stm32_sdmmc2.c | 21 +-
drivers/st/reset/stm32mp1_reset.c | 18 +-
drivers/st/tamper/stm32_tamp.c | 7 +-
drivers/st/timer/stm32_timer.c | 22 +-
drivers/st/uart/io_programmer_uart.c | 208 ++++-
fdts/stm32mp151.dtsi | 61 +-
fdts/stm32mp157a-avenger96.dts | 4 +-
fdts/stm32mp157a-dk1.dts | 4 +-
fdts/stm32mp157a-ed1.dts | 4 +-
fdts/stm32mp157c-dk2.dts | 4 +-
fdts/stm32mp157c-ed1.dts | 4 +-
fdts/stm32mp157d-dk1.dts | 4 +-
fdts/stm32mp157d-ed1.dts | 4 +-
fdts/stm32mp157f-dk2.dts | 4 +-
fdts/stm32mp157f-ed1.dts | 4 +-
fdts/stm32mp15xx-dkx.dtsi | 14 +-
fdts/stm32mp15xx-edx.dtsi | 14 +-
fdts/stm32mp15xx-evx.dtsi | 16 +-
include/drivers/raw_nand.h | 2 +-
include/drivers/st/etzpc.h | 5 +-
include/drivers/st/io_programmer.h | 8 +-
include/drivers/st/stm32mp_reset.h | 9 +-
include/dt-bindings/reset/stm32mp1-resets.h | 2 +
include/lib/psci/psci.h | 1 +
include/lib/ssp_lib.h | 35 +
include/lib/usb/usb_st_dfu.h | 10 +-
lib/psci/psci_private.h | 1 -
lib/ssp/ssp.c | 748 ++++++++++++++++++
lib/usb/usb_st_dfu.c | 101 ++-
plat/st/common/bl2_io_storage.c | 10 +-
plat/st/common/include/stm32mp_common.h | 6 +
plat/st/common/include/stm32mp_dt.h | 1 +
plat/st/common/stm32mp_common.c | 16 +
plat/st/common/stm32mp_dt.c | 27 +
plat/st/common/stm32mp_trusted_boot.c | 1 +
plat/st/stm32mp1/bl2_plat_setup.c | 45 +-
plat/st/stm32mp1/include/boot_api.h | 265 ++++++-
plat/st/stm32mp1/include/platform_def.h | 15 +-
plat/st/stm32mp1/include/stm32mp1_context.h | 6 +-
plat/st/stm32mp1/include/stm32mp1_low_power.h | 1 +
.../stm32mp1/include/stm32mp1_power_config.h | 1 +
plat/st/stm32mp1/include/stm32mp1_smc.h | 8 +
plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 4 +-
plat/st/stm32mp1/plat_image_load.c | 8 +-
plat/st/stm32mp1/platform.mk | 14 +-
plat/st/stm32mp1/services/bsec_svc.c | 4 -
plat/st/stm32mp1/services/rcc_svc.c | 17 +-
.../st/stm32mp1/services/stm32mp1_svc_setup.c | 6 +
plat/st/stm32mp1/sp_min/sp_min_setup.c | 7 +
plat/st/stm32mp1/stm32mp1_context.c | 8 +-
plat/st/stm32mp1/stm32mp1_def.h | 52 +-
plat/st/stm32mp1/stm32mp1_helper.S | 38 +-
plat/st/stm32mp1/stm32mp1_low_power.c | 132 +++-
plat/st/stm32mp1/stm32mp1_power_config.c | 35 +
plat/st/stm32mp1/stm32mp1_private.c | 34 +
plat/st/stm32mp1/stm32mp1_scmi.c | 12 +
plat/st/stm32mp1/stm32mp1_shared_resources.c | 30 +-
plat/st/stm32mp1/stm32mp1_ssp.S | 11 +
plat/st/stm32mp1/stm32mp1_ssp.ld.S | 58 ++
plat/st/stm32mp1/stm32mp1_ssp.mk | 66 ++
70 files changed, 2318 insertions(+), 208 deletions(-)
create mode 100644 include/lib/ssp_lib.h
create mode 100644 lib/ssp/ssp.c
create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.S
create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.ld.S
create mode 100644 plat/st/stm32mp1/stm32mp1_ssp.mk
diff --git a/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
index a082706ee..7d2b5be9d 100644
--- a/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
+++ b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
@@ -166,7 +166,15 @@ Defining peripheral PLL frequencies
Each PLL children nodes for PLL1 to PLL4 (see ref manual for details)
are listed with associated reg 0 to 3.
- PLLx is off when the associated node is absent or deactivated.
+
+ PLL2, PLL3 or PLL4 are off when their associated nodes are absent or
+ deactivated.
+
+ The configuration of PLL1, the source clock of Cortex-A7 core, with st,pll@0
+ node, is optional as TF-A automatically selects the most suitable operating
+ point for the platform.
+ The node st,pll@0 node should be absent; it is only used if you want to
+ override the PLL1 properties computed by TF-A (clock spreading for example).
Here are the available properties for each PLL node:
- compatible: should be "st,stm32mp1-pll"
diff --git a/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
index bd56e1946..22779b05a 100644
--- a/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
+++ b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
@@ -15,6 +15,7 @@ Optional Properties:
- Nodes corresponding to PSCI commands issued by kernel:
- system_suspend_supported_soc_modes: list of supported SoC modes in suspend
- system_off_soc_mode: SoC mode for shutdown
+ - st,retram-enabled-in-standby-ddr-sr: enable retram during standby-ddr-sr
The list of SoC modes is in include/dt-bindings/power/stm32mp1-power.h:
- modes for system_suspend
diff --git a/drivers/mtd/nand/raw_nand.c b/drivers/mtd/nand/raw_nand.c
index 48131fcb2..9481a1aab 100644
--- a/drivers/mtd/nand/raw_nand.c
+++ b/drivers/mtd/nand/raw_nand.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -190,7 +190,7 @@ static int nand_status(uint8_t *status)
return ret;
}
-int nand_wait_ready(unsigned long delay)
+int nand_wait_ready(unsigned long delay_ms)
{
uint8_t status;
int ret;
@@ -204,7 +204,7 @@ int nand_wait_ready(unsigned long delay)
return ret;
}
- timeout = timeout_init_us(delay);
+ timeout = timeout_init_us(delay_ms * 1000U);
while (!timeout_elapsed(timeout)) {
ret = nand_read_data(&status, 1U, true);
if (ret != 0) {
diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c
index b764c971c..8a8993885 100644
--- a/drivers/st/clk/stm32mp1_calib.c
+++ b/drivers/st/clk/stm32mp1_calib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -517,8 +517,14 @@ void stm32mp1_calib_init(void)
timer_val = fdt_rcc_read_uint32_default("st,cal-sec", 0) *
plat_get_syscnt_freq2();
+ if (timer_val > INT32_MAX) {
+ timer_val = INT32_MAX;
+ }
+
if (timer_val != 0U) {
/* Load & enable timer */
+ INFO("Set calibration timer to %u sec\n",
+ timer_val / plat_get_syscnt_freq2());
write_cntp_tval(timer_val);
write_cntp_ctl(BIT(0));
};
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 5efe343b8..498ca8de8 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -428,7 +428,6 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
_CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
#endif
-#if defined(IMAGE_BL2)
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
@@ -440,7 +439,6 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
-#endif
_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
@@ -698,20 +696,24 @@ 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;
+#if !STM32MP_SSP
static uint32_t pll3cr;
static uint32_t pll4cr;
static uint32_t mssckselr;
static uint32_t mcudivr;
+#endif
static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
{
return &stm32mp1_clk_gate[idx];
}
+#if !STM32MP_SSP
static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate)
{
return gate->secure == N_S;
}
+#endif
static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
{
@@ -2848,6 +2850,7 @@ unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit)
return get_id_from_rcc_bit(offset, bit);
}
+#if !STM32MP_SSP
#ifdef IMAGE_BL32
/*
* Get the parent ID of the target parent clock, for tagging as secure
@@ -3449,6 +3452,7 @@ static void sync_earlyboot_clocks_state(void)
stm32mp_clk_enable(RTCAPB);
}
+#endif /* !STM32MP_SSP */
int stm32mp1_clk_probe(void)
{
@@ -3458,7 +3462,9 @@ int stm32mp1_clk_probe(void)
stm32mp1_osc_init();
+#if !STM32MP_SSP
sync_earlyboot_clocks_state();
+#endif
/* Save current CPU operating point value */
freq_khz = udiv_round_nearest(stm32mp_clk_get_rate(CK_MPU), 1000UL);
diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c
index e976c3bdd..e81e5fdfa 100644
--- a/drivers/st/fmc/stm32_fmc2_nand.c
+++ b/drivers/st/fmc/stm32_fmc2_nand.c
@@ -25,8 +25,10 @@
#define TIMEOUT_US_1MS U(1000)
/* FMC2 Compatibility */
-#define DT_FMC2_COMPAT "st,stm32mp15-fmc2"
+#define DT_FMC2_EBI_COMPAT "st,stm32mp1-fmc2-ebi"
+#define DT_FMC2_NFC_COMPAT "st,stm32mp1-fmc2-nfc"
#define MAX_CS 2U
+#define MAX_BANK 5U
/* FMC2 Controller Registers */
#define FMC2_BCR1 0x00U
@@ -36,6 +38,7 @@
#define FMC2_PATT 0x8CU
#define FMC2_HECCR 0x94U
#define FMC2_BCHISR 0x254U
+#define FMC2_BCHICR 0x258U
#define FMC2_BCHDSR0 0x27CU
#define FMC2_BCHDSR1 0x280U
#define FMC2_BCHDSR2 0x284U
@@ -81,6 +84,8 @@
#define FMC2_PATT_DEFAULT 0x0A0A0A0AU
/* FMC2_BCHISR register */
#define FMC2_BCHISR_DERF BIT(1)
+/* FMC2_BCHICR register */
+#define FMC2_BCHICR_CLEAR_IRQ GENMASK_32(4, 0)
/* FMC2_BCHDSR0 register */
#define FMC2_BCHDSR0_DUE BIT(0)
#define FMC2_BCHDSR0_DEF BIT(1)
@@ -499,6 +504,7 @@ static void stm32_fmc2_hwctl(struct nand_device *nand)
if (nand->ecc.max_bit_corr != FMC2_ECC_HAM) {
mmio_clrbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_WEN);
+ mmio_write_32(fmc2_base() + FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
}
stm32_fmc2_set_ecc(true);
@@ -788,22 +794,25 @@ static const struct nand_ctrl_ops ctrl_ops = {
int stm32_fmc2_init(void)
{
- int fmc_node;
- int fmc_subnode = 0;
+ int fmc_ebi_node;
+ int fmc_nfc_node;
+ int fmc_flash_node = 0;
int nchips = 0;
unsigned int i;
void *fdt = NULL;
const fdt32_t *cuint;
struct dt_node_info info;
+ uintptr_t bank_address[MAX_BANK] = { 0, 0, 0, 0, 0 };
+ uint8_t bank_assigned = 0;
+ uint8_t bank;
if (fdt_get_address(&fdt) == 0) {
return -FDT_ERR_NOTFOUND;
}
- fmc_node = dt_get_node(&info, -1, DT_FMC2_COMPAT);
- if (fmc_node == -FDT_ERR_NOTFOUND) {
- WARN("No FMC2 node found\n");
- return fmc_node;
+ fmc_ebi_node = dt_get_node(&info, -1, DT_FMC2_EBI_COMPAT);
+ if (fmc_ebi_node < 0) {
+ return fmc_ebi_node;
}
if (info.status == DT_DISABLED) {
@@ -819,27 +828,69 @@ int stm32_fmc2_init(void)
stm32_fmc2.clock_id = (unsigned long)info.clock;
stm32_fmc2.reset_id = (unsigned int)info.reset;
- cuint = fdt_getprop(fdt, fmc_node, "reg", NULL);
+ cuint = fdt_getprop(fdt, fmc_ebi_node, "ranges", NULL);
if (cuint == NULL) {
return -FDT_ERR_BADVALUE;
}
- cuint += 2;
-
- for (i = 0U; i < MAX_CS; i++) {
- stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*cuint);
- stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 2));
- stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 4));
- cuint += 6;
+ for (i = 0U; i < MAX_BANK; i++) {
+ bank = fdt32_to_cpu(*cuint);
+ if ((bank >= MAX_BANK) || ((bank_assigned & BIT(bank)) != 0U)) {
+ return -FDT_ERR_BADVALUE;
+ }
+ bank_assigned |= BIT(bank);
+ bank_address[bank] = fdt32_to_cpu(*(cuint + 2));
+ cuint += 4;
}
/* Pinctrl initialization */
- if (dt_set_pinctrl_config(fmc_node) != 0) {
+ if (dt_set_pinctrl_config(fmc_ebi_node) != 0) {
return -FDT_ERR_BADVALUE;
}
+ /* Parse NFC controller node */
+ fmc_nfc_node = fdt_node_offset_by_compatible(fdt, fmc_ebi_node,
+ DT_FMC2_NFC_COMPAT);
+ if (fmc_nfc_node < 0) {
+ return fmc_nfc_node;
+ }
+
+ if (fdt_get_status(fmc_nfc_node) == DT_DISABLED) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ cuint = fdt_getprop(fdt, fmc_nfc_node, "reg", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ for (i = 0U; i < MAX_CS; i++) {
+ bank = fdt32_to_cpu(*cuint);
+ if (bank >= MAX_BANK) {
+ return -FDT_ERR_BADVALUE;
+ }
+ stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*(cuint + 1)) +
+ bank_address[bank];
+
+ bank = fdt32_to_cpu(*(cuint + 3));
+ if (bank >= MAX_BANK) {
+ return -FDT_ERR_BADVALUE;
+ }
+ stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 4)) +
+ bank_address[bank];
+
+ bank = fdt32_to_cpu(*(cuint + 6));
+ if (bank >= MAX_BANK) {
+ return -FDT_ERR_BADVALUE;
+ }
+ stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 7)) +
+ bank_address[bank];
+
+ cuint += 9;
+ }
+
/* Parse flash nodes */
- fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) {
+ fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) {
nchips++;
}
@@ -848,14 +899,19 @@ int stm32_fmc2_init(void)
return -FDT_ERR_BADVALUE;
}
- fdt_for_each_subnode(fmc_subnode, fdt, fmc_node) {
+ fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) {
/* Get chip select */
- cuint = fdt_getprop(fdt, fmc_subnode, "reg", NULL);
+ cuint = fdt_getprop(fdt, fmc_flash_node, "reg", NULL);
if (cuint == NULL) {
WARN("Chip select not well defined\n");
return -FDT_ERR_BADVALUE;
}
+
stm32_fmc2.cs_sel = fdt32_to_cpu(*cuint);
+ if (stm32_fmc2.cs_sel >= MAX_CS) {
+ return -FDT_ERR_BADVALUE;
+ }
+
VERBOSE("NAND CS %i\n", stm32_fmc2.cs_sel);
}
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index cdb56ffbe..a6c8dd0f5 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -161,13 +161,14 @@ int dt_set_pinctrl_config(int node)
const fdt32_t *cuint;
int lenp = 0;
uint32_t i;
- uint8_t status = fdt_get_status(node);
+ uint8_t status;
void *fdt;
if (fdt_get_address(&fdt) == 0) {
return -FDT_ERR_NOTFOUND;
}
+ status = fdt_get_status(node);
if (status == DT_DISABLED) {
return -FDT_ERR_NOTFOUND;
}
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
index 0b0e84ec1..daf05af0b 100644
--- a/drivers/st/io/io_mmc.c
+++ b/drivers/st/io/io_mmc.c
@@ -97,20 +97,20 @@ static int mmc_block_seek(io_entity_t *entity, int mode,
static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
{
- uint8_t retries = 3U;
-
- do {
- retries--;
- if (retries == 0U) {
- return -EIO;
- }
+ uint8_t retries;
+ for (retries = 0U; retries < 3U; retries++) {
*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
buffer, length);
- } while (*length_read != length);
+ if (*length_read == length) {
+ return 0;
+ }
+ WARN("%s: length_read = %u (!= %u), retry %d\n", __func__,
+ *length_read, length, retries + 1U);
+ }
- return 0;
+ return -EIO;
}
/* Close a file on the mmc device */
diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c
index 20da9656e..02ade112a 100644
--- a/drivers/st/io/io_programmer_st_usb.c
+++ b/drivers/st/io/io_programmer_st_usb.c
@@ -17,6 +17,7 @@
#include <drivers/st/io_programmer_st_usb.h>
#include <drivers/st/io_stm32image.h>
#include <drivers/st/stm32_iwdg.h>
+#include <lib/ssp_lib.h>
#include <lib/usb/usb_st_dfu.h>
#define USB_STATE_READY 0
@@ -89,13 +90,22 @@ static uint16_t usb_callback_write_done(uint32_t *written_in, uint32_t len)
}
/* Call back to notify that a read memory is requested */
-static uint8_t *usb_callback_read(uint8_t *src, uint8_t *dest, uint32_t len)
+static uint16_t usb_callback_read(uint8_t *src, uint8_t *dest, uint32_t len)
{
+#if STM32MP_SSP
+ if (current_phase.phase_id == SSP_PHASE) {
+ const size_t size = SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t);
+
+ if (len >= size) {
+ memcpy(dest, src, size);
+ return size;
+ }
+ }
+#else
ERROR("%s read is not supported src 0x%lx dest 0x%lx len %i\n",
__func__, (uintptr_t)src, (uintptr_t)dest, len);
-
- /* Return a valid address to avoid HardFault */
- return (uint8_t *)(dest);
+#endif
+ return 0;
}
/* Get the status to know if written operation has been checked */
@@ -173,10 +183,11 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity)
{
int result;
+#if !STM32MP_SSP
uint32_t length = 0;
boot_api_image_header_t *header =
(boot_api_image_header_t *)first_usb_buffer;
-
+#endif
const struct stm32image_part_info *partition_spec =
(struct stm32image_part_info *)spec;
@@ -186,7 +197,7 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
assert(entity);
current_phase.current_packet = 0;
-
+#if !STM32MP_SSP
if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) {
/* read flash layout first for U-boot */
current_phase.phase_id = PHASE_FLASHLAYOUT;
@@ -221,6 +232,16 @@ static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
current_phase.phase_id = PHASE_SSBL;
current_phase.max_size = dt_get_ddr_size();
}
+#else
+ if (!strcmp(partition_spec->name, "SSP")) {
+ current_phase.phase_id = SSP_PHASE;
+ current_phase.keep_header = 1;
+ }
+
+ if (!strcmp(partition_spec->name, "SSP_INIT")) {
+ current_phase.phase_id = RESET_PHASE;
+ }
+#endif
entity->info = (uintptr_t)&current_phase;
result = 0;
} else {
@@ -267,6 +288,64 @@ static int usb_block_seek(io_entity_t *entity, int mode,
}
/* Read data from a file on the usb device */
+#if STM32MP_SSP
+static int usb_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint64_t timeout;
+ uint32_t detach_timeout = DETACH_TIMEOUT;
+ ssp_exchange_t *exchange = (ssp_exchange_t *)buffer;
+
+ if (current_phase.phase_id == RESET_PHASE) {
+ usb_dfu_set_phase_id(RESET_PHASE);
+ usb_dfu_set_upload_addr(buffer);
+ usb_dfu_error_msg_size(length);
+ } else {
+ usb_dfu_set_upload_addr((uint32_t)exchange->msg);
+ usb_dfu_set_download_addr((uint32_t)exchange->blob);
+
+ /* Use flashlayout partition for SSP exchange */
+ usb_dfu_set_phase_id(PHASE_FLASHLAYOUT);
+
+ INFO("Start Download partition SSP address 0x%lx length %i\n",
+ (uintptr_t)exchange->blob, length);
+ }
+
+ while (!usb_dfu_download_is_completed()) {
+ /* Reload watchdog */
+ stm32_iwdg_refresh();
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+ }
+
+ /* Wait Detach in case */
+ usb_dfu_set_phase_id(0x0);
+ usb_dfu_set_upload_addr(UNDEFINE_DOWN_ADDR);
+ usb_dfu_request_detach();
+ timeout = timeout_init_us(IO_USB_TIMEOUT_10_SEC);
+ while (detach_timeout != 0U) {
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+
+ if (usb_dfu_detach_req() == 0U) {
+ /*
+ * Continue to handle usb core IT to assure
+ * complete data transmission.
+ */
+ detach_timeout--;
+ }
+
+ if (timeout_elapsed(timeout)) {
+ return -EIO;
+ }
+ }
+
+ /* STOP the USB Handler */
+ usb_core_stop((usb_handle_t *)usb_dev_info.info);
+
+ *length_read = length;
+
+ return 0;
+}
+#else /* STM32MP_SSP */
static int usb_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
{
@@ -355,6 +434,7 @@ static int usb_block_read(io_entity_t *entity, uintptr_t buffer,
return 0;
}
+#endif /* STM32MP_SSP */
/* Close a file on the usb device */
static int usb_block_close(io_entity_t *entity)
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index 6055e4d84..ee7c8c6f1 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -266,9 +266,6 @@ int stm32_iwdg_init(void)
stm32mp_register_secure_periph_iomem(iwdg->base);
}
- stm32mp_clk_enable(iwdg->clock);
- stm32mp_clk_disable(iwdg->clock);
-
#if defined(IMAGE_BL32)
res = stm32_iwdg_conf_etimeout(node, iwdg);
if (res != 0) {
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 782127c49..e4047e44a 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -326,6 +326,17 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55));
+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+ /*
+ * Clear the SDMMC_DCTRLR if the command does not await data.
+ * Skip CMD55 as the next command could be data related, and
+ * the register could have been set in prepare function.
+ */
+ if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && !next_cmd_is_acmd) {
+ mmio_write_32(base + SDMMC_DCTRLR, 0U);
+ }
+
if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
}
@@ -446,10 +457,10 @@ static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
assert(cmd != NULL);
- for (retry = 0; retry <= 3; retry++) {
+ for (retry = 0U; retry < 3U; retry++) {
err = stm32_sdmmc2_send_cmd_req(cmd);
if (err == 0) {
- return err;
+ return 0;
}
if ((cmd->cmd_idx == MMC_CMD(1)) ||
@@ -459,8 +470,8 @@ static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
/* Command 8 is expected to fail for eMMC */
if (!(cmd->cmd_idx == MMC_CMD(8))) {
- WARN(" CMD%d, Retry: %d, Error: %d\n",
- cmd->cmd_idx, retry, err);
+ WARN(" CMD%u, Retry: %u, Error: %d\n",
+ cmd->cmd_idx, retry + 1U, err);
}
udelay(10);
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index a1e6e6b86..908c538aa 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -76,3 +76,19 @@ int stm32mp_reset_deassert_to(uint32_t id, unsigned int to_us)
return 0;
}
+
+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ /*
+ * The RCC_MP_GCR is a read/write register.
+ * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
+ * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
+ */
+ if (assert_not_deassert) {
+ mmio_clrbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+ } else {
+ mmio_setbits_32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+ }
+}
diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c
index 216e324d5..568d6c4a4 100644
--- a/drivers/st/tamper/stm32_tamp.c
+++ b/drivers/st/tamper/stm32_tamp.c
@@ -11,6 +11,7 @@
#include <platform_def.h>
+#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_rng.h>
#include <drivers/st/stm32_rtc.h>
#include <drivers/st/stm32_tamp.h>
@@ -360,8 +361,10 @@ int stm32_tamp_init(void)
stm32_tamp_set_secured(stm32_tamp.base);
- if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) {
- stm32_tamp_configure_or(stm32_tamp.base, 1);
+ 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);
+ }
}
if (stm32_gic_enable_spi(node, NULL) < 0) {
diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c
index a4e178ec4..34f1f6206 100644
--- a/drivers/st/timer/stm32_timer.c
+++ b/drivers/st/timer/stm32_timer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -62,6 +62,7 @@
#define TIM_PRESCAL_HSI 10U
#define TIM_PRESCAL_CSI 7U
#define TIM_MIN_FREQ_CALIB 50000000U
+#define TIM_THRESHOLD 1U
struct stm32_timer_instance {
uintptr_t base;
@@ -127,8 +128,8 @@ static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer)
{
uint32_t timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US;
uint32_t counter = 0U;
- uint32_t old_counter = 0U;
- int twice = 0;
+ uint32_t old_counter;
+ uint64_t conv_timeout;
if (stm32_timer_config(timer) < 0) {
return 0U;
@@ -149,22 +150,29 @@ static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer)
mmio_write_32(timer->base + TIM_SR, 0U);
- while ((twice < 2) || (old_counter != counter)) {
- timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US;
+ conv_timeout = timeout_init_us(TIM_TIMEOUT_US);
+ do {
+ if (timeout_elapsed(conv_timeout)) {
+ WARN("Timer counter not stable\n");
+ timeout = 0U;
+ goto out;
+ }
+ timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US;
while (((mmio_read_32(timer->base + TIM_SR) &
TIM_SR_CC1IF) == 0U) && (timeout != 0U)) {
udelay(TIM_TIMEOUT_STEP_US);
timeout--;
}
+
if (timeout == 0U) {
goto out;
}
old_counter = counter;
counter = mmio_read_32(timer->base + TIM_CCR1);
- twice++;
- }
+ } while ((MAX(counter, old_counter) - MIN(counter, old_counter)) >
+ TIM_THRESHOLD);
out:
stm32mp_clk_disable(timer->clk);
diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c
index 6d024e158..01961a0e8 100644
--- a/drivers/st/uart/io_programmer_uart.c
+++ b/drivers/st/uart/io_programmer_uart.c
@@ -18,6 +18,7 @@
#include <drivers/st/io_stm32image.h>
#include <drivers/st/io_uart.h>
#include <drivers/st/stm32_iwdg.h>
+#include <lib/ssp_lib.h>
/* USART bootloader protocol version V4.0*/
#define USART_BL_VERSION 0x40
@@ -31,6 +32,9 @@ static const uint8_t command_tab[] = {
GET_VER_COMMAND,
GET_ID_COMMAND,
PHASE_COMMAND,
+#if STM32MP_SSP
+ READ_PART_COMMAND,
+#endif
START_COMMAND,
DOWNLOAD_COMMAND
};
@@ -195,8 +199,10 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
int result = -EIO;
const struct stm32image_part_info *partition_spec =
(struct stm32image_part_info *)spec;
+#if !STM32MP_SSP
uint32_t length = 0;
uint32_t layout_length = 0;
+#endif
/* Use PHASE_FSBL1 like init value*/
if (current_phase.phase_id == PHASE_FSBL1) {
@@ -205,6 +211,7 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
current_phase.current_packet = 0;
+#if !STM32MP_SSP
if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) {
/* read flashlayout first for U-boot */
current_phase.phase_id = PHASE_FLASHLAYOUT;
@@ -224,6 +231,18 @@ static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
current_phase.max_size = dt_get_ddr_size();
current_phase.keep_header = 0;
}
+#else
+ if (!strcmp(partition_spec->name, "SSP")) {
+ current_phase.phase_id = SSP_PHASE;
+ header_length_read = 0;
+ }
+
+ if (!strcmp(partition_spec->name, "SSP_INIT")) {
+ current_phase.phase_id = RESET_PHASE;
+ header_length_read = 0;
+ }
+#endif
+
entity->info = (uintptr_t)&current_phase;
result = 0;
} else {
@@ -303,17 +322,128 @@ static int get_id_command(void)
return 0;
}
-static int uart_send_phase(uint32_t address)
+static int uart_send_phase(uint32_t address, size_t length)
{
- uart_write_byte(0x05); /* length of data - 1 */
+ size_t local_length = 0;
+ uint32_t i;
+
+ if (current_phase.phase_id == RESET_PHASE) {
+ local_length = length;
+ }
+
+ if ((local_length + 5U) > UINT8_MAX) {
+ return -EINVAL;
+ }
+
+ uart_write_byte(local_length + 5U); /* length of data - 1 */
+
/* Send the ID of next partition */
uart_write_byte(current_phase.phase_id); /* partition ID */
uart_write_uint32(address); /* destination address */
- uart_write_byte(0x00); /* length of extra data */
+
+ uart_write_byte(local_length); /* length of extra data */
+
+ for (i = 0; i < local_length; i++) {
+ uart_write_byte(((char *)address)[i]);
+ }
+
+ return 0;
+}
+
+#if STM32MP_SSP
+static int uart_read_part(uint8_t *buffer, size_t length, size_t *length_read)
+{
+ uint8_t byte = 0U;
+ uint8_t xor = 0U;
+ uint8_t partid = 0U;
+ uint16_t size = 0U;
+ uint32_t start_address = 0U;
+ uint32_t i;
+
+ /* Get partition id */
+ if (uart_read_byte(&partid) != 0) {
+ return -EIO;
+ }
+
+ if (partid != SSP_PART_ID) {
+ return -EPERM;
+ }
+
+ xor = partid;
+
+ /* Get address */
+ for (i = 4U; i > 0U; i--) {
+ if (uart_read_byte(&byte) != 0) {
+ return -EIO;
+ }
+
+ xor ^= byte;
+ start_address = (start_address << 8) | byte;
+ }
+
+ /* Checksum */
+ if (uart_read_byte(&byte) != 0) {
+ return -EIO;
+ }
+
+ if (xor != byte) {
+ WARN("UART: Start cmd: address checksum: %x != %x\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ uart_write_byte(ACK_BYTE);
+
+ /* Get number of bytes to send */
+ if (uart_read_byte(&byte) != 0) {
+ return -EIO;
+ }
+
+ xor = byte;
+
+ /* Send Size + 1 */
+ size = byte++;
+
+ /* Checksum */
+ if (uart_read_byte(&byte) != 0) {
+ return -EIO;
+ }
+
+ if ((xor ^ byte) != 0xFF) {
+ WARN("UART: Start cmd: length checksum: %x != %x\n", xor, byte);
+ return -EPROTO;
+ }
+
+ uart_write_byte(ACK_BYTE);
+
+ switch (partid) {
+ case SSP_PART_ID:
+ if ((start_address != 0U) ||
+ (size < (SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t)))) {
+ return -EIO;
+ }
+
+ for (i = 0U;
+ i < (SSP_KEY_CERTIFICATE_SIZE * sizeof(uint32_t));
+ i++, buffer++) {
+ uart_write_byte(*buffer);
+ }
+
+ for (; i < size; i++) {
+ uart_write_byte(0x0);
+ }
+
+ break;
+
+ default:
+ WARN("Not supported\n");
+ return -EPROTO;
+ }
return 0;
}
+#endif /* STM32MP_SSP */
static int uart_download_part(uint8_t *buffer, uint32_t *length_read)
{
@@ -325,15 +455,23 @@ static int uart_download_part(uint8_t *buffer, uint32_t *length_read)
int i = 0;
volatile uint8_t *ptr = (uint8_t *)buffer;
- /* get operation number */
- if (uart_read_byte(&operation))
+ /* Get operation number */
+ if (uart_read_byte(&operation) != 0) {
return -EIO;
+ }
+
xor = operation;
- /* get packet Number */
- for (i = 3, byte = 0; i > 0; i--) {
- if (uart_read_byte(&byte))
+ if ((operation != 0x0) && (operation != 0xF3)) {
+ return -EPERM;
+ }
+
+ /* Get packet number */
+ for (i = 3; i > 0; i--) {
+ if (uart_read_byte(&byte) != 0) {
return -EIO;
+ }
+
xor ^= byte;
packet_number = (packet_number << 8) | byte;
}
@@ -430,6 +568,12 @@ static int uart_start_cmd(boot_api_image_header_t *header, uintptr_t buffer)
return stm32mp_check_header(header, buffer);
+#if STM32MP_SSP
+ case SSP_PHASE:
+ current_phase.phase_id = RESET_PHASE;
+ break;
+#endif
+
default:
ERROR("Invalid phase ID : %i\n", current_phase.phase_id);
return -EINVAL;
@@ -447,6 +591,9 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
uint32_t ptr_offset = 0;
uint8_t command = 0;
uint8_t all_commands_done = 0;
+#if STM32MP_SSP
+ ssp_exchange_t *exchange = (ssp_exchange_t *)buffer;
+#endif
boot_api_image_header_t *header =
(boot_api_image_header_t *)&header_buffer[0];
@@ -456,7 +603,7 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
ptr_offset += header_length_read;
} else if (header_length_read &&
((header_length_read -
- sizeof(boot_api_image_header_t)) > 0)) {
+ sizeof(boot_api_image_header_t)) >= 0)) {
#if TRUSTED_BOARD_BOOT
stm32mp_save_loaded_header(header_buffer);
#endif
@@ -508,12 +655,44 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
break;
case PHASE_COMMAND:
- result = uart_send_phase((uint32_t)buffer);
+ result = uart_send_phase((uint32_t)buffer, length);
+#if STM32MP_SSP
+ if (current_phase.phase_id == RESET_PHASE) {
+ all_commands_done = 1;
+ }
+#endif
break;
+#if STM32MP_SSP
+ case READ_PART_COMMAND:
+ result = uart_read_part((uint8_t *)(buffer), length,
+ length_read);
+
+ if (result == 0) {
+ /* No ACK_BYTE needed */
+ continue;
+ }
+
+ break;
+#endif
+
case DOWNLOAD_COMMAND:
- result = uart_download_part((uint8_t *)(buffer +
- ptr_offset),
+#if STM32MP_SSP
+ result = uart_download_part((uint8_t *)
+ (exchange->blob +
+ ptr_offset),
+ &read_length);
+ if (!result) {
+ ptr_offset += read_length;
+ total_length += read_length;
+ if (total_length > length) {
+ /* Buffer too long */
+ all_commands_done = 1;
+ }
+ }
+#else
+ result = uart_download_part((uint8_t *)
+ (buffer + ptr_offset),
&read_length);
if (!result) {
ptr_offset += read_length;
@@ -524,6 +703,7 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
all_commands_done = 1;
}
}
+#endif
break;
@@ -531,7 +711,6 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
result = uart_start_cmd(header, buffer);
if (!result)
all_commands_done = 1;
-
break;
default:
@@ -557,8 +736,7 @@ static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
*length_read = total_length;
INFO("Read block in buffer 0x%lx size 0x%x phase ID %i\n",
- buffer, length, current_phase.phase_id);
-
+ buffer, *length_read, current_phase.phase_id);
return 0;
}
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index 6e6dff4f7..6aaa9f58f 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -41,7 +41,12 @@
<&nand_otp>,
<&uid_otp>,
<&package_otp>,
- <&hw2_otp>;
+ <&hw2_otp>,
+ <&pkh_otp>,
+ <&cfg2_otp>,
+ <&ssp_otp>,
+ <&chip_otp>,
+ <&rma_otp>;
nvmem-cell-names = "cfg0_otp",
"part_number_otp",
@@ -49,7 +54,12 @@
"nand_otp",
"uid_otp",
"package_otp",
- "hw2_otp";
+ "hw2_otp",
+ "pkh_otp",
+ "cfg2_otp",
+ "ssp_otp",
+ "chip_otp",
+ "rma_otp";
};
psci {
@@ -298,19 +308,34 @@
secure-status = "disabled";
};
- fmc: nand-controller@58002000 {
- compatible = "st,stm32mp15-fmc2";
- reg = <0x58002000 0x1000>,
- <0x80000000 0x1000>,
- <0x88010000 0x1000>,
- <0x88020000 0x1000>,
- <0x81000000 0x1000>,
- <0x89010000 0x1000>,
- <0x89020000 0x1000>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ fmc: memory-controller@58002000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "st,stm32mp1-fmc2-ebi";
+ reg = <0x58002000 0x1000>;
clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>;
status = "disabled";
+
+ ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
+ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
+ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
+ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
+ <4 0 0x80000000 0x10000000>; /* NAND */
+
+ nand-controller@4,0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32mp1-fmc2-nfc";
+ reg = <4 0x00000000 0x1000>,
+ <4 0x08010000 0x1000>,
+ <4 0x08020000 0x1000>,
+ <4 0x01000000 0x1000>,
+ <4 0x09010000 0x1000>,
+ <4 0x09020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
};
qspi: spi@58003000 {
@@ -456,9 +481,15 @@
part_number_otp: part_number_otp@4 {
reg = <0x4 0x1>;
};
+ cfg2_otp: cfg2_otp@8 {
+ reg = <0x8 0x4>;
+ };
monotonic_otp: monotonic_otp@10 {
reg = <0x10 0x4>;
};
+ ssp_otp: ssp_otp@20 {
+ reg = <0x20 0x4>;
+ };
nand_otp: nand_otp@24 {
reg = <0x24 0x4>;
};
@@ -480,6 +511,12 @@
pkh_otp: pkh_otp@60 {
reg = <0x60 0x20>;
};
+ chip_otp: chip_otp@a0 {
+ reg = <0xa0 0x40>;
+ };
+ rma_otp: rma_otp@e0 {
+ reg = <0xe0 0x4>;
+ };
mac_addr: mac_addr@e4 {
reg = <0xe4 0x8>;
st,non-secure-otp;
diff --git a/fdts/stm32mp157a-avenger96.dts b/fdts/stm32mp157a-avenger96.dts
index d9b3d1d8f..2efd0d3c5 100644
--- a/fdts/stm32mp157a-avenger96.dts
+++ b/fdts/stm32mp157a-avenger96.dts
@@ -46,8 +46,8 @@
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts
index 4d506bce5..5d5c0a5f7 100644
--- a/fdts/stm32mp157a-dk1.dts
+++ b/fdts/stm32mp157a-dk1.dts
@@ -36,8 +36,8 @@
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157a-ed1.dts b/fdts/stm32mp157a-ed1.dts
index 4f84ec623..9da3e307e 100644
--- a/fdts/stm32mp157a-ed1.dts
+++ b/fdts/stm32mp157a-ed1.dts
@@ -37,8 +37,8 @@
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts
index 436a15970..ff5c4509f 100644
--- a/fdts/stm32mp157c-dk2.dts
+++ b/fdts/stm32mp157c-dk2.dts
@@ -42,8 +42,8 @@
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index 5aadb1ff0..a1e72f816 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -42,8 +42,8 @@
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157d-dk1.dts b/fdts/stm32mp157d-dk1.dts
index d320f993e..078bc717b 100644
--- a/fdts/stm32mp157d-dk1.dts
+++ b/fdts/stm32mp157d-dk1.dts
@@ -40,8 +40,8 @@
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157d-ed1.dts b/fdts/stm32mp157d-ed1.dts
index 76f0614d6..961e43d6a 100644
--- a/fdts/stm32mp157d-ed1.dts
+++ b/fdts/stm32mp157d-ed1.dts
@@ -37,8 +37,8 @@
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157f-dk2.dts b/fdts/stm32mp157f-dk2.dts
index 9c79bfb43..a8ed842e4 100644
--- a/fdts/stm32mp157f-dk2.dts
+++ b/fdts/stm32mp157f-dk2.dts
@@ -46,8 +46,8 @@
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp157f-ed1.dts b/fdts/stm32mp157f-ed1.dts
index a659cf84d..729dae8af 100644
--- a/fdts/stm32mp157f-ed1.dts
+++ b/fdts/stm32mp157f-ed1.dts
@@ -42,8 +42,8 @@
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
- DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
- DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
+ DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index 53790f29b..65e8efa83 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -210,7 +210,7 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
standby-ddr-sr {
- regulator-on-in-suspend;
+ regulator-off-in-suspend;
};
standby-ddr-off {
regulator-off-in-suspend;
@@ -289,7 +289,11 @@
<&package_otp>,
<&hw2_otp>,
<&pkh_otp>,
- <&board_id>;
+ <&board_id>,
+ <&cfg2_otp>,
+ <&ssp_otp>,
+ <&chip_otp>,
+ <&rma_otp>;
nvmem-cell-names = "cfg0_otp",
"part_number_otp",
@@ -299,7 +303,11 @@
"package_otp",
"hw2_otp",
"pkh_otp",
- "board_id";
+ "board_id",
+ "cfg2_otp",
+ "ssp_otp",
+ "chip_otp",
+ "rma_otp";
};
&pwr_regulators {
diff --git a/fdts/stm32mp15xx-edx.dtsi b/fdts/stm32mp15xx-edx.dtsi
index dd921908b..2cf25dda6 100644
--- a/fdts/stm32mp15xx-edx.dtsi
+++ b/fdts/stm32mp15xx-edx.dtsi
@@ -215,7 +215,7 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
standby-ddr-sr {
- regulator-on-in-suspend;
+ regulator-off-in-suspend;
};
standby-ddr-off {
regulator-off-in-suspend;
@@ -296,7 +296,11 @@
<&package_otp>,
<&hw2_otp>,
<&pkh_otp>,
- <&board_id>;
+ <&board_id>,
+ <&cfg2_otp>,
+ <&ssp_otp>,
+ <&chip_otp>,
+ <&rma_otp>;
nvmem-cell-names = "cfg0_otp",
"part_number_otp",
@@ -306,7 +310,11 @@
"package_otp",
"hw2_otp",
"pkh_otp",
- "board_id";
+ "board_id",
+ "cfg2_otp",
+ "ssp_otp",
+ "chip_otp",
+ "rma_otp";
};
&pwr_regulators {
diff --git a/fdts/stm32mp15xx-evx.dtsi b/fdts/stm32mp15xx-evx.dtsi
index fee2bac86..d8fa8b378 100644
--- a/fdts/stm32mp15xx-evx.dtsi
+++ b/fdts/stm32mp15xx-evx.dtsi
@@ -8,14 +8,16 @@
pinctrl-names = "default";
pinctrl-0 = <&fmc_pins_a>;
status = "okay";
- #address-cells = <1>;
- #size-cells = <0>;
- nand@0 {
- reg = <0>;
- nand-on-flash-bbt;
- #address-cells = <1>;
- #size-cells = <1>;
+ nand-controller@4,0 {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/include/drivers/raw_nand.h b/include/drivers/raw_nand.h
index 9018f0242..532c2b495 100644
--- a/include/drivers/raw_nand.h
+++ b/include/drivers/raw_nand.h
@@ -169,7 +169,7 @@ struct rawnand_device {
};
int nand_raw_init(unsigned long long *size, unsigned int *erase_size);
-int nand_wait_ready(unsigned long delay);
+int nand_wait_ready(unsigned long delay_ms);
int nand_read_page_cmd(unsigned int page, unsigned int offset,
uintptr_t buffer, unsigned int len);
int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer,
diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h
index c0ed06f6e..4cc3b206f 100644
--- a/include/drivers/st/etzpc.h
+++ b/include/drivers/st/etzpc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,9 @@
#ifndef __ETZPC_H__
#define __ETZPC_H__
+#include <stdbool.h>
+#include <stdint.h>
+
/* Define security level for each peripheral (DECPROT) */
enum etzpc_decprot_attributes {
TZPC_DECPROT_S_RW = 0,
diff --git a/include/drivers/st/io_programmer.h b/include/drivers/st/io_programmer.h
index c6c2de10f..6f3fd4409 100644
--- a/include/drivers/st/io_programmer.h
+++ b/include/drivers/st/io_programmer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,12 +12,18 @@
#define PHASE_FSBL1 1
#define PHASE_FSBL2 2
#define PHASE_SSBL 3
+#define RESET_PHASE 0xFF
+
+#if STM32MP_SSP
+#define SSP_PHASE 0xF3
+#endif
/* Command definition */
#define GET_CMD_COMMAND 0x00
#define GET_VER_COMMAND 0x01
#define GET_ID_COMMAND 0x02
#define PHASE_COMMAND 0x03
+#define READ_PART_COMMAND 0x12
#define START_COMMAND 0x21
#define DOWNLOAD_COMMAND 0x31
diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h
index 7114dddf0..a672b93a6 100644
--- a/include/drivers/st/stm32mp_reset.h
+++ b/include/drivers/st/stm32mp_reset.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -47,4 +47,11 @@ static inline void stm32mp_reset_release(uint32_t reset_id)
(void)stm32mp_reset_deassert_to(reset_id, 0);
}
+/*
+ * Manage reset control for the MCU reset
+ *
+ * @assert_not_deassert: reset requested state
+ */
+void stm32mp_reset_assert_deassert_to_mcu(bool assert_not_deassert);
+
#endif /* STM32MP_RESET_H */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index bc71924fa..f3a0ed317 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -7,6 +7,7 @@
#ifndef _DT_BINDINGS_STM32MP1_RESET_H_
#define _DT_BINDINGS_STM32MP1_RESET_H_
+#define MCU_HOLD_BOOT_R 2144
#define LTDC_R 3072
#define DSI_R 3076
#define DDRPERFM_R 3080
@@ -117,5 +118,6 @@
#define RST_SCMI0_RNG1 8
#define RST_SCMI0_MDMA 9
#define RST_SCMI0_MCU 10
+#define RST_SCMI0_MCU_HOLD_BOOT 11
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 7f7b7e3ff..5c51754c1 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -349,6 +349,7 @@ int psci_node_hw_state(u_register_t target_cpu,
int psci_features(unsigned int psci_fid);
void __dead2 psci_power_down_wfi(void);
void psci_arch_setup(void);
+unsigned int psci_is_last_on_cpu(void);
#endif /*__ASSEMBLER__*/
diff --git a/include/lib/ssp_lib.h b/include/lib/ssp_lib.h
new file mode 100644
index 000000000..26232d13c
--- /dev/null
+++ b/include/lib/ssp_lib.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SSP_LIB_H
+#define SSP_LIB_H
+#include <boot_api.h>
+
+/* Constants */
+#define SSP_BLOB_FILE_MAX_ADDR (BL2_RW_LIMIT - PLAT_XLAT_SIZE)
+#define SSP_KEY_CERTIFICATE_SIZE U(34) // 4 * 34 bytes : 136 bytes
+#define SSP_PART_ID 0xF3
+
+/*
+ * SSP message format for flashloader exchange.
+ *
+ * msg: Message containing public key and certificate.
+ * blob: Output buffer for encrypted file.
+ */
+typedef struct ssp_exchange {
+ uint32_t msg[SSP_KEY_CERTIFICATE_SIZE];
+ uint8_t *blob;
+} ssp_exchange_t __aligned(4);
+
+/*
+ * Start the SSP processing.
+ *
+ * Parameters:
+ * boot_context : Shared boot_context
+ */
+void ssp_start(boot_api_context_t *boot_context);
+
+#endif /* SSP_LIB_H */
diff --git a/include/lib/usb/usb_st_dfu.h b/include/lib/usb/usb_st_dfu.h
index 8a3a5a505..57f4e8ff1 100644
--- a/include/lib/usb/usb_st_dfu.h
+++ b/include/lib/usb/usb_st_dfu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -89,7 +89,11 @@ typedef enum {
typedef void (*p_function)(void);
typedef struct {
+#if STM32MP_SSP
+ uint8_t buffer[512];
+#else
uint8_t buffer[10];
+#endif
uint8_t dev_state;
uint8_t dev_status[DFU_STATUS_DEPTH];
uint8_t manif_state;
@@ -101,16 +105,18 @@ typedef struct {
typedef struct {
uint16_t (*write_done)(uint32_t *written_in, uint32_t len);
- uint8_t* (*read)(uint8_t *src, uint8_t *dest, uint32_t len);
+ uint16_t (*read)(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t (*get_status)(void);
} usb_dfu_media_t;
void usb_dfu_register_callback(usb_handle_t *pdev);
void usb_dfu_set_phase_id(uint32_t phase_id);
void usb_dfu_set_download_addr(uintptr_t addr);
+void usb_dfu_set_upload_addr(uintptr_t addr);
uint32_t usb_dfu_download_is_completed(void);
uint32_t usb_dfu_get_current_req(void);
uint32_t usb_dfu_detach_req(void);
void usb_dfu_request_detach(void);
+void usb_dfu_error_msg_size(uint32_t size);
#endif /* USB_ST_DFU_H */
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index b49847c95..795fcb3d3 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -285,7 +285,6 @@ unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info);
unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info);
void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl);
void psci_print_power_domain_map(void);
-unsigned int psci_is_last_on_cpu(void);
int psci_spd_migrate_info(u_register_t *mpidr);
void psci_do_pwrdown_sequence(unsigned int power_level);
diff --git a/lib/ssp/ssp.c b/lib/ssp/ssp.c
new file mode 100644
index 000000000..dff8bfefd
--- /dev/null
+++ b/lib/ssp/ssp.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <endian.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <drivers/io/io_driver.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/io_stm32image.h>
+#include <drivers/st/stm32mp_pmic.h>
+#include <drivers/st/stm32_hash.h>
+#include <drivers/st/stpmic1.h>
+#include <lib/mmio.h>
+#include <lib/ssp_lib.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+/* Local status for SSP processing sequences */
+typedef enum {
+ SSP_NONE,
+ SSP_GET_CERT,
+ SSP_FLASH_OEM,
+ SSP_DONE,
+ SSP_ERROR
+} ssp_result_e;
+
+struct otp_val {
+ uint32_t idx;
+ uint32_t nb;
+};
+
+static struct otp_val otp_ssp;
+static struct otp_val otp_rma;
+static struct otp_val otp_pubkey;
+
+static int initialize_otp(void)
+{
+ uint32_t len;
+
+ /* OTP SSP */
+ if (stm32_get_otp_index(SSP_OTP, &otp_ssp.idx, NULL) != 0) {
+ VERBOSE("%s: get index error\n", __func__);
+ return -EINVAL;
+ }
+
+ /* OTP public key */
+ if (stm32_get_otp_index(PKH_OTP, &(otp_pubkey.idx), &len) != 0) {
+ VERBOSE("%s: get index error\n", __func__);
+ return -EINVAL;
+ }
+
+ if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) {
+ VERBOSE("%s: length Error\n", __func__);
+ return -EINVAL;
+ }
+
+ otp_pubkey.nb = len / (CHAR_BIT * sizeof(uint32_t));
+
+ /* OTP RMA */
+ if (stm32_get_otp_index(RMA_OTP, &otp_rma.idx, NULL) != 0) {
+ VERBOSE("%s: get index error\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Return device handler for flashloader interface.
+ */
+static int ssp_get_loader_handle(uintptr_t *dev_handle, uintptr_t *dev_spec)
+{
+ int result;
+
+ /* Obtain a reference to the image handle to get boot device */
+ result = plat_get_image_source(BL33_IMAGE_ID, dev_handle, dev_spec);
+ if (result != 0) {
+ WARN("Failed to obtain reference to image '%s' (%i)\n",
+ BL33_IMAGE_NAME, result);
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/*
+ * Compute HASH from public key and burn it in OTP.
+ */
+static int ssp_pub_key_prog(boot_api_context_t *boot_context)
+{
+ uint8_t key_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ uint8_t *pubk = (uint8_t *)
+ boot_context->p_ssp_config->p_blob_payload->oem_ecdsa_pubk;
+ uint32_t *value = (uint32_t *)key_hash;
+ uint32_t i;
+
+ if (stm32_hash_register() != 0) {
+ return -EINVAL;
+ }
+
+ stm32_hash_init(HASH_SHA256);
+
+ if (stm32_hash_final_update(pubk, BOOT_API_SSP_PUBK_KEY_SIZE_BYTES,
+ key_hash) != 0) {
+ ERROR("Hash of payload failed\n");
+ return -EINVAL;
+ }
+
+ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) {
+ if (bsec_program_otp(bswap32(*value), i) != BSEC_OK) {
+ return -EINVAL;
+ }
+
+ value++;
+ if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+ ERROR("Error locking OTP %i\n", i);
+ panic();
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Burn OTP to close device.
+ */
+static int ssp_close_device(void)
+{
+ uint32_t otp;
+ uint32_t value;
+
+ if (stm32_get_otp_index(CFG0_OTP, &otp, NULL) != 0) {
+ return -EINVAL;
+ }
+
+ if (bsec_read_otp(&value, otp) != BSEC_OK) {
+ return -EINVAL;
+ }
+
+ if ((value & CFG0_CLOSED_DEVICE) != 0U) {
+ ERROR("Device already closed\n");
+ return -EINVAL;
+ }
+
+ value |= CFG0_CLOSED_DEVICE;
+ if (bsec_program_otp(value, otp) != BSEC_OK) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * OTP initial check to detect previous values.
+ */
+static int ssp_secrets_check(boot_api_context_t *boot_ctx)
+{
+ uint32_t i;
+ uint32_t check_val;
+ uint32_t otp_byte =
+ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes;
+ uint32_t otp_decrypted = round_up(otp_byte, sizeof(uint32_t)) /
+ sizeof(uint32_t);
+
+ for (i = otp_pubkey.idx; i < (otp_pubkey.idx + otp_pubkey.nb); i++) {
+ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) {
+ return -EINVAL;
+ }
+
+ if (check_val != 0U) {
+ ERROR("OTP %d value already programmed\n", i);
+ return -EINVAL;
+ }
+ }
+
+ /* OTP decrypted include RMA password */
+ if (otp_decrypted > (2U + SSP_OTP_SECRET_END - SSP_OTP_SECRET_BASE)) {
+ return -EINVAL;
+ }
+
+ /* Check RMA password */
+ if (stm32_get_otp_value_from_idx(otp_rma.idx, &check_val) != 0) {
+ return -EINVAL;
+ }
+
+ if (check_val != 0U) {
+ ERROR("OTP %s value already programmed\n", RMA_OTP);
+ return -EINVAL;
+ }
+
+ /* Check all OTP available */
+ for (i = SSP_OTP_SECRET_BASE;
+ i < SSP_OTP_SECRET_BASE + otp_decrypted - 1; i++) {
+ if (stm32_get_otp_value_from_idx(i, &check_val) != 0) {
+ return -EINVAL;
+ }
+
+ if (check_val != 0U) {
+ ERROR("OTP %d value already programmed\n", i);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Burn OTP with the decrypted secret received.
+ */
+static int ssp_secrets_flash(boot_api_context_t *boot_ctx)
+{
+ uint32_t i;
+ uint32_t *val;
+ uint32_t otp_byte =
+ boot_ctx->p_ssp_config->p_blob_payload->oem_secret_size_bytes;
+ uint32_t otp_decrypted = round_up(otp_byte, sizeof(uint32_t)) /
+ sizeof(uint32_t);
+ uint32_t otp_mask = 0U;
+
+ if (otp_byte % sizeof(uint32_t) != 0U) {
+ otp_mask = GENMASK_32(((otp_byte % sizeof(uint32_t)) *
+ sizeof(uint32_t)) - 1, 0);
+ }
+
+ val = (uint32_t *)boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted;
+
+ /* Burn RMA password */
+ if (otp_decrypted != 0U) {
+ if (bsec_program_otp((*val & RMA_OTP_MASK), otp_rma.idx) !=
+ BSEC_OK) {
+ WARN("RMA programing failed\n");
+ return -EINVAL;
+ }
+
+ val++;
+ otp_decrypted--;
+
+ for (i = SSP_OTP_SECRET_BASE;
+ i < (SSP_OTP_SECRET_BASE + otp_decrypted - 1); i++) {
+
+ if (*val == 0U) {
+ val++;
+ continue;
+ }
+
+ if (bsec_program_otp(*val, i) != BSEC_OK) {
+ WARN("Error writing OTP %i\n", i);
+ return -EINVAL;
+ }
+
+ if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+ WARN("Error locking OTP %i\n", i);
+ return -EINVAL;
+ }
+
+ val++;
+ }
+
+ if (*val != 0U) {
+ /* Mask the last OTP value if needed */
+ if (otp_mask != 0U) {
+ *val &= otp_mask;
+ }
+
+ if (bsec_program_otp(*val, i) != BSEC_OK) {
+ WARN("Error writing OTP %i\n", i);
+ return -EINVAL;
+ }
+
+ if (bsec_permanent_lock_otp(i) != BSEC_OK) {
+ WARN("Error locking OTP %i\n", i);
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Finish SSP processing by fusing OTP SSP success.
+ */
+static int ssp_finish_process(void)
+{
+ uint32_t val;
+
+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) {
+ return -EINVAL;
+ }
+
+ if ((val & SSP_OTP_SUCCESS) != 0U) {
+ WARN("Error while configuring OTP\n");
+ return -EINVAL;
+ }
+
+ val |= SSP_OTP_SUCCESS;
+ if (bsec_program_otp(val, otp_ssp.idx) != BSEC_OK) {
+ return -EINVAL;
+ }
+
+ VERBOSE("Write OTP Success\n");
+
+ return 0;
+}
+
+/*
+ * Transform integer to string.
+ */
+static void itoa(uint32_t num, char *str, int nb)
+{
+ if (num == 0U) {
+ while (nb--) {
+ str[nb] = '0';
+ }
+ return;
+ }
+
+ while (num != 0U) {
+ int rem = num % 16;
+
+ str[--nb] = (rem > 9) ? (rem - 10) + 'A' : rem + '0';
+ num /= 16;
+ }
+
+ while (nb != 0) {
+ str[--nb] = '0';
+ }
+}
+
+/*
+ * Return chip product ID.
+ */
+static int ssp_get_product_id(char *msg)
+{
+ uint32_t otp;
+ uint32_t otp_idx;
+ uint32_t chip_id;
+
+ if (stm32_get_otp_index(CFG2_OTP, &otp_idx, NULL) != 0) {
+ VERBOSE("Get index error\n");
+ return -EINVAL;
+ }
+
+ if (stm32_get_otp_value_from_idx(otp_idx, &otp) != 0) {
+ return -EINVAL;
+ }
+
+ if (stm32mp1_dbgmcu_get_chip_dev_id(&chip_id) < 0) {
+ return -EINVAL;
+ }
+
+ itoa(chip_id, msg, 3);
+ itoa((otp & OTP_CFG2_SEC_COUNTER_MASK) >>
+ OTP_CFG2_SEC_COUNTER_SHIFT, msg + 3, 2);
+
+ itoa(0, msg + 5, 1);
+ itoa((otp & OTP_CFG2_ST_KEY_MASK) >>
+ OTP_CFG2_ST_KEY_SHIFT, msg + 6, 2);
+
+ return 0;
+}
+
+/*
+ * Clean external data and bootrom context secret values.
+ */
+static void ssp_cleanup(boot_api_context_t *boot_context)
+{
+ boot_api_ssp_config_t *ssp_config = boot_context->p_ssp_config;
+
+ /* Cleanup boot_context */
+ if (ssp_config->p_ssp_oem_secrets_decrypted != NULL) {
+ zeromem(ssp_config->p_ssp_oem_secrets_decrypted,
+ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES);
+ zeromem(ssp_config->p_chip_pubk,
+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+ zeromem(ssp_config->p_blob_license,
+ sizeof(boot_api_ssp_blob_license_t));
+ zeromem(ssp_config->p_blob_payload,
+ sizeof(boot_api_ssp_blob_payload_t));
+ }
+
+ ssp_config->ssp_cmd = 0U;
+
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)ssp_config->p_ssp_oem_secrets_decrypted,
+ BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES);
+
+ flush_dcache_range((uintptr_t)ssp_config->p_chip_pubk,
+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+
+ flush_dcache_range((uintptr_t)ssp_config->p_blob_license,
+ sizeof(boot_api_ssp_blob_license_t));
+
+ flush_dcache_range((uintptr_t)ssp_config->p_blob_payload,
+ sizeof(boot_api_ssp_blob_payload_t));
+#endif
+
+ ssp_config->p_ssp_oem_secrets_decrypted = NULL;
+ ssp_config->p_chip_pubk = NULL;
+ ssp_config->p_blob_license = NULL;
+ ssp_config->p_blob_payload = NULL;
+
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)boot_context,
+ sizeof(boot_api_context_t));
+
+ flush_dcache_range((uintptr_t)ssp_config,
+ sizeof(boot_api_ssp_config_t));
+#endif
+}
+
+/*
+ * Send certificate to the programmer and retrieve the associated
+ * encrypted file.
+ */
+static int ssp_download_phase(boot_api_context_t *boot_ctx)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t otp;
+ uint32_t otp_idx;
+ uint32_t otp_len;
+ uint8_t *blob_file;
+ int result = 0;
+ uintptr_t dev_handle, handle, dev_spec;
+ size_t length_read;
+ struct stm32image_part_info partition_spec = {
+ .name = "SSP"
+ };
+
+ blob_file = (uint8_t *)page_align(SSP_BLOB_FILE_MAX_ADDR -
+ sizeof(boot_api_ssp_blob_license_t) -
+ sizeof(boot_api_ssp_blob_payload_t),
+ DOWN);
+
+ ssp_exchange_t flash_exch = {
+ .blob = blob_file
+ };
+
+ /* Prepare the ROM Security constant */
+ if (ssp_get_product_id((char *)flash_exch.msg) != 0) {
+ return -EINVAL;
+ }
+
+ /* Prepare public key and certificate for flashloader */
+ /* Read Public Key from boot_context */
+ memcpy((uint8_t *)flash_exch.msg + 8,
+ boot_ctx->p_ssp_config->p_chip_pubk,
+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES);
+
+ if (stm32_get_otp_index(CHIP_CERTIFICATE_OTP,
+ &otp_idx, &otp_len) != 0) {
+ VERBOSE("Get index error\n");
+ return -EINVAL;
+ }
+
+ if (otp_len != (CHAR_BIT * CHIP_CERTIFICATE_MAX_SIZE)) {
+ VERBOSE("Length Error\n");
+ return -EINVAL;
+ }
+
+ otp_len /= (CHAR_BIT * sizeof(uint32_t));
+
+ /* Read Certificat from OTP */
+ for (i = otp_idx, j = 0; i < (otp_idx + otp_len); i++, j++) {
+ stm32_get_otp_value_from_idx(i, &otp);
+ flash_exch.msg[18 + j] = bswap32(otp);
+ }
+
+ if (ssp_get_loader_handle(&dev_handle, &dev_spec) != 0) {
+ WARN("Error while retrieving handle\n");
+ return -ENOENT;
+ }
+
+ result = io_open(dev_handle, (uintptr_t)&partition_spec, &handle);
+ if (result != 0) {
+ WARN("SSP io open error %i\n", result);
+ return -EINVAL;
+ }
+
+ result = io_read(handle, (uintptr_t)&flash_exch,
+ sizeof(boot_api_ssp_blob_license_t) +
+ sizeof(boot_api_ssp_blob_payload_t),
+ &length_read);
+ if (result != 0) {
+ WARN("SSP read command error %i\n", result);
+ return -EINVAL;
+ }
+
+ boot_ctx->p_ssp_config->p_blob_license =
+ (boot_api_ssp_blob_license_t *)blob_file;
+
+ /* Payload is concatene with license file */
+ boot_ctx->p_ssp_config->p_blob_payload =
+ (boot_api_ssp_blob_payload_t *)(blob_file +
+ sizeof(boot_api_ssp_blob_license_t));
+
+ /* Set return address for decrypted_secrets */
+ boot_ctx->p_ssp_config->p_ssp_oem_secrets_decrypted =
+ boot_ctx->p_ssp_config->p_blob_payload->oem_encrypted_secrets;
+
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)boot_ctx->p_ssp_config->p_blob_license,
+ sizeof(boot_api_ssp_blob_license_t));
+ flush_dcache_range((uintptr_t)boot_ctx->p_ssp_config->p_blob_payload,
+ sizeof(boot_api_ssp_blob_payload_t));
+#endif
+ result = io_close(handle);
+
+ return result;
+}
+
+/*
+ * Burn decrypted secrets into OTP, clean memory and close the device.
+ */
+static int ssp_secret_programming(boot_api_context_t *boot_context)
+{
+ int result;
+
+ result = ssp_secrets_check(boot_context);
+ if (result != 0) {
+ WARN("SSP ERROR checking OTP\n");
+ goto clean;
+ }
+
+ result = ssp_pub_key_prog(boot_context);
+ if (result != 0) {
+ WARN("SSP ERROR writing HASH key\n");
+ goto clean;
+ }
+
+ result = ssp_close_device();
+ if (result != 0) {
+ WARN("SSP close device failed\n");
+ goto clean;
+ }
+
+ result = ssp_secrets_flash(boot_context);
+ if (result != 0) {
+ WARN("SSP Secret flash failed\n");
+ }
+
+clean:
+ ssp_cleanup(boot_context);
+
+ if (result != 0) {
+ return result;
+ }
+
+ return ssp_finish_process();
+}
+
+/*
+ * Enable the SSP processing.
+ */
+static int ssp_enable_processing(boot_api_context_t *boot_context)
+{
+ static const char buf_err[] = "Provisioning";
+ uint32_t val;
+ int result;
+ uintptr_t dev_handle, handle, dev_spec;
+ size_t length_read;
+ struct stm32image_part_info partition_spec = {
+ .name = "SSP_INIT"
+ };
+
+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &val) != 0) {
+ return -EINVAL;
+ }
+
+ if (((val & SSP_OTP_MASK) == SSP_OTP_MASK) ||
+ ((val & SSP_OTP_MASK) == SSP_OTP_SUCCESS)) {
+ return -EINVAL;
+ }
+
+ if ((val & SSP_OTP_MASK) == 0U) {
+ if (bsec_program_otp(SSP_OTP_REQ, otp_ssp.idx) != BSEC_OK) {
+ return -EINVAL;
+ }
+ }
+
+ if (ssp_get_loader_handle(&dev_handle, &dev_spec) != 0) {
+ WARN("Error while retrieving handle\n");
+ return -ENOENT;
+ }
+
+ result = io_open(dev_handle, (uintptr_t)&partition_spec, &handle);
+ if (result != 0) {
+ WARN("SSP io open error %i\n", result);
+ return -EINVAL;
+ }
+
+ result = io_read(handle, (uintptr_t)&buf_err, sizeof(buf_err),
+ &length_read);
+ if (result != 0) {
+ WARN("SSP read command error %i\n", result);
+ return -EINVAL;
+ }
+
+ result = io_close(handle);
+ if (result != 0) {
+ WARN("SSP io close error %i\n", result);
+ return -EINVAL;
+ }
+
+ boot_context->p_ssp_config->ssp_cmd =
+ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK;
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config,
+ sizeof(boot_api_ssp_config_t));
+#endif
+ return 0;
+}
+
+/*
+ * Retrieve the current status of the SSP from bootrom context and OTP value.
+ */
+static ssp_result_e ssp_check_status(boot_api_context_t *boot_context)
+{
+ uint32_t otp;
+
+ if (initialize_otp() < 0) {
+ return SSP_ERROR;
+ }
+
+ if (stm32_get_otp_value_from_idx(otp_ssp.idx, &otp) != 0) {
+ return SSP_ERROR;
+ }
+
+ if ((otp & SSP_OTP_REQ) == 0U) {
+ return SSP_NONE;
+ }
+
+ if ((otp & SSP_OTP_SUCCESS) != 0U) {
+ return SSP_DONE;
+ }
+
+ VERBOSE("Start Get ssp_cmd : %x\n",
+ boot_context->p_ssp_config->ssp_cmd);
+
+ switch (boot_context->p_ssp_config->ssp_cmd) {
+ case BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK:
+ INFO("Detected start SSP Phase 2\n");
+ return SSP_GET_CERT;
+ case BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK:
+ INFO("Detected start SSP Phase 3\n");
+ return SSP_FLASH_OEM;
+ default:
+ return SSP_NONE;
+ }
+}
+
+/*
+ * Start the SSP processing.
+ */
+void ssp_start(boot_api_context_t *boot_context)
+{
+ int result;
+
+ switch (ssp_check_status(boot_context)) {
+ case SSP_GET_CERT:
+ result = ssp_download_phase(boot_context);
+ if (result != 0) {
+ /*
+ * Download Phase failed, clean, reset
+ */
+ ssp_cleanup(boot_context);
+
+ ERROR("SSP_Error: Resetting target\n");
+ goto out;
+ }
+
+ /* Process completed, go to Phase 3 */
+ boot_context->p_ssp_config->ssp_cmd =
+ BOOT_API_CTX_SSP_CMD_PROV_SECRET;
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config,
+ sizeof(boot_api_ssp_config_t));
+#endif
+ break;
+
+ case SSP_FLASH_OEM:
+ result = ssp_secret_programming(boot_context);
+ if (result != 0) {
+ ERROR("Error during provisionning\n");
+ goto out;
+ }
+
+ NOTICE("Provisioning completed\n");
+ goto out;
+
+ case SSP_ERROR:
+ /*
+ * Error during bootrom SSP processing
+ */
+ ERROR("SSP_Error: Resetting target\n");
+ goto out;
+
+ case SSP_NONE:
+ default:
+ result = ssp_enable_processing(boot_context);
+ if (result != 0) {
+ ERROR("Start SSP Failed (%i)\n", result);
+ goto out;
+ }
+ }
+
+ if (result == 0) {
+ /*
+ * Keep VDDCORE && VDD enabled if pmic used to generate
+ * the required MPSYSRST.
+ */
+ if (dt_pmic_status() > 0) {
+ const char *name;
+
+ name = stm32mp_get_cpu_supply_name();
+ if (name == NULL) {
+ goto out;
+ }
+
+ if (stpmic1_regulator_mask_reset_set(name) != 0) {
+ WARN("Failed to write %s reset mask\n", name);
+ }
+
+ name = stm32mp_get_vdd_supply_name();
+ if (name == NULL) {
+ goto out;
+ }
+
+ if (stpmic1_regulator_mask_reset_set(name) != 0) {
+ WARN("Failed to write %s reset mask\n", name);
+ }
+ }
+ }
+
+out:
+ stm32mp_plat_reset(plat_my_core_pos());
+}
diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c
index 8876b7499..1c0c2efd6 100644
--- a/lib/usb/usb_st_dfu.c
+++ b/lib/usb/usb_st_dfu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,10 +12,12 @@
#include <lib/usb/usb_st_dfu.h>
static uintptr_t usbd_dfu_download_address;
+static uintptr_t usbd_dfu_upload_address;
static uint32_t usbd_dfu_phase_id;
static uint32_t usbd_dfu_operation_complete;
static uint32_t usbd_dfu_current_req;
static uint32_t usbd_detach_req;
+static uint32_t usbd_error_msg_size;
/*
* @brief USBD_DFU_Init
@@ -370,39 +372,91 @@ static void usb_dfu_upload(usb_handle_t *pdev, usb_setup_req_t *req)
INFO("UPLOAD :\n");
INFO("\t\tPhase ID : %i\n", usbd_dfu_phase_id);
+#if STM32MP_SSP
INFO("\t\taddress 0x%lx\n",
- usbd_dfu_download_address);
+ usbd_dfu_upload_address);
hdfu->buffer[0] = usbd_dfu_phase_id;
- hdfu->buffer[1] = (uint8_t)
- (usbd_dfu_download_address);
- hdfu->buffer[2] = (uint8_t)
- (usbd_dfu_download_address >>
- 8);
- hdfu->buffer[3] = (uint8_t)
- (usbd_dfu_download_address >>
- 16);
- hdfu->buffer[4] = (uint8_t)
- (usbd_dfu_download_address >>
- 24);
-
+ hdfu->buffer[1] = usbd_dfu_upload_address;
+ hdfu->buffer[2] = usbd_dfu_upload_address >> 8;
+ hdfu->buffer[3] = usbd_dfu_upload_address >> 16;
+ hdfu->buffer[4] = usbd_dfu_upload_address >> 24;
hdfu->buffer[5] = 0x00;
hdfu->buffer[6] = 0x00;
hdfu->buffer[7] = 0x00;
hdfu->buffer[8] = 0x00;
- if ((usbd_dfu_download_address ==
+ if ((usbd_dfu_upload_address ==
UNDEFINE_DOWN_ADDR) &&
(usbd_detach_req)) {
INFO("Send detach request\n");
hdfu->buffer[9] = 0x01;
pdev->ep_in[0].total_length = 10;
pdev->ep_in[0].rem_length = 10;
+ } else {
+ if (usbd_dfu_phase_id != 0xFF) {
+ pdev->ep_in[0].total_length = 9;
+ pdev->ep_in[0].rem_length = 9;
+ } else {
+ memcpy(&hdfu->buffer[9],
+ (char *)
+ usbd_dfu_upload_address,
+ usbd_error_msg_size);
+ pdev->ep_in[0].total_length =
+ 9 + usbd_error_msg_size;
+ pdev->ep_in[0].rem_length =
+ 9 + usbd_error_msg_size;
+ usbd_dfu_operation_complete = 1;
+ }
+ }
+
+ if (hdfu->alt_setting != DFU_GET_PHASE) {
+ uint16_t size;
+
+ /* Change SSP phase */
+ size = ((usb_dfu_media_t *)
+ pdev->user_data)->
+ read((uint8_t *)
+ usbd_dfu_upload_address,
+ &hdfu->buffer[9],
+ hdfu->wlength);
+
+ if (size != 0) {
+ pdev->ep_in[0].total_length +=
+ size;
+ pdev->ep_in[0].rem_length +=
+ size;
+ }
+ }
+#else /* STM32MP_SSP */
+ INFO("\t\taddress 0x%lx\n",
+ usbd_dfu_download_address);
+
+ hdfu->buffer[0] = usbd_dfu_phase_id;
+ hdfu->buffer[1] = usbd_dfu_download_address;
+ hdfu->buffer[2] = usbd_dfu_download_address >>
+ 8;
+ hdfu->buffer[3] = usbd_dfu_download_address >>
+ 16;
+ hdfu->buffer[4] = usbd_dfu_download_address >>
+ 24;
+ hdfu->buffer[5] = 0x00;
+ hdfu->buffer[6] = 0x00;
+ hdfu->buffer[7] = 0x00;
+ hdfu->buffer[8] = 0x00;
+
+ if ((usbd_dfu_download_address ==
+ UNDEFINE_DOWN_ADDR) &&
+ (usbd_detach_req)) {
+ INFO("Send detach request\n");
+ hdfu->buffer[9] = 0x01;
+ pdev->ep_in[0].total_length = 10;
+ pdev->ep_in[0].rem_length = 10;
} else {
pdev->ep_in[0].total_length = 9;
pdev->ep_in[0].rem_length = 9;
}
-
+#endif /* STM32MP_SSP */
/* Send the status data over EP0 */
pdev->ep0_state = USBD_EP0_DATA_IN;
/* Start the transfer */
@@ -662,6 +716,10 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req)
usb_dfu_upload(pdev, req);
break;
+ case DFU_DNLOAD:
+ usb_dfu_download(pdev, req);
+ break;
+
case DFU_GETSTATUS:
INFO("GETSTATUS :\n");
usb_dfu_get_status(pdev);
@@ -759,6 +817,7 @@ static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req)
break;
case DFU_DETACH:
+ INFO("Receive DFU detach\n");
usb_dfu_detach(pdev, req);
break;
@@ -844,6 +903,11 @@ void usb_dfu_set_download_addr(uintptr_t addr)
usbd_dfu_download_address = addr;
}
+void usb_dfu_set_upload_addr(uintptr_t addr)
+{
+ usbd_dfu_upload_address = addr;
+}
+
uint32_t usb_dfu_download_is_completed(void)
{
return usbd_dfu_operation_complete;
@@ -863,3 +927,8 @@ void usb_dfu_request_detach(void)
{
usbd_detach_req = 1;
}
+
+void usb_dfu_error_msg_size(uint32_t size)
+{
+ usbd_error_msg_size = size;
+}
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index f94a5c2c2..60503587f 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -128,6 +128,7 @@ static pcd_handle_t pcd_handle;
static const io_dev_connector_t *usb_dev_con;
#endif /* STM32MP_USB_PROGRAMMER */
+#if !STM32MP_SSP
#ifdef AARCH32_SP_OPTEE
static const struct stm32image_part_info optee_header_partition_spec = {
.name = OPTEE_HEADER_IMAGE_NAME,
@@ -154,6 +155,7 @@ static const io_block_spec_t bl2_block_spec = {
.offset = BL2_BASE,
.length = STM32MP_BL2_SIZE,
};
+#endif /* !STM32MP_SSP */
static const struct stm32image_part_info bl33_partition_spec = {
.name = BL33_IMAGE_NAME,
@@ -199,7 +201,9 @@ static io_block_spec_t stm32image_block_spec = {
static const io_dev_connector_t *stm32image_dev_con __unused;
+#if !STM32MP_SSP
static int open_dummy(const uintptr_t spec);
+#endif
static int open_image(const uintptr_t spec);
static int open_storage(const uintptr_t spec);
@@ -210,6 +214,7 @@ struct plat_io_policy {
};
static const struct plat_io_policy policies[] = {
+#if !STM32MP_SSP
[BL2_IMAGE_ID] = {
.dev_handle = &dummy_dev_handle,
.image_spec = (uintptr_t)&bl2_block_spec,
@@ -237,7 +242,8 @@ static const struct plat_io_policy policies[] = {
.image_spec = (uintptr_t)&bl32_block_spec,
.check = open_dummy
},
-#endif
+#endif /* AARCH32_SP_OPTEE */
+#endif /* !STM32MP_SSP */
[BL33_IMAGE_ID] = {
.dev_handle = &image_dev_handle,
.image_spec = (uintptr_t)&bl33_partition_spec,
@@ -257,10 +263,12 @@ static const struct plat_io_policy policies[] = {
}
};
+#if !STM32MP_SSP
static int open_dummy(const uintptr_t spec)
{
return io_dev_init(dummy_dev_handle, 0);
}
+#endif
static int open_image(const uintptr_t spec)
{
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index ab419f15f..65d480688 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -23,6 +23,7 @@ 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);
/* Return the base address of the DDR controller */
uintptr_t stm32mp_ddrctrl_base(void);
@@ -94,6 +95,11 @@ void stm32mp_print_boardinfo(void);
/* Check HW CPU OPP support */
bool stm32mp_supports_cpu_opp(uint32_t opp_id);
+#if STM32MP_SSP
+/* Check HW support SSP */
+bool stm32mp_supports_ssp(void);
+#endif
+
/*
* Util for clock gating and to get clock rate for stm32 and platform drivers
* @id: Target clock ID, ID used in clock DT bindings
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index 873bed551..996ed0a7f 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -49,6 +49,7 @@ 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_board_model(void);
int fdt_get_gpio_bank_pinctrl_node(unsigned int bank);
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index e838995cc..612358c24 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -170,6 +170,22 @@ const char *stm32mp_get_cpu_supply_name(void)
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;
+}
+
#if TRUSTED_BOARD_BOOT
/* Save pointer to last loaded header */
static boot_api_image_header_t *latest_stm32_header;
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index f6de0b62a..b12fc8640 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -650,6 +650,33 @@ uint32_t dt_get_pwr_vdd_voltage(void)
return fdt32_to_cpu(*cuint);
}
+/*******************************************************************************
+ * This function retrieves VDD regulator name from DT.
+ * Returns string taken from supply node, NULL otherwise.
+ ******************************************************************************/
+const char *dt_get_vdd_regulator_name(void)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ node = dt_get_node_by_compatible(DT_PWR_COMPAT);
+ if (node < 0) {
+ return NULL;
+ }
+
+ cuint = fdt_getprop(fdt, node, "vdd-supply", 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 CPU regulator name from DT.
* Returns string taken from supply node, NULL otherwise.
diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c
index f47584206..57c09839e 100644
--- a/plat/st/common/stm32mp_trusted_boot.c
+++ b/plat/st/common/stm32mp_trusted_boot.c
@@ -32,6 +32,7 @@ int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
VERBOSE("get_rot_pk_hash: get index error\n");
return -EINVAL;
}
+
if (len != (CHAR_BIT * BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)) {
VERBOSE("get_rot_pk_hash: length Error\n");
return -EINVAL;
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 3f5eb5674..68a5bd3e6 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -30,6 +30,7 @@
#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
#include <lib/optee_utils.h>
+#include <lib/ssp_lib.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -41,6 +42,7 @@
#define TIMEOUT_US_1MS U(1000)
+#if !STM32MP_SSP
static const char debug_msg[626] = {
"***************************************************\n"
"** NOTICE NOTICE NOTICE NOTICE NOTICE **\n"
@@ -55,6 +57,7 @@ static const char debug_msg[626] = {
"** **\n"
"***************************************************\n"
};
+#endif
static struct console_stm32 console;
static enum boot_device_e boot_device = BOOT_DEVICE_BOARD;
@@ -158,6 +161,11 @@ void bl2_el3_early_platform_setup(u_register_t arg0,
stm32mp_save_boot_ctx_address(arg0);
}
+#if STM32MP_SSP
+void bl2_platform_setup(void)
+{
+}
+#else
void bl2_platform_setup(void)
{
int ret;
@@ -217,6 +225,7 @@ void bl2_platform_setup(void)
configure_pmic();
}
}
+#endif /* STM32MP_SSP */
static void update_monotonic_counter(void)
{
@@ -258,9 +267,11 @@ static void initialize_clock(void)
uint32_t freq_khz = 0U;
int ret = 0;
+#if !STM32MP_SSP
if (wakeup_standby) {
ret = stm32_get_pll1_settings_from_context();
}
+#endif
/*
* If no pre-defined PLL1 settings in DT, find the highest frequency
@@ -343,6 +354,13 @@ void bl2_el3_plat_arch_setup(void)
BL_CODE_END - BL_CODE_BASE,
MT_CODE | MT_SECURE);
+#if SEPARATE_CODE_AND_RODATA
+ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE);
+#endif
+
+#if !STM32MP_SSP
#ifdef AARCH32_SP_OPTEE
mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
STM32MP_OPTEE_SIZE,
@@ -352,6 +370,7 @@ void bl2_el3_plat_arch_setup(void)
mmap_add_region(BL32_BASE, BL32_BASE,
BL32_LIMIT - BL32_BASE,
MT_RO_DATA | MT_SECURE);
+#endif
#endif
/* Prevent corruption of preloaded Device Tree */
mmap_add_region(DTB_BASE, DTB_BASE,
@@ -502,7 +521,18 @@ void bl2_el3_plat_arch_setup(void)
console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF);
+#if STM32MP_SSP
+ if (boot_context->p_ssp_config->ssp_cmd !=
+ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK) {
+ stm32mp_print_cpuinfo();
+ if (!stm32mp_supports_ssp()) {
+ ERROR("Chip doesn't support SSP\n");
+ panic();
+ }
+ }
+#else
stm32mp_print_cpuinfo();
+#endif
board_model = dt_get_board_model();
if (board_model != NULL) {
@@ -536,6 +566,7 @@ skip_console_init:
stm32_iwdg_refresh();
+#if !STM32MP_SSP
if (bsec_read_debug_conf() != 0U) {
result = stm32mp1_dbgmcu_freeze_iwdg2();
if (result != 0) {
@@ -554,6 +585,7 @@ skip_console_init:
}
stm32mp1_arch_security_setup();
+#endif
print_reset_reason();
@@ -564,7 +596,18 @@ skip_console_init:
print_pmic_info_and_debug();
}
- stm32mp_io_setup();
+#if STM32MP_SSP
+ if (boot_context->p_ssp_config->ssp_cmd !=
+ BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK) {
+ stm32mp_io_setup();
+ }
+
+ ssp_start(boot_context);
+#else
+ if (!wakeup_standby) {
+ stm32mp_io_setup();
+ }
+#endif
}
#if defined(AARCH32_SP_OPTEE)
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 872e2044c..04be28d1e 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -335,15 +335,278 @@ BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX 23
/* 'K' 'B' 'U' 'P' -.> 'PUBK' */
#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK 0x4B425550
+#if STM32MP_SSP
+/* 'V' 'O' 'R' 'P' -.> 'PROV' */
+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET 0x564F5250
+/*
+ * Possible values of boot context field
+ * 'ssp_config_ptr_in->ssp_cmd' written by bootROM as Acknowledge
+ * of a request of SSP by FSBL.
+ */
+
+/* Written by bootROM on SSP error */
+#define BOOT_API_CTX_SSP_CMD_INVALID 0x00000000
+/*
+ * 'A' 'B' 'U' 'P' -.> 'PUBA' : ACK of ECIES_CHIP_PUBK calculation
+ * request by bootROM.
+ */
+#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK_ACK 0x41425550
+/*
+ * 'A' 'O' 'R' 'P' -.> 'PROA' : ACK of OEM Secret Provisioning request
+ * by bootROM.
+ */
+#define BOOT_API_CTX_SSP_CMD_PROV_SECRET_ACK 0x414F5250
+
+/*
+ * Constants required for SSP
+ */
+/* '.' 'P' 'S' 'S' -.> 'SSP.' */
+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_NORMAL 0x2E505353
+/* 'L' 'P' 'S' 'S' -.> 'SSPL' */
+#define BOOT_API_SSP_BLOB_LICENSE_TYPE_SSP_LIVE 0x4C505353
+/* version 1 */
+#define BOOT_API_SSP_LICENSE_LAYOUT_VERSION_TO_MATCH 0x00000001
+/* 'P' 'P' 'S' 'S' -.> 'SSPP' */
+#define BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP 0x50505353
+/* IV AES on 128 bits = 16 bytes and KEY AES on 128 bits = 16 bytes */
+#define BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES 32
+/* version 1 */
+#define BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH 0x00000001
+/*
+ * Scalar in Elliptic curve cryptography is an integer (often a Prime)
+ * the number of bytes of this scalar is defined below.
+ */
+#define BOOT_API_SSP_SCALAR_SIZE_BYTES 32
+
+/*
+ * In Elliptic curve cryptography coordinates of points are 2D P
+ * (Px, Py) as concatenation of two scalars.
+ */
+#define BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES \
+ (2 * BOOT_API_SSP_SCALAR_SIZE_BYTES)
+
+/* In Elliptic curve cryptography Private Keys are scalars */
+#define BOOT_API_SSP_PRIVK_KEY_SIZE_BYTES \
+ BOOT_API_SSP_SCALAR_SIZE_BYTES
+
+/*
+ * In ECIES algorithm the Shared Secret (SS) is
+ * the x coordinate (Px) of a point P(Px,Py) obtained on reference
+ * NIST-P256 Elliptic curve chosen.
+ */
+#define BOOT_API_SSP_ECDH_SHARED_SECRET_SIZE_BYTES \
+ BOOT_API_SSP_SCALAR_SIZE_BYTES
+
+/*
+ * In Elliptic curve cryptography Public Keys are Points on Elliptic
+ * curve chosen P(x,y).
+ * Public Key is the x, y coordinates concatenated
+ * Ecies_eph_pubk and OEM_ECDSA_PUBK are each 64 bytes = 512 bits key
+ * sizes.
+ */
+#define BOOT_API_SSP_PUBK_KEY_SIZE_BYTES \
+ BOOT_API_SSP_EC_COORDINATE_SIZE_BYTES
+
+/*
+ * Size in bytes of ECIES_Chip_pubk obtained from bootROM at end of SSP
+ * phase 1 : Chip public key calculation.
+ */
+#define BOOT_API_SSP_ECIES_CHIP_PUBK_SIZE_BYTES \
+ BOOT_API_SSP_PUBK_KEY_SIZE_BYTES
+
+/* AES-GCM authentication tag size is 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES 16
+
+/* AES-GCM Symmetric Key size is 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_KEY_SIZE_BYTES 16
+
+/* AES-GCM Initialization Vector (IV) size is of 16 bytes = 128 bits */
+#define BOOT_API_SSP_AES_GCM_IV_SIZE_BYTES 16
+
+/*
+ * 88 bytes (license_type, live_session_id, license_version,
+ * fsbl_min_version, rfu[8], eph_ecies_pubk[])
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE 88
+
+/*
+ * 32 bytes AAD License Secret from 2nd round KDF-SHA-256
+ * from ECDH Shared Secret hence KDF[32..63] aka "Authorization Token"
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF 32
+
+/*
+ * Total License AAD size = 88 + 32 = 120 bytes
+ */
+#define BOOT_API_SSP_AES_GCM_LICENSE_AAD_SIZE_BYTES \
+ (BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_LICENSE + \
+ BOOT_API_SSP_AES_GCM_LICENSE_AAD_NB_BYTES_FROM_KDF)
+
+/*
+ * AAD for Payload size : composed of :
+ * payload_magic, payload_protocol_version, oem_ecdsa_pubk[], oem_secret_size
+ * = 4 + 4 + 64 + 4 = 76 bytes AAD for Payload
+ */
+#define BOOT_API_SSP_AES_GCM_PAYLOAD_AAD_SIZE_BYTES 76
+
+/*
+ * OEM Secrets max size in bytes :
+ * [OTP[95:59] + OTP_CFG56 (RMA Unlock and Relock passwords)] x 4 bytes
+ * by OTP word = 152 bytes
+ */
+#define BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES 152
+
+/*
+ * Possible values of boot context field 'ssp_status'
+ * as can be read by FSBL-SSP
+ */
+#define BOOT_API_CTX_SSP_STATUS_NO_SSP 0
+#define BOOT_API_CTX_SSP_STATUS_CHIP_PUBK_CALC_FINISHED 1
+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FINISHED 2
+#define BOOT_API_CTX_SSP_STATUS_OEM_SEC_PROV_FORBIDDEN 3
+
+/*
+ * Reserved size for future use
+ */
+#define BOOT_API_SSP_HSM_OEM_RFU_SIZE 8
+
/*
* Exported types
*/
+/*
+ * SSP related definitions
+ */
+/*
+ * SSP BLOB License structure : Binary Large OBject License structure
+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret
+ * provisioning.
+ * License information data, the structure is read by bootROM.
+ */
+typedef struct {
+ /*
+ * License Type provided by HSM-OEM tool
+ * should match Normal SSP License of Live SSP License.
+ */
+ uint32_t license_type;
+
+ /* Live Session ID provided by HSM-OEM tool */
+ uint32_t live_session_id;
+
+ /*
+ * Version of the License Protocol (Structure)
+ * should be incremented each time a new.
+ */
+ uint32_t license_version;
+
+ /*
+ * Minimum FSBL version to be compared
+ * with FSBL Header field 'imageVersion'.
+ */
+ uint32_t fsbl_min_version;
+
+ /* RFU provided by HSM-OEM tool */
+ uint8_t rfu[BOOT_API_SSP_HSM_OEM_RFU_SIZE];
+
+ /*
+ * Ephemeral ECIES Public Key from HSM-OEM
+ * 64 bytes = 512 bits.
+ */
+ uint8_t eph_ecies_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES];
+
+ /*
+ * Encrypted (IV,Key) : with Shared Secret based on
+ * 'Ephemeral ECIES Key pair' and 'ECIES Chip Key pair'.
+ */
+ uint8_t encrypted_iv_and_key
+ [BOOT_API_SSP_ENCRYPTED_IV_AND_KEY_SIZE_BYTES];
+
+ /*
+ * AUTH_TAG AES-GCM from encryption of (IV, Key)
+ * in HSM-OEM with License AAD scheme
+ * License Tag is 16 bytes = 128 bits.
+ */
+ uint8_t license_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES];
+
+} boot_api_ssp_blob_license_t;
+
+/*
+ * SSP BLOB Payload structure : Binary Large OBject Payload Structure
+ * Should be written by FSBL-SSP to provide bootROM with SSP OEM Secret
+ * provisioning input data, the structure is read by bootROM
+ * The BLOB Payload size is fixed to a max size of 244 bytes based
+ * on a max number of bytes of OEM secret derived from OTP upper free
+ * area in STM32MP15xx cut 2.0.In this table oem_encrypted_secrets[]
+ * of max size only the first 'p_blob_payload->oem_secret_size_bytes'
+ * bytes will be considered and used by bootROM.
+ */
+typedef struct {
+ /*
+ * BLOB Payload Magic : for memory validity check of BLOB Payload
+ * to match against BOOT_API_SSP_BLOB_PAYLOAD_MAGIC_SSP by bootROM.
+ */
+ uint32_t payload_magic;
+
+ /*
+ * SSP Payload protocol version : on 32 bits
+ * to be checked by bootROM for equality with
+ * BOOT_API_SSP_PAYLOAD_PROTOCOL_VERSION_TO_MATCH
+ * ie : 0x00000001 : version 1 of SSP Payload
+ */
+ uint32_t payload_protocol_version;
+
+ /*
+ * OEM_ECDSA_PUBK Public Key defined by OEM
+ * 64 bytes = 512 bits
+ */
+ uint8_t oem_ecdsa_pubk[BOOT_API_SSP_PUBK_KEY_SIZE_BYTES];
+
+ /*
+ * Size of Table of OEM Secrets encrypted with AES-GCM (Key,IV) from
+ * License field 'encrypted_iv_and_key[]'
+ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES:
+ * is verified by bootROM.
+ */
+ uint32_t oem_secret_size_bytes;
+
+ /*
+ * AUTH_TAG AES-GCM computed by HSM-OEM when encrypting OEM Secrets with
+ * (Key,IV) using special AAD scheme for Payload.
+ * 16 bytes = 128 bits
+ */
+ uint8_t payload_tag[BOOT_API_SSP_AES_GCM_AUTH_TAG_SIZE_BYTES];
+
+ /*
+ * OEM Secrets encrypted with AES-GCM (IV, Key) from
+ * License field 'encrypted_iv_and_key[]'.
+ * The payload size is 'oem_secret_size_bytes'
+ * should be <= BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES =
+ * 152 bytes : OEM Secrets max size in bytes :
+ * [OTP_CFG56, OTP_CFG59, OTP_CFG60..95] x 4 bytes by OTP word.
+ */
+ uint8_t oem_encrypted_secrets[BOOT_API_SSP_OEM_SECRETS_MAX_SIZE_BYTES];
+
+} boot_api_ssp_blob_payload_t;
+#endif
+
/* SSP Configuration structure */
typedef struct {
/* SSP Command*/
uint32_t ssp_cmd;
+#if STM32MP_SSP
+ /* ECIES chip public key */
+ uint8_t *p_chip_pubk;
+ /* Blob License Address */
+ boot_api_ssp_blob_license_t *p_blob_license;
+ /* Blob Payload Address */
+ boot_api_ssp_blob_payload_t *p_blob_payload;
+ /* Secrets Decrypted Address */
+ uint8_t *p_ssp_oem_secrets_decrypted;
+ /* Reserved for Future Use (RFU) */
+ uint32_t padding_rfu;
+#else
uint8_t reserved[20];
+#endif
} boot_api_ssp_config_t;
/*
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 694c3c4bb..380e1200e 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -60,18 +60,31 @@
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
* size plus a little space for growth.
*/
+#if !STM32MP_SSP
#define BL2_BASE STM32MP_BL2_BASE
#define BL2_LIMIT (STM32MP_BL2_BASE + \
STM32MP_BL2_SIZE)
+#else
+#define BL2_RO_BASE STM32MP_BL2_BASE
+#define BL2_RO_LIMIT (STM32MP_BL2_BASE + \
+ STM32MP_BL2_SIZE)
+#define BL2_RW_BASE BL2_RO_LIMIT
+#define BL2_RW_LIMIT (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ PLAT_XLAT_SIZE - \
+ STM32MP_BL2_SIZE)
+#endif
/*******************************************************************************
* BL32 specific defines.
******************************************************************************/
+#if !STM32MP_SSP
#ifndef AARCH32_SP_OPTEE
#define BL32_BASE STM32MP_BL32_BASE
#define BL32_LIMIT (STM32MP_BL32_BASE + \
STM32MP_BL32_SIZE)
#endif
+#endif
/*******************************************************************************
* BL33 specific defines.
diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h
index 21214d35a..ed9a3dc72 100644
--- a/plat/st/stm32mp1/include/stm32mp1_context.h
+++ b/plat/st/stm32mp1/include/stm32mp1_context.h
@@ -10,10 +10,14 @@
#include <stdbool.h>
#include <stdint.h>
+#include <drivers/st/stm32_rtc.h>
+
#define DDR_CRC_GRANULE 32
void stm32_clean_context(void);
-int stm32_save_context(uint32_t zq0cr0_zdata);
+int stm32_save_context(uint32_t zq0cr0_zdata,
+ struct stm32_rtc_calendar *rtc_time,
+ unsigned long long stgen_cnt);
int stm32_restore_context(void);
unsigned long long stm32_get_stgen_from_context(void);
int stm32_restore_backup_reg(void);
diff --git a/plat/st/stm32mp1/include/stm32mp1_low_power.h b/plat/st/stm32mp1/include/stm32mp1_low_power.h
index 82b3d36c1..9524b6414 100644
--- a/plat/st/stm32mp1/include/stm32mp1_low_power.h
+++ b/plat/st/stm32mp1/include/stm32mp1_low_power.h
@@ -15,5 +15,6 @@ void stm32_apply_pmic_suspend_config(uint32_t mode);
void stm32_exit_cstop(void);
void stm32_pwr_down_wfi(void);
void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr);
+void stm32_auto_stop(void);
#endif /* STM32MP1_LOW_POWER_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_power_config.h b/plat/st/stm32mp1/include/stm32mp1_power_config.h
index 7bd07956a..37312c8de 100644
--- a/plat/st/stm32mp1/include/stm32mp1_power_config.h
+++ b/plat/st/stm32mp1/include/stm32mp1_power_config.h
@@ -24,5 +24,6 @@ void stm32mp1_init_lp_states(void);
int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status);
uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode);
int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode);
+bool stm32mp1_get_retram_enabled(void);
#endif /* STM32MP1_POWER_CONFIG_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
index 19ae1d0a3..a800e4155 100644
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -91,6 +91,14 @@
*/
#define STM32_SMC_RCC_OPP 0x82001009
+/*
+ * SIP function STM32_SMC_AUTO_STOP - CPU auto stop for OS driver suspend
+ *
+ * Argument a0: (input) This SMCC ID: STM32_SMC_AUTO_STOP
+ * (output) Status return code.
+ */
+#define STM32_SMC_AUTO_STOP 0x8200100a
+
/*
* SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT0/1
*
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index 1d407bb72..559788686 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,6 +19,7 @@
* the next executable image id.
******************************************************************************/
static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#if !STM32MP_SSP
/* Fill BL32 related information */
{
.image_id = BL32_IMAGE_ID,
@@ -78,6 +79,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
.next_handoff_image_id = INVALID_IMAGE_ID,
},
#endif /* AARCH32_SP_OPTEE */
+#endif /* !STM32MP_SSP */
/* Fill BL33 related information */
{
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
index 0a7437ba4..6de18e1f7 100644
--- a/plat/st/stm32mp1/plat_image_load.c
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -33,11 +33,10 @@ static bool addr_inside_backupsram(uintptr_t addr)
******************************************************************************/
bl_load_info_t *plat_get_bl_image_load_info(void)
{
+#if !STM32MP_SSP
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp_get_boot_ctx_address();
-#ifdef AARCH32_SP_OPTEE
bl_mem_params_node_t *bl32 = get_bl_mem_params_node(BL32_IMAGE_ID);
-#endif
bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID);
uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
uint32_t bkpr_core1_addr =
@@ -60,9 +59,8 @@ bl_load_info_t *plat_get_bl_image_load_info(void)
if (mmio_read_32(bkpr_core1_addr) != 0U) {
bl33->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
-
-#ifdef AARCH32_SP_OPTEE
bl32->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
+#ifdef AARCH32_SP_OPTEE
bl32->ep_info.pc = stm32_pm_get_optee_ep();
if (addr_inside_backupsram(bl32->ep_info.pc)) {
@@ -86,7 +84,7 @@ bl_load_info_t *plat_get_bl_image_load_info(void)
STM32MP_DDR_S_SIZE -
STM32MP_DDR_SHMEM_SIZE -
bl33->image_info.image_base;
-
+#endif /* STM32MP_SSP */
return get_bl_load_info_from_mem_params_desc();
}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 840a38d14..3264d6091 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -10,11 +10,19 @@ BL2_AT_EL3 := 1
USE_COHERENT_MEM := 0
# Add specific ST version
-ST_VERSION := r1.0
+ST_VERSION := r2.0
VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING}
TRUSTED_BOARD_BOOT := 1
+STM32MP_SSP ?= 0
+$(eval $(call assert_boolean,STM32MP_SSP))
+$(eval $(call add_define,STM32MP_SSP))
+
+ifeq ($(STM32MP_SSP),1)
+include plat/st/stm32mp1/stm32mp1_ssp.mk
+endif
+
# Please don't increment this value without good understanding of
# the monotonic counter
STM32_TF_VERSION ?= 0
@@ -185,8 +193,10 @@ BL2_SOURCES += drivers/st/uart/io_programmer_uart.c \
drivers/st/uart/stm32mp1xx_hal_uart.c
endif
+ifeq ($(STM32MP_SSP),0)
BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \
drivers/st/ddr/stm32mp1_ram.c
+endif
BL2_SOURCES += common/desc_image_load.c \
plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
@@ -227,7 +237,9 @@ STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
.PHONY: check_dtc_version stm32image clean_stm32image
.SUFFIXES:
+ifeq ($(STM32MP_SSP),0)
all: check_dtc_version stm32image ${STM32_TF_STM32}
+endif
ifeq ($(AARCH32_SP),sp_min)
# BL32 is built only if using SP_MIN
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
index e75571f98..273c1cf9d 100644
--- a/plat/st/stm32mp1/services/bsec_svc.c
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -27,10 +27,6 @@
#include "bsec_svc.h"
-#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS)
-#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS)
-#define SSP_OTP_MASK (SSP_OTP_REQ | SSP_OTP_SUCCESS)
-
enum bsec_ssp_status {
BSEC_NO_SSP = 0,
BSEC_SSP_SET,
diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c
index 640816fca..0be76bbda 100644
--- a/plat/st/stm32mp1/services/rcc_svc.c
+++ b/plat/st/stm32mp1/services/rcc_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -70,8 +70,8 @@ static void access_allowed_mask(uint32_t request, uint32_t offset,
}
}
-static void raw_allowed_access_request(uint32_t request,
- uint32_t offset, uint32_t value)
+static uint32_t raw_allowed_access_request(uint32_t request,
+ uint32_t offset, uint32_t value)
{
uint32_t allowed_mask = 0;
@@ -80,16 +80,15 @@ static void raw_allowed_access_request(uint32_t request,
case RCC_MP_CIFR:
allowed_mask = RCC_MP_CIFR_WKUPF;
break;
- case RCC_MP_GCR:
- allowed_mask = RCC_MP_GCR_BOOT_MCU;
- break;
default:
- panic();
+ return STM32_SMC_INVALID_PARAMS;
}
if (allowed_mask != 0U) {
access_allowed_mask(request, offset, value, allowed_mask);
}
+
+ return STM32_SMC_OK;
}
uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3)
@@ -110,9 +109,7 @@ uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3)
offset &= RCC_OFFSET_MASK;
}
- raw_allowed_access_request(request, offset, value);
-
- return STM32_SMC_OK;
+ return raw_allowed_access_request(request, offset, value);
}
uint32_t rcc_cal_scv_handler(uint32_t x1)
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
index b2a84c15e..7ade11071 100644
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -13,6 +13,7 @@
#include <lib/psci/psci.h>
#include <tools_share/uuid.h>
+#include <stm32mp1_low_power.h>
#include <stm32mp1_smc.h>
#include "bsec_svc.h"
@@ -90,6 +91,11 @@ static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
ret1 = pm_domain_scv_handler(x1, x2);
break;
+ case STM32_SMC_AUTO_STOP:
+ stm32_auto_stop();
+ ret1 = STM32_SMC_OK;
+ break;
+
case STM32_SMC_SCMI_MESSAGE_AGENT0:
scmi_smt_fastcall_smc_entry(0U);
ret1 = STM32_SMC_OK;
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index f57630604..f0af4af13 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -181,6 +181,13 @@ void sp_min_plat_fiq_handler(uint32_t id)
case ARM_IRQ_SEC_SGI_1:
stm32_sgi1_it_handler();
break;
+ case ARM_IRQ_SEC_SGI_6:
+ /* tell the primary cpu to exit from stm32_pwr_down_wfi() */
+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) {
+ stm32mp1_calib_set_wakeup(true);
+ }
+ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_6);
+ break;
case STM32MP1_IRQ_IWDG1:
case STM32MP1_IRQ_IWDG2:
stm32_iwdg_it_handler(id);
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
index e77b8a79f..11a84db9b 100644
--- a/plat/st/stm32mp1/stm32mp1_context.c
+++ b/plat/st/stm32mp1/stm32mp1_context.c
@@ -158,7 +158,9 @@ void stm32mp1_pm_restore_clock_cfg(size_t offset, uint8_t *data, size_t size)
stm32mp_clk_disable(BKPSRAM);
}
-int stm32_save_context(uint32_t zq0cr0_zdata)
+int stm32_save_context(uint32_t zq0cr0_zdata,
+ struct stm32_rtc_calendar *rtc_time,
+ unsigned long long stgen_cnt)
{
void *smc_context;
void *cpu_context;
@@ -185,8 +187,8 @@ int stm32_save_context(uint32_t zq0cr0_zdata)
backup_data->zq0cr0_zdata = zq0cr0_zdata;
- stm32_rtc_get_calendar(&backup_data->rtc);
- backup_data->stgen = stm32mp_stgen_get_counter();
+ memcpy(&backup_data->rtc, rtc_time, sizeof(struct stm32_rtc_calendar));
+ backup_data->stgen = stgen_cnt;
stm32mp1_clk_lp_save_opp_pll1_settings(backup_data->pll1_settings,
sizeof(backup_data->pll1_settings));
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index d458805a1..af6d4b6dc 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -131,6 +131,12 @@ enum ddr_type {
(STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE))
+#if STM32MP_SSP
+#define STM32MP_BL2_SIZE U(0x00010000) /* 64 Ko for BL2 */
+
+#define STM32MP_BL2_BASE STM32MP_DTB_BASE + \
+ STM32MP_DTB_SIZE
+#else /* STM32MP_SSP */
#ifdef AARCH32_SP_OPTEE
#define STM32MP_BL32_SIZE U(0)
@@ -139,11 +145,7 @@ enum ddr_type {
#define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \
STM32MP_OPTEE_BASE)
#else
-#if STACK_PROTECTOR_ENABLED
-#define STM32MP_BL32_SIZE U(0x00013000) /* 76 KB for BL32 */
-#else
-#define STM32MP_BL32_SIZE U(0x00012000) /* 72 KB for BL32 */
-#endif
+#define STM32MP_BL32_SIZE U(0x00014000) /* 80 KB for BL32 */
#endif
#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \
@@ -166,6 +168,7 @@ enum ddr_type {
#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \
STM32MP_BL2_SIZE)
+#endif /* STM32MP_SSP */
#if STM32MP_USB_PROGRAMMER
/* BL2 and BL32/sp_min require 5 finer granularity tables */
@@ -179,6 +182,9 @@ enum ddr_type {
* MAX_MMAP_REGIONS is usually:
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
*/
+#if STM32MP_SSP
+ #define MAX_MMAP_REGIONS 8
+#else
#if defined(IMAGE_BL2)
#if STM32MP_USB_PROGRAMMER
#define MAX_MMAP_REGIONS 12
@@ -189,24 +195,35 @@ enum ddr_type {
#if defined(IMAGE_BL32)
#define MAX_MMAP_REGIONS 6
#endif
+#endif /* STM32MP_SSP */
#define XLAT_TABLE_OCTETSIZE U(0x1000)
#define PLAT_XLAT_SIZE (MAX_XLAT_TABLES * \
XLAT_TABLE_OCTETSIZE)
+#if STM32MP_SSP
+#define PLAT_XLAT_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ PLAT_XLAT_SIZE)
+#else
#define PLAT_XLAT_BASE (STM32MP_BL2_BASE - \
PLAT_XLAT_SIZE)
+#endif
/* DTB initialization value */
#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */
+#if STM32MP_SSP
+#define STM32MP_DTB_BASE U(0x2FFC3000)
+#else
#define STM32MP_DTB_BASE (PLAT_XLAT_BASE - \
STM32MP_DTB_SIZE)
+#endif
#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
/* Define Temporary Stack size use during low power mode */
-#define STM32MP_INT_STACK_SIZE 0x100
+#define STM32MP_INT_STACK_SIZE 0x200
/* Define maximum page size for NAND devices */
#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000)
@@ -404,11 +421,34 @@ enum ddr_type {
#define UID_OTP "uid_otp"
#define PKH_OTP "pkh_otp"
#define BOARD_ID_OTP "board_id"
+#define CFG2_OTP "cfg2_otp"
+#define SSP_OTP "ssp_otp"
+#define CHIP_CERTIFICATE_OTP "chip_otp"
+#define RMA_OTP "rma_otp"
/* OTP mask */
/* CFG0 */
#define CFG0_CLOSED_DEVICE BIT(6)
+/* CFG2 */
+#define OTP_CFG2_SEC_COUNTER_MASK GENMASK_32(27, 20)
+#define OTP_CFG2_SEC_COUNTER_SHIFT U(20)
+#define OTP_CFG2_ST_KEY_MASK GENMASK_32(31, 28)
+#define OTP_CFG2_ST_KEY_SHIFT U(28)
+
+/* SSP */
+#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS)
+#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS)
+#define SSP_OTP_MASK GENMASK_32(9, 8)
+#define SSP_OTP_SECRET_BASE U(59)
+#define SSP_OTP_SECRET_END U(95)
+
+/* CHIP_CERT */
+#define CHIP_CERTIFICATE_MAX_SIZE U(0x40)
+
+/* RMA */
+#define RMA_OTP_MASK GENMASK_32(29, 0)
+
/* PART NUMBER */
#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0)
#define PART_NUMBER_OTP_PART_SHIFT 0
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
index b80716253..cea39c16a 100644
--- a/plat/st/stm32mp1/stm32mp1_helper.S
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -46,17 +46,20 @@ func plat_report_exception
bne undef_inst_lbl
ldr r4, =abort_str
bl asm_print_str
- b print_excpetion_info
+ mrs r4, lr_abt
+ sub r4, r4, #4
+ b print_exception_info
undef_inst_lbl:
/* Test for an undefined instruction */
cmp r0, #MODE32_und
- bne other_excpetion_lbl
+ bne other_exception_lbl
ldr r4, =undefined_str
bl asm_print_str
- b print_excpetion_info
+ mrs r4, lr_und
+ b print_exception_info
-other_excpetion_lbl:
+other_exception_lbl:
/* Other exceptions */
mov r9, r0
ldr r4, =exception_start_str
@@ -65,10 +68,9 @@ other_excpetion_lbl:
bl asm_print_hex
ldr r4, =exception_end_str
bl asm_print_str
+ mov r4, r6
-print_excpetion_info:
- mrs r4, lr_svc
- sub r4, r4, #4
+print_exception_info:
bl asm_print_hex
ldr r4, =end_error_str
@@ -265,15 +267,19 @@ func plat_crash_console_init
str r2, [r1, #GPIO_PUPD_OFFSET]
/* Set alternate */
ldr r2, =DEBUG_UART_TX_GPIO_PORT
- cmp r2, #GPIO_ALT_LOWER_LIMIT
- ldrge r2, [r1, #GPIO_AFRH_OFFSET]
- bicge r2, r2, #(GPIO_ALTERNATE_MASK << ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
- orrge r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
- strge r2, [r1, #GPIO_AFRH_OFFSET]
- ldrlt r2, [r1, #GPIO_AFRL_OFFSET]
- biclt r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
- orrlt r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
- strlt r2, [r1, #GPIO_AFRL_OFFSET]
+#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
+ ldr r2, [r1, #GPIO_AFRH_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ str r2, [r1, #GPIO_AFRH_OFFSET]
+#else
+ ldr r2, [r1, #GPIO_AFRL_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
+ str r2, [r1, #GPIO_AFRL_OFFSET]
+#endif
/* Enable UART clock, with its source */
ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
mov r2, #DEBUG_UART_TX_CLKSRC
diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c
index fb975f5f6..f48f38c2e 100644
--- a/plat/st/stm32mp1/stm32mp1_low_power.c
+++ b/plat/st/stm32mp1/stm32mp1_low_power.c
@@ -24,6 +24,8 @@
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/power/stm32mp1-power.h>
#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
#include <plat/common/platform.h>
#include <boot_api.h>
@@ -31,12 +33,14 @@
#include <stm32mp_dt.h>
#include <stm32mp1_context.h>
#include <stm32mp1_low_power.h>
+#include <stm32mp1_power_config.h>
#include <stm32mp1_private.h>
static unsigned int gicc_pmr;
static struct stm32_rtc_calendar sleep_time;
static bool enter_cstop_done;
static uint32_t int_stack[STM32MP_INT_STACK_SIZE];
+static unsigned long long stgen_cnt;
extern void wfi_svc_int_enable(uintptr_t stack_addr);
@@ -91,12 +95,24 @@ static const struct pwr_lp_config config_pwr[STM32_PM_MAX_SOC_MODE] = {
#define GICC_PMR_PRIORITY_8 U(0x8)
+enum {
+ STATE_NONE = 0,
+ STATE_AUTOSTOP_ENTRY,
+ STATE_AUTOSTOP_EXIT,
+};
+
+static struct spinlock lp_lock;
+static volatile int cpu0_state = STATE_NONE;
+static volatile int cpu1_state = STATE_NONE;
+
void stm32_apply_pmic_suspend_config(uint32_t mode)
{
- const char *node_name = config_pwr[mode].regul_suspend_node_name;
+ const char *node_name;
assert(mode < ARRAY_SIZE(config_pwr));
+ node_name = config_pwr[mode].regul_suspend_node_name;
+
if (node_name != NULL) {
if (!initialize_pmic_i2c()) {
panic();
@@ -193,6 +209,9 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
stm32mp1_clock_stopmode_save();
+ stm32_rtc_get_calendar(&sleep_time);
+ stgen_cnt = stm32mp_stgen_get_counter();
+
if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) {
/*
* Save non-secure world entrypoint after standby in Backup
@@ -202,23 +221,29 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
mmio_write_32(bkpr_core1_magic,
BOOT_API_A7_CORE0_MAGIC_NUMBER);
- if (stm32_save_context(zq0cr0_zdata) != 0) {
+ if (stm32_save_context(zq0cr0_zdata, &sleep_time,
+ stgen_cnt) != 0) {
panic();
}
- /* Keep retention and backup RAM content in standby */
- mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN |
- PWR_CR2_RREN);
+ if (stm32mp1_get_retram_enabled()) {
+ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_RREN);
+ while ((mmio_read_32(pwr_base + PWR_CR2) &
+ PWR_CR2_RRRDY) == 0U) {
+ ;
+ }
+ }
+
+ /* Keep backup RAM content in standby */
+ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN);
while ((mmio_read_32(pwr_base + PWR_CR2) &
- (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) {
+ PWR_CR2_BRRDY) == 0U) {
;
}
}
stm32mp_clk_disable(RTCAPB);
- stm32_rtc_get_calendar(&sleep_time);
-
enter_cstop_done = true;
}
@@ -265,8 +290,7 @@ void stm32_exit_cstop(void)
stdby_time_in_ms = stm32_rtc_diff_calendar(&current_calendar,
&sleep_time);
- stm32mp_stgen_restore_counter(stm32_get_stgen_from_context(),
- stdby_time_in_ms);
+ stm32mp_stgen_restore_counter(stgen_cnt, stdby_time_in_ms);
stm32mp1_syscfg_enable_io_compensation();
@@ -275,6 +299,94 @@ void stm32_exit_cstop(void)
}
}
+static int get_locked(volatile int *state)
+{
+ volatile int val;
+
+ spin_lock(&lp_lock);
+ val = *state;
+ spin_unlock(&lp_lock);
+
+ return val;
+}
+
+static void set_locked(volatile int *state, int val)
+{
+ spin_lock(&lp_lock);
+ *state = val;
+ spin_unlock(&lp_lock);
+}
+
+static void smp_synchro(int state, bool wake_up)
+{
+ /* if the other CPU is stopped, no need to synchronize */
+ if (psci_is_last_on_cpu() == 1U) {
+ return;
+ }
+
+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) {
+ set_locked(&cpu0_state, state);
+
+ while (get_locked(&cpu1_state) != state) {
+ if (wake_up) {
+ /* wakeup secondary CPU */
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6,
+ STM32MP_SECONDARY_CPU);
+ udelay(10);
+ }
+ };
+ } else {
+ while (get_locked(&cpu0_state) != state) {
+ if (wake_up) {
+ /* wakeup primary CPU */
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_6,
+ STM32MP_PRIMARY_CPU);
+ udelay(10);
+ }
+ };
+
+ set_locked(&cpu1_state, state);
+ }
+}
+
+static void stm32_auto_stop_cpu0(void)
+{
+ smp_synchro(STATE_AUTOSTOP_ENTRY, false);
+
+ enter_cstop(STM32_PM_CSTOP_ALLOW_LP_STOP, 0);
+
+ stm32_pwr_down_wfi();
+
+ stm32_exit_cstop();
+
+ smp_synchro(STATE_AUTOSTOP_EXIT, true);
+}
+
+static void stm32_auto_stop_cpu1(void)
+{
+ unsigned int gicc_pmr_cpu1;
+
+ /* clear cache before the DDR is being disabled by cpu0 */
+ dcsw_op_all(DC_OP_CISW);
+
+ smp_synchro(STATE_AUTOSTOP_ENTRY, false);
+
+ gicc_pmr_cpu1 = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8);
+ wfi();
+ plat_ic_set_priority_mask(gicc_pmr_cpu1);
+
+ smp_synchro(STATE_AUTOSTOP_EXIT, true);
+}
+
+void stm32_auto_stop(void)
+{
+ if (plat_my_core_pos() == STM32MP_PRIMARY_CPU) {
+ stm32_auto_stop_cpu0();
+ } else {
+ stm32_auto_stop_cpu1();
+ }
+}
+
static void enter_shutdown(void)
{
/* Set DDR in Self-refresh before shutting down the platform */
diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c
index 079c5eece..da9d84b2e 100644
--- a/plat/st/stm32mp1/stm32mp1_power_config.c
+++ b/plat/st/stm32mp1/stm32mp1_power_config.c
@@ -18,9 +18,11 @@
#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes"
#define SYSTEM_OFF_MODE "system_off_soc_mode"
+#define RETRAM_ENABLED "st,retram-enabled-in-standby-ddr-sr"
static uint32_t deepest_system_suspend_mode;
static uint32_t system_off_mode;
+static bool retram_enabled;
static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE];
static int dt_get_pwr_node(void)
@@ -96,12 +98,40 @@ static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state)
return 0;
}
+static int dt_fill_retram_enabled(void)
+{
+ int pwr_node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ pwr_node = dt_get_pwr_node();
+ if (pwr_node < 0) {
+ return -ENOENT;
+ }
+
+ if (fdt_getprop(fdt, pwr_node, RETRAM_ENABLED, NULL) == NULL) {
+ retram_enabled = false;
+ } else {
+ retram_enabled = true;
+ }
+
+ return 0;
+}
+
void stm32mp1_init_lp_states(void)
{
if (dt_fill_lp_state(&system_off_mode, SYSTEM_OFF_MODE) < 0) {
ERROR("Node %s not found\n", SYSTEM_OFF_MODE);
panic();
}
+
+ if (dt_fill_retram_enabled() < 0) {
+ ERROR("could not configure retram state\n");
+ panic();
+ }
}
/* Init with all domains ON */
@@ -185,3 +215,8 @@ int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode)
return 0;
}
+
+bool stm32mp1_get_retram_enabled(void)
+{
+ return retram_enabled;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index b94857bcb..1a57a7b68 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -101,7 +101,9 @@ static const mmap_region_t stm32mp1_mmap[] = {
MAP_SRAM_MCU,
#endif
MAP_DEVICE1,
+#if !STM32MP_SSP
MAP_DEVICE2,
+#endif
{0}
};
#endif
@@ -189,6 +191,7 @@ void __dead2 stm32mp_wait_cpu_reset(void)
}
}
+#if defined(IMAGE_BL32)
/*
* 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):
@@ -232,9 +235,22 @@ static const struct tzc_source_ip tzc_source_ip[] = {
_TZC_COND(DMA1_R, DMA1, STM32MP1_ETZPC_DMA1_ID),
_TZC_COND(DMA2_R, DMA2, STM32MP1_ETZPC_DMA2_ID),
};
+#endif
#define TIMEOUT_US_1MS U(1000)
+#if defined(IMAGE_BL2)
+void __dead2 stm32mp_plat_reset(int cpu)
+{
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPSYSRST);
+
+ /* Loop in case system reset is not immediately caught */
+ for ( ; ; ) {
+ ;
+ }
+}
+#else
void __dead2 stm32mp_plat_reset(int cpu)
{
uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST;
@@ -289,6 +305,7 @@ void __dead2 stm32mp_plat_reset(int cpu)
stm32mp_wait_cpu_reset();
}
+#endif /* IMAGE_BL2 */
unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
{
@@ -420,6 +437,23 @@ bool stm32mp_supports_cpu_opp(uint32_t opp_id)
}
}
+#if STM32MP_SSP
+bool stm32mp_supports_ssp(void)
+{
+ switch (get_part_number()) {
+ case STM32MP157F_PART_NB:
+ case STM32MP157C_PART_NB:
+ case STM32MP153F_PART_NB:
+ case STM32MP153C_PART_NB:
+ case STM32MP151F_PART_NB:
+ case STM32MP151C_PART_NB:
+ return true;
+ default:
+ return false;
+ }
+}
+#endif /* STM32MP_SSP */
+
void stm32mp_print_cpuinfo(void)
{
const char *cpu_s, *cpu_r, *pkg;
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
index c1e91538f..bd1e4e071 100644
--- a/plat/st/stm32mp1/stm32mp1_scmi.c
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -128,6 +128,7 @@ static struct stm32_scmi_rd stm32_scmi0_reset_domain[] = {
RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+ RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"),
};
struct scmi_agent_resources {
@@ -444,6 +445,10 @@ int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id,
return SCMI_NOT_FOUND;
}
+ if (rd->reset_id == MCU_HOLD_BOOT_R) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
if (!stm32mp_nsec_can_access_reset(rd->reset_id)) {
return SCMI_DENIED;
}
@@ -479,6 +484,13 @@ int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id,
return SCMI_DENIED;
}
+ if (rd->reset_id == MCU_HOLD_BOOT_R) {
+ VERBOSE("SCMI MCU reset %s\n",
+ assert_not_deassert ? "set" : "release");
+ stm32mp_reset_assert_deassert_to_mcu(assert_not_deassert);
+ return SCMI_SUCCESS;
+ }
+
if (assert_not_deassert) {
VERBOSE("SCMI reset %lu set\n", rd->reset_id);
stm32mp_reset_set(rd->reset_id);
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
index 232fbebdb..df4224be3 100644
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -66,6 +66,7 @@ static const char *shres2str_id(unsigned int id)
return shres2str_id_tbl[id];
}
+#if !STM32MP_SSP
static const char *shres2str_state_tbl[4] = {
[SHRES_UNREGISTERED] = "unregistered",
[SHRES_NON_SECURE] = "non-secure",
@@ -76,6 +77,7 @@ static const char *shres2str_state(unsigned int id)
{
return shres2str_state_tbl[id];
}
+#endif /* !STM32MP_SSP */
struct shres2decprot {
unsigned int shres_id;
@@ -146,6 +148,12 @@ static unsigned int get_gpioz_nbpin(void)
return (unsigned int)gpioz_nbpin;
}
+#if STM32MP_SSP
+static void register_periph(unsigned int id __unused,
+ unsigned int state __unused)
+{
+}
+#else
static void register_periph(unsigned int id, unsigned int state)
{
assert((id < STM32MP1_SHRES_COUNT) &&
@@ -227,6 +235,7 @@ static void register_periph(unsigned int id, unsigned int state)
}
}
}
+#endif /* STM32MP_SSP */
static bool stm32mp1_mckprot_resource(unsigned int id)
{
@@ -375,13 +384,18 @@ void stm32mp1_register_etzpc_decprot(unsigned int id,
switch (id) {
case STM32MP1_ETZPC_STGENC_ID:
case STM32MP1_ETZPC_BKPSRAM_ID:
- case STM32MP1_ETZPC_DDRCTRL_ID:
- case STM32MP1_ETZPC_DDRPHYC_ID:
/* We assume these must always be assigned to secure world */
if (state != SHRES_SECURE) {
panic();
}
break;
+ case STM32MP1_ETZPC_DDRCTRL_ID:
+ case STM32MP1_ETZPC_DDRPHYC_ID:
+ /* allow write only for secure world */
+ if ((attr != TZPC_DECPROT_S_RW) && (attr != TZPC_DECPROT_NS_R_S_W)) {
+ panic();
+ }
+ break;
default:
id_shres = decprot2shres(id);
if (id_shres == SHRES_INVALID) {
@@ -580,6 +594,7 @@ bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
shres_id = STM32MP1_SHRES_MDMA;
break;
case MCU_R:
+ case MCU_HOLD_BOOT_R:
shres_id = STM32MP1_SHRES_MCU;
break;
default:
@@ -628,6 +643,7 @@ static bool check_decprot(unsigned int id, enum etzpc_decprot_attributes exp)
case TZPC_DECPROT_NS_R_S_W:
case TZPC_DECPROT_MCU_ISOLATION:
+ break;
default:
panic();
}
@@ -663,9 +679,15 @@ static void check_etzpc_secure_configuration(void)
error |= !check_decprot(STM32MP1_ETZPC_CRYP1_ID,
decprot_periph_attr(STM32MP1_SHRES_CRYP1));
- error |= !check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, TZPC_DECPROT_S_RW);
+ error |= !((check_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+ TZPC_DECPROT_NS_R_S_W)) ||
+ (check_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+ TZPC_DECPROT_S_RW)));
- error |= !check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, TZPC_DECPROT_S_RW);
+ error |= !((check_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+ TZPC_DECPROT_NS_R_S_W)) ||
+ (check_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+ TZPC_DECPROT_S_RW)));
error |= !check_decprot(STM32MP1_ETZPC_I2C6_ID,
decprot_periph_attr(STM32MP1_SHRES_I2C6));
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.S b/plat/st/stm32mp1/stm32mp1_ssp.S
new file mode 100644
index 000000000..83a66c2aa
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_ssp.S
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .dtb_image
+.incbin DTB_BIN_PATH
+
+.section .bl2_image
+.incbin BL2_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.ld.S b/plat/st/stm32mp1/stm32mp1_ssp.ld.S
new file mode 100644
index 000000000..5f05e7be6
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_ssp.ld.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define TF_LINKER_SCRIPT
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+
+ENTRY(__BL2_IMAGE_START__)
+
+MEMORY {
+ HEADER (rw) : ORIGIN = STM32MP_DTB_BASE, LENGTH = 0x3000
+ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE
+}
+
+SECTIONS
+{
+ /*
+ * TF mapping must conform to ROM code specification.
+ */
+ .header : {
+ __HEADER_START__ = .;
+ KEEP(*(.header))
+ . = ALIGN(4);
+ __HEADER_END__ = .;
+ } >HEADER
+
+ . = STM32MP_BINARY_BASE;
+ .data . : {
+ . = ALIGN(PAGE_SIZE);
+ __DATA_START__ = .;
+ *(.data*)
+
+ /*
+ * Device tree
+ */
+ __DTB_IMAGE_START__ = .;
+ *(.dtb_image*)
+ __DTB_IMAGE_END__ = .;
+
+ /*
+ * BL2 image
+ */
+ . = (STM32MP_BL2_BASE - STM32MP_BINARY_BASE);
+ __BL2_IMAGE_START__ = .;
+ *(.bl2_image*)
+ __BL2_IMAGE_END__ = .;
+ __DATA_END__ = .;
+ } >RAM
+
+ __TF_END__ = .;
+
+}
+#undef TF_LINKER_SCRIPT
diff --git a/plat/st/stm32mp1/stm32mp1_ssp.mk b/plat/st/stm32mp1/stm32mp1_ssp.mk
new file mode 100644
index 000000000..6d1fc49dc
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_ssp.mk
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ST_VERSION := r1.0
+VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING}
+
+# Required to use BL2_IN_XIP_MEM
+BL2_IN_XIP_MEM := 1
+$(eval $(call add_define,BL2_IN_XIP_MEM))
+
+SEPARATE_CODE_AND_RODATA := 1
+
+# Macros and rules to build TF-A binary
+STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
+STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=)
+STM32_TF_SSP_STM32 := ${BUILD_PLAT}/tf-a-ssp-${STM32_DT_BASENAME}.stm32
+STM32_TF_SSP_BINARY := $(STM32_TF_SSP_STM32:.stm32=.bin)
+STM32_TF_SSP_MAPFILE := $(STM32_TF_SSP_STM32:.stm32=.map)
+STM32_TF_SSP_LINKERFILE := $(STM32_TF_SSP_STM32:.stm32=.ld)
+STM32_TF_SSP_ELF := $(STM32_TF_SSP_STM32:.stm32=.elf)
+STM32_TF_SSP_OBJS := ${BUILD_PLAT}/stm32mp1-ssp.o
+STM32_TF_SSP_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
+
+BL2_SOURCES += lib/ssp/ssp.c
+
+${STM32_TF_SSP_OBJS}: plat/st/stm32mp1/stm32mp1_ssp.S bl2 ${STM32_TF_SSP_DTBFILE}
+ @echo " AS $<"
+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+ -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \
+ -DDTB_BIN_PATH=\"${STM32_TF_SSP_DTBFILE}\" \
+ -c plat/st/stm32mp1/stm32mp1_ssp.S -o $@
+
+
+${STM32_TF_SSP_LINKERFILE}: plat/st/stm32mp1/stm32mp1_ssp.ld.S
+ @echo " LDS $<"
+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
+
+${STM32_TF_SSP_ELF}: ${STM32_TF_SSP_OBJS} ${STM32_TF_SSP_LINKERFILE}
+ @echo " LDS $<"
+ ${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} \
+ -Map=${STM32_TF_SSP_MAPFILE} \
+ --script ${STM32_TF_SSP_LINKERFILE} \
+ ${STM32_TF_SSP_OBJS}
+
+${STM32_TF_SSP_BINARY}: ${STM32_TF_SSP_ELF}
+ ${Q}${OC} -O binary ${STM32_TF_SSP_ELF} $@
+ @echo
+ @echo "Built $@ successfully"
+ @echo
+
+${STM32_TF_SSP_STM32}: check_dtc_version stm32image ${STM32_TF_SSP_BINARY}
+ @echo
+ @echo "Generated $@"
+ $(eval LOADADDR = $(shell cat ${STM32_TF_SSP_MAPFILE} | grep RAM | awk '{print $$2}'))
+ $(eval ENTRY = $(shell cat ${STM32_TF_SSP_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+ ${STM32IMAGE} -s ${STM32_TF_SSP_BINARY} -d $@ \
+ -l $(LOADADDR) -e ${ENTRY} \
+ -v ${STM32_TF_VERSION} \
+ -m ${STM32_HEADER_VERSION_MAJOR} \
+ -n ${STM32_HEADER_VERSION_MINOR}
+ @echo
+
+all: ${STM32_TF_SSP_STM32}
--
2.17.1