From 3e97529fe31f7f87396b2a58c17189d03e7f0c76 Mon Sep 17 00:00:00 2001 From: Romuald JEANNE 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 #include #include +#include #include #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)¤t_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 +#include #include #include #include @@ -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 #include #include +#include /* 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)¤t_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 = ; + 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 = ; + 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 +#include + /* 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 + +/* 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 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 #include #include +#include #include #include @@ -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 #include +#include + #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 #include +#include #include #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 #include #include +#include +#include #include #include @@ -31,12 +33,14 @@ #include #include #include +#include #include 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(¤t_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 + +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