5753 lines
161 KiB
Diff
5753 lines
161 KiB
Diff
From 74771d5557e59fd428c2a6df2323601da27c19ea Mon Sep 17 00:00:00 2001
|
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
|
Date: Tue, 17 Sep 2019 12:30:44 +0200
|
|
Subject: [PATCH] st update r1.1.0
|
|
|
|
---
|
|
.../memory-controllers/st,stm32mp1-ddr.txt | 299 +++++++++++
|
|
drivers/mmc/mmc.c | 10 +-
|
|
drivers/st/bsec/bsec.c | 334 +++++-------
|
|
drivers/st/clk/stm32mp1_calib.c | 530 +++++++++++++++++++
|
|
drivers/st/clk/stm32mp1_clk.c | 578 +++------------------
|
|
drivers/st/ddr/stm32mp1_ddr.c | 93 ++--
|
|
drivers/st/ddr/stm32mp1_ram.c | 4 +-
|
|
drivers/st/i2c/stm32_i2c.c | 41 +-
|
|
drivers/st/iwdg/stm32_iwdg.c | 20 +-
|
|
drivers/st/mmc/stm32_sdmmc2.c | 47 +-
|
|
drivers/st/nand/nand.c | 136 ++---
|
|
drivers/st/timer/stm32_timer.c | 27 +-
|
|
fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 13 +-
|
|
fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 10 +-
|
|
fdts/stm32mp157a-dk1.dts | 16 +-
|
|
fdts/stm32mp157c-ed1.dts | 35 +-
|
|
fdts/stm32mp157c-security.dtsi | 5 +-
|
|
fdts/stm32mp157c.dtsi | 21 +
|
|
include/drivers/mmc.h | 1 +
|
|
include/drivers/st/bsec.h | 19 +-
|
|
include/drivers/st/nand.h | 48 +-
|
|
include/drivers/st/stm32_iwdg.h | 4 +-
|
|
include/drivers/st/stm32_sdmmc2.h | 3 +-
|
|
include/drivers/st/stm32mp1_calib.h | 20 +
|
|
include/drivers/st/stm32mp1_clk.h | 11 +-
|
|
include/drivers/st/stm32mp1_pwr.h | 2 +
|
|
include/drivers/st/stm32mp1_rcc.h | 86 ++-
|
|
include/lib/aarch32/arch.h | 5 +-
|
|
include/lib/aarch32/arch_helpers.h | 5 +-
|
|
plat/st/common/bl2_io_storage.c | 550 ++++++++++----------
|
|
plat/st/common/include/stm32mp_auth.h | 8 +
|
|
plat/st/common/stm32mp_auth.c | 23 +-
|
|
plat/st/common/stm32mp_dt.c | 15 +-
|
|
plat/st/stm32mp1/bl2_plat_setup.c | 23 +-
|
|
plat/st/stm32mp1/include/stm32mp1_private.h | 5 +
|
|
plat/st/stm32mp1/platform.mk | 41 +-
|
|
plat/st/stm32mp1/services/bsec_svc.c | 27 +-
|
|
plat/st/stm32mp1/services/rcc_svc.c | 4 +-
|
|
plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 1 +
|
|
plat/st/stm32mp1/sp_min/sp_min_setup.c | 60 ++-
|
|
plat/st/stm32mp1/stm32mp1_def.h | 17 +-
|
|
plat/st/stm32mp1/stm32mp1_helper.S | 13 +-
|
|
plat/st/stm32mp1/stm32mp1_low_power.c | 32 +-
|
|
plat/st/stm32mp1/stm32mp1_pm.c | 17 +-
|
|
plat/st/stm32mp1/stm32mp1_private.c | 203 +++++++-
|
|
plat/st/stm32mp1/stm32mp1_security.c | 17 +-
|
|
plat/st/stm32mp1/stm32mp1_shared_resources.c | 4 +-
|
|
plat/st/stm32mp1/stm32mp1_syscfg.c | 77 ++-
|
|
48 files changed, 2200 insertions(+), 1360 deletions(-)
|
|
create mode 100644 docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
create mode 100644 drivers/st/clk/stm32mp1_calib.c
|
|
create mode 100644 include/drivers/st/stm32mp1_calib.h
|
|
|
|
diff --git a/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
new file mode 100644
|
|
index 0000000..ee708ce
|
|
--- /dev/null
|
|
+++ b/docs/devicetree/bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
@@ -0,0 +1,299 @@
|
|
+ST,stm32mp1 DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL and DDRPHYC)
|
|
+
|
|
+--------------------
|
|
+Required properties:
|
|
+--------------------
|
|
+- compatible : Should be "st,stm32mp1-ddr"
|
|
+- reg : controleur (DDRCTRL) and phy (DDRPHYC) base address
|
|
+- clocks : controller clocks handle
|
|
+- clock-names : associated controller clock names
|
|
+ the "ddrphyc" clock is used to check the DDR frequency
|
|
+ at phy level according the expected value in "mem-speed" field
|
|
+
|
|
+the next attributes are DDR parameters, they are generated by DDR tools
|
|
+included in STM32 Cube tool
|
|
+
|
|
+info attributes:
|
|
+----------------
|
|
+- st,mem-name : name for DDR configuration, simple string for information
|
|
+- st,mem-speed : DDR expected speed for the setting in kHz
|
|
+- st,mem-size : DDR mem size in byte
|
|
+
|
|
+
|
|
+controlleur attributes:
|
|
+-----------------------
|
|
+- st,ctl-reg : controleur values depending of the DDR type
|
|
+ (DDR3/LPDDR2/LPDDR3)
|
|
+ for STM32MP15x: 25 values are requested in this order
|
|
+ MSTR
|
|
+ MRCTRL0
|
|
+ MRCTRL1
|
|
+ DERATEEN
|
|
+ DERATEINT
|
|
+ PWRCTL
|
|
+ PWRTMG
|
|
+ HWLPCTL
|
|
+ RFSHCTL0
|
|
+ RFSHCTL3
|
|
+ CRCPARCTL0
|
|
+ ZQCTL0
|
|
+ DFITMG0
|
|
+ DFITMG1
|
|
+ DFILPCFG0
|
|
+ DFIUPD0
|
|
+ DFIUPD1
|
|
+ DFIUPD2
|
|
+ DFIPHYMSTR
|
|
+ ODTMAP
|
|
+ DBG0
|
|
+ DBG1
|
|
+ DBGCMD
|
|
+ POISONCFG
|
|
+ PCCFG
|
|
+
|
|
+- st,ctl-timing : controleur values depending of frequency and timing parameter
|
|
+ of DDR
|
|
+ for STM32MP15x: 12 values are requested in this order
|
|
+ RFSHTMG
|
|
+ DRAMTMG0
|
|
+ DRAMTMG1
|
|
+ DRAMTMG2
|
|
+ DRAMTMG3
|
|
+ DRAMTMG4
|
|
+ DRAMTMG5
|
|
+ DRAMTMG6
|
|
+ DRAMTMG7
|
|
+ DRAMTMG8
|
|
+ DRAMTMG14
|
|
+ ODTCFG
|
|
+
|
|
+- st,ctl-map : controleur values depending of address mapping
|
|
+ for STM32MP15x: 9 values are requested in this order
|
|
+ ADDRMAP1
|
|
+ ADDRMAP2
|
|
+ ADDRMAP3
|
|
+ ADDRMAP4
|
|
+ ADDRMAP5
|
|
+ ADDRMAP6
|
|
+ ADDRMAP9
|
|
+ ADDRMAP10
|
|
+ ADDRMAP11
|
|
+
|
|
+- st,ctl-perf : controleur values depending of performance and scheduling
|
|
+ for STM32MP15x: 17 values are requested in this order
|
|
+ SCHED
|
|
+ SCHED1
|
|
+ PERFHPR1
|
|
+ PERFLPR1
|
|
+ PERFWR1
|
|
+ PCFGR_0
|
|
+ PCFGW_0
|
|
+ PCFGQOS0_0
|
|
+ PCFGQOS1_0
|
|
+ PCFGWQOS0_0
|
|
+ PCFGWQOS1_0
|
|
+ PCFGR_1
|
|
+ PCFGW_1
|
|
+ PCFGQOS0_1
|
|
+ PCFGQOS1_1
|
|
+ PCFGWQOS0_1
|
|
+ PCFGWQOS1_1
|
|
+
|
|
+phyc attributes:
|
|
+----------------
|
|
+- st,phy-reg : phy values depending of the DDR type (DDR3/LPDDR2/LPDDR3)
|
|
+ for STM32MP15x: 11 values are requested in this order
|
|
+ PGCR
|
|
+ ACIOCR
|
|
+ DXCCR
|
|
+ DSGCR
|
|
+ DCR
|
|
+ ODTCR
|
|
+ ZQ0CR1
|
|
+ DX0GCR
|
|
+ DX1GCR
|
|
+ DX2GCR
|
|
+ DX3GCR
|
|
+
|
|
+- st,phy-timing : phy values depending of frequency and timing parameter of DDR
|
|
+ for STM32MP15x: 10 values are requested in this order
|
|
+ PTR0
|
|
+ PTR1
|
|
+ PTR2
|
|
+ DTPR0
|
|
+ DTPR1
|
|
+ DTPR2
|
|
+ MR0
|
|
+ MR1
|
|
+ MR2
|
|
+ MR3
|
|
+
|
|
+- st,phy-cal : phy cal depending of calibration or tuning of DDR
|
|
+ for STM32MP15x: 12 values are requested in this order
|
|
+ DX0DLLCR
|
|
+ DX0DQTR
|
|
+ DX0DQSTR
|
|
+ DX1DLLCR
|
|
+ DX1DQTR
|
|
+ DX1DQSTR
|
|
+ DX2DLLCR
|
|
+ DX2DQTR
|
|
+ DX2DQSTR
|
|
+ DX3DLLCR
|
|
+ DX3DQTR
|
|
+ DX3DQSTR
|
|
+
|
|
+Example:
|
|
+
|
|
+/ {
|
|
+ soc {
|
|
+ u-boot,dm-spl;
|
|
+
|
|
+ ddr: ddr@0x5A003000{
|
|
+ u-boot,dm-spl;
|
|
+ u-boot,dm-pre-reloc;
|
|
+
|
|
+ compatible = "st,stm32mp1-ddr";
|
|
+
|
|
+ reg = <0x5A003000 0x550
|
|
+ 0x5A004000 0x234>;
|
|
+
|
|
+ clocks = <&rcc_clk AXIDCG>,
|
|
+ <&rcc_clk DDRC1>,
|
|
+ <&rcc_clk DDRC2>,
|
|
+ <&rcc_clk DDRPHYC>,
|
|
+ <&rcc_clk DDRCAPB>,
|
|
+ <&rcc_clk DDRPHYCAPB>;
|
|
+
|
|
+ clock-names = "axidcg",
|
|
+ "ddrc1",
|
|
+ "ddrc2",
|
|
+ "ddrphyc",
|
|
+ "ddrcapb",
|
|
+ "ddrphycapb";
|
|
+
|
|
+ st,mem-name = "DDR3 2x4Gb 533MHz";
|
|
+ st,mem-speed = <533000>;
|
|
+ st,mem-size = <0x40000000>;
|
|
+
|
|
+ st,ctl-reg = <
|
|
+ 0x00040401 /*MSTR*/
|
|
+ 0x00000010 /*MRCTRL0*/
|
|
+ 0x00000000 /*MRCTRL1*/
|
|
+ 0x00000000 /*DERATEEN*/
|
|
+ 0x00800000 /*DERATEINT*/
|
|
+ 0x00000000 /*PWRCTL*/
|
|
+ 0x00400010 /*PWRTMG*/
|
|
+ 0x00000000 /*HWLPCTL*/
|
|
+ 0x00210000 /*RFSHCTL0*/
|
|
+ 0x00000000 /*RFSHCTL3*/
|
|
+ 0x00000000 /*CRCPARCTL0*/
|
|
+ 0xC2000040 /*ZQCTL0*/
|
|
+ 0x02050105 /*DFITMG0*/
|
|
+ 0x00000202 /*DFITMG1*/
|
|
+ 0x07000000 /*DFILPCFG0*/
|
|
+ 0xC0400003 /*DFIUPD0*/
|
|
+ 0x00000000 /*DFIUPD1*/
|
|
+ 0x00000000 /*DFIUPD2*/
|
|
+ 0x00000000 /*DFIPHYMSTR*/
|
|
+ 0x00000001 /*ODTMAP*/
|
|
+ 0x00000000 /*DBG0*/
|
|
+ 0x00000000 /*DBG1*/
|
|
+ 0x00000000 /*DBGCMD*/
|
|
+ 0x00000000 /*POISONCFG*/
|
|
+ 0x00000010 /*PCCFG*/
|
|
+ >;
|
|
+
|
|
+ st,ctl-timing = <
|
|
+ 0x0080008A /*RFSHTMG*/
|
|
+ 0x121B2414 /*DRAMTMG0*/
|
|
+ 0x000D041B /*DRAMTMG1*/
|
|
+ 0x0607080E /*DRAMTMG2*/
|
|
+ 0x0050400C /*DRAMTMG3*/
|
|
+ 0x07040407 /*DRAMTMG4*/
|
|
+ 0x06060303 /*DRAMTMG5*/
|
|
+ 0x02020002 /*DRAMTMG6*/
|
|
+ 0x00000202 /*DRAMTMG7*/
|
|
+ 0x00001005 /*DRAMTMG8*/
|
|
+ 0x000D041B /*DRAMTMG1*/4
|
|
+ 0x06000600 /*ODTCFG*/
|
|
+ >;
|
|
+
|
|
+ st,ctl-map = <
|
|
+ 0x00080808 /*ADDRMAP1*/
|
|
+ 0x00000000 /*ADDRMAP2*/
|
|
+ 0x00000000 /*ADDRMAP3*/
|
|
+ 0x00001F1F /*ADDRMAP4*/
|
|
+ 0x07070707 /*ADDRMAP5*/
|
|
+ 0x0F070707 /*ADDRMAP6*/
|
|
+ 0x00000000 /*ADDRMAP9*/
|
|
+ 0x00000000 /*ADDRMAP10*/
|
|
+ 0x00000000 /*ADDRMAP11*/
|
|
+ >;
|
|
+
|
|
+ st,ctl-perf = <
|
|
+ 0x00001201 /*SCHED*/
|
|
+ 0x00001201 /*SCHED*/1
|
|
+ 0x01000001 /*PERFHPR1*/
|
|
+ 0x08000200 /*PERFLPR1*/
|
|
+ 0x08000400 /*PERFWR1*/
|
|
+ 0x00010000 /*PCFGR_0*/
|
|
+ 0x00000000 /*PCFGW_0*/
|
|
+ 0x02100B03 /*PCFGQOS0_0*/
|
|
+ 0x00800100 /*PCFGQOS1_0*/
|
|
+ 0x01100B03 /*PCFGWQOS0_0*/
|
|
+ 0x01000200 /*PCFGWQOS1_0*/
|
|
+ 0x00010000 /*PCFGR_1*/
|
|
+ 0x00000000 /*PCFGW_1*/
|
|
+ 0x02100B03 /*PCFGQOS0_1*/
|
|
+ 0x00800000 /*PCFGQOS1_1*/
|
|
+ 0x01100B03 /*PCFGWQOS0_1*/
|
|
+ 0x01000200 /*PCFGWQOS1_1*/
|
|
+ >;
|
|
+
|
|
+ st,phy-reg = <
|
|
+ 0x01442E02 /*PGCR*/
|
|
+ 0x10400812 /*ACIOCR*/
|
|
+ 0x00000C40 /*DXCCR*/
|
|
+ 0xF200001F /*DSGCR*/
|
|
+ 0x0000000B /*DCR*/
|
|
+ 0x00010000 /*ODTCR*/
|
|
+ 0x0000007B /*ZQ0CR1*/
|
|
+ 0x0000CE81 /*DX0GCR*/
|
|
+ 0x0000CE81 /*DX1GCR*/
|
|
+ 0x0000CE81 /*DX2GCR*/
|
|
+ 0x0000CE81 /*DX3GCR*/
|
|
+ >;
|
|
+
|
|
+ st,phy-timing = <
|
|
+ 0x0022A41B /*PTR0*/
|
|
+ 0x047C0740 /*PTR1*/
|
|
+ 0x042D9C80 /*PTR2*/
|
|
+ 0x369477D0 /*DTPR0*/
|
|
+ 0x098A00D8 /*DTPR1*/
|
|
+ 0x10023600 /*DTPR2*/
|
|
+ 0x00000830 /*MR0*/
|
|
+ 0x00000000 /*MR1*/
|
|
+ 0x00000208 /*MR2*/
|
|
+ 0x00000000 /*MR3*/
|
|
+ >;
|
|
+
|
|
+ st,phy-cal = <
|
|
+ 0x40000000 /*DX0DLLCR*/
|
|
+ 0xFFFFFFFF /*DX0DQTR*/
|
|
+ 0x3DB02000 /*DX0DQSTR*/
|
|
+ 0x40000000 /*DX1DLLCR*/
|
|
+ 0xFFFFFFFF /*DX1DQTR*/
|
|
+ 0x3DB02000 /*DX1DQSTR*/
|
|
+ 0x40000000 /*DX2DLLCR*/
|
|
+ 0xFFFFFFFF /*DX2DQTR*/
|
|
+ 0x3DB02000 /*DX2DQSTR*/
|
|
+ 0x40000000 /*DX3DLLCR*/
|
|
+ 0xFFFFFFFF /*DX3DQTR*/
|
|
+ 0x3DB02000 /*DX3DQSTR*/
|
|
+ >;
|
|
+
|
|
+ status = "okay";
|
|
+ };
|
|
+ };
|
|
+};
|
|
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
|
|
index 4f9cecf..3f9657d 100644
|
|
--- a/drivers/mmc/mmc.c
|
|
+++ b/drivers/mmc/mmc.c
|
|
@@ -28,6 +28,7 @@ static unsigned char mmc_ext_csd[512] __aligned(16);
|
|
static unsigned int mmc_flags;
|
|
static struct mmc_device_info *mmc_dev_info;
|
|
static unsigned int rca;
|
|
+static unsigned int scr[2] __aligned(16) = { 0 };
|
|
|
|
static const unsigned char tran_speed_base[16] = {
|
|
0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
|
|
@@ -89,7 +90,8 @@ static int mmc_device_state(void)
|
|
ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
|
|
MMC_RESPONSE_R1, &resp_data[0]);
|
|
if (ret != 0) {
|
|
- return ret;
|
|
+ retries--;
|
|
+ continue;
|
|
}
|
|
|
|
if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
|
|
@@ -128,7 +130,6 @@ static int mmc_sd_switch(unsigned int bus_width)
|
|
{
|
|
int ret;
|
|
int retries = MMC_DEFAULT_MAX_RETRIES;
|
|
- unsigned int scr[2] = { 0 };
|
|
unsigned int bus_width_arg = 0;
|
|
|
|
ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr));
|
|
@@ -340,8 +341,9 @@ static int sd_send_op_cond(void)
|
|
}
|
|
|
|
/* ACMD41: SD_SEND_OP_COND */
|
|
- ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R3,
|
|
- &resp_data[0]);
|
|
+ ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS |
|
|
+ mmc_dev_info->ocr_voltage, MMC_RESPONSE_R3,
|
|
+ &resp_data[0]);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
|
|
index c579c41..3dad2c2 100644
|
|
--- a/drivers/st/bsec/bsec.c
|
|
+++ b/drivers/st/bsec/bsec.c
|
|
@@ -125,19 +125,30 @@ static uint32_t otp_bank_offset(uint32_t otp)
|
|
sizeof(uint32_t);
|
|
}
|
|
|
|
-static uint32_t bsec_check_error(uint32_t otp)
|
|
+/*
|
|
+ * bsec_check_error: check BSEC error status.
|
|
+ * otp: OTP number.
|
|
+ * check_disturbed: check only error (false),
|
|
+ * or error and disturbed status (true).
|
|
+ * return value: BSEC_OK if no error.
|
|
+ */
|
|
+static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed)
|
|
{
|
|
uint32_t bit = BIT(otp & BSEC_OTP_MASK);
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
|
|
- if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
|
|
- return BSEC_DISTURBED;
|
|
- }
|
|
-
|
|
if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) {
|
|
return BSEC_ERROR;
|
|
}
|
|
|
|
+ if (!check_disturbed) {
|
|
+ return BSEC_OK;
|
|
+ }
|
|
+
|
|
+ if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
|
|
+ return BSEC_DISTURBED;
|
|
+ }
|
|
+
|
|
return BSEC_OK;
|
|
}
|
|
|
|
@@ -263,14 +274,16 @@ uint32_t bsec_get_config(struct bsec_config *cfg)
|
|
uint32_t bsec_shadow_register(uint32_t otp)
|
|
{
|
|
uint32_t result;
|
|
+ bool value;
|
|
bool power_up = false;
|
|
|
|
- if (otp > STM32MP1_OTP_MAX_ID) {
|
|
- return BSEC_INVALID_PARAM;
|
|
+ result = bsec_read_sr_lock(otp, &value);
|
|
+ if (result != BSEC_OK) {
|
|
+ ERROR("BSEC: %u Sticky-read bit read Error %i\n", otp, result);
|
|
+ return result;
|
|
}
|
|
|
|
- /* Check if shadowing of OTP is locked */
|
|
- if (bsec_read_sr_lock(otp)) {
|
|
+ if (value) {
|
|
VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n",
|
|
otp);
|
|
}
|
|
@@ -287,14 +300,13 @@ uint32_t bsec_shadow_register(uint32_t otp)
|
|
|
|
bsec_lock();
|
|
|
|
- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
|
|
mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ);
|
|
|
|
while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
|
|
;
|
|
}
|
|
|
|
- result = bsec_check_error(otp);
|
|
+ result = bsec_check_error(otp, true);
|
|
|
|
bsec_unlock();
|
|
|
|
@@ -315,22 +327,14 @@ uint32_t bsec_shadow_register(uint32_t otp)
|
|
*/
|
|
uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
|
|
{
|
|
- uint32_t result;
|
|
-
|
|
if (otp > STM32MP1_OTP_MAX_ID) {
|
|
return BSEC_INVALID_PARAM;
|
|
}
|
|
|
|
- bsec_lock();
|
|
-
|
|
*val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF +
|
|
(otp * sizeof(uint32_t)));
|
|
|
|
- result = bsec_check_error(otp);
|
|
-
|
|
- bsec_unlock();
|
|
-
|
|
- return result;
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
@@ -342,24 +346,25 @@ uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
|
|
uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
|
|
{
|
|
uint32_t result;
|
|
+ bool value;
|
|
|
|
- if (otp > STM32MP1_OTP_MAX_ID) {
|
|
- return BSEC_INVALID_PARAM;
|
|
+ result = bsec_read_sw_lock(otp, &value);
|
|
+ if (result != BSEC_OK) {
|
|
+ ERROR("BSEC: %u Sticky-write bit read Error %i\n", otp, result);
|
|
+ return result;
|
|
}
|
|
|
|
- /* Check if programming of OTP is locked */
|
|
- if (bsec_read_sw_lock(otp)) {
|
|
+ if (value) {
|
|
VERBOSE("BSEC: OTP %i is locked and write will be ignored\n",
|
|
otp);
|
|
}
|
|
|
|
+ /* Ensure integrity of each register access sequence */
|
|
bsec_lock();
|
|
|
|
mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF +
|
|
(otp * sizeof(uint32_t)), val);
|
|
|
|
- result = bsec_check_error(otp);
|
|
-
|
|
bsec_unlock();
|
|
|
|
return result;
|
|
@@ -376,13 +381,15 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
|
|
{
|
|
uint32_t result;
|
|
bool power_up = false;
|
|
+ bool value;
|
|
|
|
- if (otp > STM32MP1_OTP_MAX_ID) {
|
|
- return BSEC_INVALID_PARAM;
|
|
+ result = bsec_read_sp_lock(otp, &value);
|
|
+ if (result != BSEC_OK) {
|
|
+ ERROR("BSEC: %u Sticky-prog bit read Error %i\n", otp, result);
|
|
+ return result;
|
|
}
|
|
|
|
- /* Check if programming of OTP is locked */
|
|
- if (bsec_read_sp_lock(otp)) {
|
|
+ if (value) {
|
|
WARN("BSEC: OTP locked, prog will be ignored\n");
|
|
}
|
|
|
|
@@ -403,10 +410,8 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
|
|
|
|
bsec_lock();
|
|
|
|
- /* Set value in write register */
|
|
mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val);
|
|
|
|
- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
|
|
mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE);
|
|
|
|
while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
|
|
@@ -416,7 +421,7 @@ uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
|
|
if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
|
|
result = BSEC_PROG_FAIL;
|
|
} else {
|
|
- result = bsec_check_error(otp);
|
|
+ result = bsec_check_error(otp, true);
|
|
}
|
|
|
|
bsec_unlock();
|
|
@@ -468,10 +473,8 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp)
|
|
|
|
bsec_lock();
|
|
|
|
- /* Set value in write register */
|
|
mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data);
|
|
|
|
- /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
|
|
mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF,
|
|
addr | BSEC_WRITE | BSEC_LOCK);
|
|
|
|
@@ -482,7 +485,7 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp)
|
|
if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
|
|
result = BSEC_PROG_FAIL;
|
|
} else {
|
|
- result = bsec_check_error(otp);
|
|
+ result = bsec_check_error(otp, false);
|
|
}
|
|
|
|
bsec_unlock();
|
|
@@ -497,7 +500,7 @@ uint32_t bsec_permanent_lock_otp(uint32_t otp)
|
|
}
|
|
|
|
/*
|
|
- * bsec_write_debug_conf: write value in debug feature
|
|
+ * bsec_write_debug_conf: write value in debug feature.
|
|
* to enable/disable debug service.
|
|
* val: value to write.
|
|
* return value: BSEC_OK if no error.
|
|
@@ -521,7 +524,7 @@ uint32_t bsec_write_debug_conf(uint32_t val)
|
|
}
|
|
|
|
/*
|
|
- * bsec_read_debug_conf: read debug configuration.
|
|
+ * bsec_read_debug_conf: return debug configuration register value.
|
|
*/
|
|
uint32_t bsec_read_debug_conf(void)
|
|
{
|
|
@@ -537,7 +540,7 @@ uint32_t bsec_get_status(void)
|
|
}
|
|
|
|
/*
|
|
- * bsec_get_hw_conf: return hardware configuration.
|
|
+ * bsec_get_hw_conf: return hardware configuration register value.
|
|
*/
|
|
uint32_t bsec_get_hw_conf(void)
|
|
{
|
|
@@ -545,7 +548,7 @@ uint32_t bsec_get_hw_conf(void)
|
|
}
|
|
|
|
/*
|
|
- * bsec_get_version: return BSEC version.
|
|
+ * bsec_get_version: return BSEC version register value.
|
|
*/
|
|
uint32_t bsec_get_version(void)
|
|
{
|
|
@@ -553,7 +556,7 @@ uint32_t bsec_get_version(void)
|
|
}
|
|
|
|
/*
|
|
- * bsec_get_id: return BSEC ID.
|
|
+ * bsec_get_id: return BSEC ID register value.
|
|
*/
|
|
uint32_t bsec_get_id(void)
|
|
{
|
|
@@ -561,7 +564,7 @@ uint32_t bsec_get_id(void)
|
|
}
|
|
|
|
/*
|
|
- * bsec_get_magic_id: return BSEC magic number.
|
|
+ * bsec_get_magic_id: return BSEC magic number register value.
|
|
*/
|
|
uint32_t bsec_get_magic_id(void)
|
|
{
|
|
@@ -569,229 +572,178 @@ uint32_t bsec_get_magic_id(void)
|
|
}
|
|
|
|
/*
|
|
- * bsec_write_sr_lock: write shadow-read lock.
|
|
+ * bsec_set_sr_lock: set shadow-read lock.
|
|
* otp: OTP number.
|
|
- * value: value to write in the register.
|
|
- * Must be always 1.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_write_sr_lock(uint32_t otp, uint32_t value)
|
|
+uint32_t bsec_set_sr_lock(uint32_t otp)
|
|
{
|
|
- bool result = false;
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
- uint32_t bank_value;
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
|
|
- bsec_lock();
|
|
-
|
|
- bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
|
|
-
|
|
- if ((bank_value & otp_mask) == value) {
|
|
- /*
|
|
- * In case of write don't need to write,
|
|
- * the lock is already set.
|
|
- */
|
|
- if (value != 0U) {
|
|
- result = true;
|
|
- }
|
|
- } else {
|
|
- if (value != 0U) {
|
|
- bank_value = bank_value | otp_mask;
|
|
- } else {
|
|
- bank_value = bank_value & ~otp_mask;
|
|
- }
|
|
-
|
|
- /*
|
|
- * We can write 0 in all other OTP
|
|
- * if the lock is activated in one of other OTP.
|
|
- * Write 0 has no effect.
|
|
- */
|
|
- mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, bank_value);
|
|
- result = true;
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
}
|
|
|
|
+ bsec_lock();
|
|
+ mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask);
|
|
bsec_unlock();
|
|
|
|
- return result;
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
* bsec_read_sr_lock: read shadow-read lock.
|
|
* otp: OTP number.
|
|
- * return: true if otp is locked, else false.
|
|
+ * value: read value (true or false).
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_read_sr_lock(uint32_t otp)
|
|
+uint32_t bsec_read_sr_lock(uint32_t otp, bool *value)
|
|
{
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
|
|
+ uint32_t bank_value;
|
|
+
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
+ }
|
|
|
|
- return (bank_value & otp_mask) != 0U;
|
|
+ bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
|
|
+
|
|
+ *value = ((bank_value & otp_mask) != 0U);
|
|
+
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
- * bsec_write_sw_lock: write shadow-write lock.
|
|
+ * bsec_set_sw_lock: set shadow-write lock.
|
|
* otp: OTP number.
|
|
- * value: Value to write in the register.
|
|
- * Must be always 1.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_write_sw_lock(uint32_t otp, uint32_t value)
|
|
+uint32_t bsec_set_sw_lock(uint32_t otp)
|
|
{
|
|
- bool result = false;
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
- uint32_t bank_value;
|
|
-
|
|
- bsec_lock();
|
|
|
|
- bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
|
|
-
|
|
- if ((bank_value & otp_mask) == value) {
|
|
- /*
|
|
- * In case of write don't need to write,
|
|
- * the lock is already set.
|
|
- */
|
|
- if (value != 0U) {
|
|
- result = true;
|
|
- }
|
|
- } else {
|
|
- if (value != 0U) {
|
|
- bank_value = bank_value | otp_mask;
|
|
- } else {
|
|
- bank_value = bank_value & ~otp_mask;
|
|
- }
|
|
-
|
|
- /*
|
|
- * We can write 0 in all other OTP
|
|
- * if the lock is activated in one of other OTP.
|
|
- * Write 0 has no effect.
|
|
- */
|
|
- mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, bank_value);
|
|
- result = true;
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
}
|
|
|
|
+ bsec_lock();
|
|
+ mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask);
|
|
bsec_unlock();
|
|
|
|
- return result;
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
* bsec_read_sw_lock: read shadow-write lock.
|
|
* otp: OTP number.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * value: read value (true or false).
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_read_sw_lock(uint32_t otp)
|
|
+uint32_t bsec_read_sw_lock(uint32_t otp, bool *value)
|
|
{
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
|
|
+ uint32_t bank_value;
|
|
+
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
+ }
|
|
|
|
- return (bank_value & otp_mask) != 0U;
|
|
+ bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
|
|
+
|
|
+ *value = ((bank_value & otp_mask) != 0U);
|
|
+
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
- * bsec_write_sp_lock: write shadow-program lock.
|
|
+ * bsec_set_sp_lock: set shadow-program lock.
|
|
* otp: OTP number.
|
|
- * value: Value to write in the register.
|
|
- * Must be always 1.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_write_sp_lock(uint32_t otp, uint32_t value)
|
|
+uint32_t bsec_set_sp_lock(uint32_t otp)
|
|
{
|
|
- bool result = false;
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
- uint32_t bank_value;
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
|
|
- bsec_lock();
|
|
-
|
|
- bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
|
|
-
|
|
- if ((bank_value & otp_mask) == value) {
|
|
- /*
|
|
- * In case of write don't need to write,
|
|
- * the lock is already set.
|
|
- */
|
|
- if (value != 0U) {
|
|
- result = true;
|
|
- }
|
|
- } else {
|
|
- if (value != 0U) {
|
|
- bank_value = bank_value | otp_mask;
|
|
- } else {
|
|
- bank_value = bank_value & ~otp_mask;
|
|
- }
|
|
-
|
|
- /*
|
|
- * We can write 0 in all other OTP
|
|
- * if the lock is activated in one of other OTP.
|
|
- * Write 0 has no effect.
|
|
- */
|
|
- mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, bank_value);
|
|
- result = true;
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
}
|
|
|
|
+ bsec_lock();
|
|
+ mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask);
|
|
bsec_unlock();
|
|
|
|
- return result;
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
* bsec_read_sp_lock: read shadow-program lock.
|
|
* otp: OTP number.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * value: read value (true or false).
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_read_sp_lock(uint32_t otp)
|
|
+uint32_t bsec_read_sp_lock(uint32_t otp, bool *value)
|
|
{
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
- uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
|
|
+ uint32_t bank_value;
|
|
+
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
+ }
|
|
+
|
|
+ bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
|
|
+
|
|
+ *value = ((bank_value & otp_mask) != 0U);
|
|
|
|
- return (bank_value & otp_mask) != 0U;
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
- * bsec_wr_lock: Read permanent lock status.
|
|
+ * bsec_read_permanent_lock: Read permanent lock status.
|
|
* otp: OTP number.
|
|
- * return: true if OTP is locked, else false.
|
|
+ * value: read value (true or false).
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-bool bsec_wr_lock(uint32_t otp)
|
|
+uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value)
|
|
{
|
|
uint32_t bank = otp_bank_offset(otp);
|
|
- uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK);
|
|
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
|
|
+ uint32_t bank_value;
|
|
|
|
- if ((mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank) &
|
|
- lock_bit) != 0U) {
|
|
- /*
|
|
- * In case of write don't need to write,
|
|
- * the lock is already set.
|
|
- */
|
|
- return true;
|
|
+ if (otp > STM32MP1_OTP_MAX_ID) {
|
|
+ return BSEC_INVALID_PARAM;
|
|
}
|
|
|
|
- return false;
|
|
+ bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank);
|
|
+
|
|
+ *value = ((bank_value & otp_mask) != 0U);
|
|
+
|
|
+ return BSEC_OK;
|
|
}
|
|
|
|
/*
|
|
- * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable
|
|
- * service: Service to lock see header file.
|
|
- * value: Value to write must always set to 1 (only use for debug purpose).
|
|
- * return: BSEC_OK if succeed.
|
|
+ * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable.
|
|
+ * service: Service to lock, see header file.
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
-uint32_t bsec_otp_lock(uint32_t service, uint32_t value)
|
|
+uint32_t bsec_otp_lock(uint32_t service)
|
|
{
|
|
uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF;
|
|
|
|
switch (service) {
|
|
case BSEC_LOCK_UPPER_OTP:
|
|
- mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP);
|
|
+ mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP));
|
|
break;
|
|
case BSEC_LOCK_DEBUG:
|
|
- mmio_write_32(reg, value << BSEC_LOCK_DEBUG);
|
|
+ mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG));
|
|
break;
|
|
case BSEC_LOCK_PROGRAM:
|
|
- mmio_write_32(reg, value << BSEC_LOCK_PROGRAM);
|
|
+ mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM));
|
|
break;
|
|
default:
|
|
return BSEC_INVALID_PARAM;
|
|
@@ -803,7 +755,7 @@ uint32_t bsec_otp_lock(uint32_t service, uint32_t value)
|
|
/*
|
|
* bsec_power_safmem: Activate or deactivate SAFMEM power.
|
|
* power: true to power up, false to power down.
|
|
- * return: BSEC_OK if succeed.
|
|
+ * return value: BSEC_OK if no error.
|
|
*/
|
|
static uint32_t bsec_power_safmem(bool power)
|
|
{
|
|
@@ -822,7 +774,6 @@ static uint32_t bsec_power_safmem(bool power)
|
|
|
|
mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val);
|
|
|
|
- /* Waiting loop */
|
|
if (power) {
|
|
while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) &&
|
|
(timeout != 0U)) {
|
|
@@ -845,23 +796,7 @@ static uint32_t bsec_power_safmem(bool power)
|
|
}
|
|
|
|
/*
|
|
- * bsec_mode_is_closed_device: read OTP secure sub-mode.
|
|
- * return: false if open_device and true of closed_device.
|
|
- */
|
|
-bool bsec_mode_is_closed_device(void)
|
|
-{
|
|
- uint32_t value;
|
|
-
|
|
- if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) ||
|
|
- (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) {
|
|
- return true;
|
|
- }
|
|
-
|
|
- return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED;
|
|
-}
|
|
-
|
|
-/*
|
|
- * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value
|
|
+ * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value.
|
|
* otp_value: read value.
|
|
* word: OTP number.
|
|
* return value: BSEC_OK if no error.
|
|
@@ -887,7 +822,7 @@ uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word)
|
|
/*
|
|
* bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
|
|
* otp: OTP number.
|
|
- * return: BSEC_OK if authorized access.
|
|
+ * return value: BSEC_OK if authorized access.
|
|
*/
|
|
uint32_t bsec_check_nsec_access_rights(uint32_t otp)
|
|
{
|
|
@@ -897,11 +832,8 @@ uint32_t bsec_check_nsec_access_rights(uint32_t otp)
|
|
}
|
|
|
|
if (otp >= STM32MP1_UPPER_OTP_START) {
|
|
- /* Check if BSEC is in OTP-SECURED closed_device state. */
|
|
- if (bsec_mode_is_closed_device()) {
|
|
- if (!non_secure_can_access(otp)) {
|
|
- return BSEC_ERROR;
|
|
- }
|
|
+ if (!non_secure_can_access(otp)) {
|
|
+ return BSEC_ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
diff --git a/drivers/st/clk/stm32mp1_calib.c b/drivers/st/clk/stm32mp1_calib.c
|
|
new file mode 100644
|
|
index 0000000..030a84f
|
|
--- /dev/null
|
|
+++ b/drivers/st/clk/stm32mp1_calib.c
|
|
@@ -0,0 +1,530 @@
|
|
+/*
|
|
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <arch.h>
|
|
+#include <arch_helpers.h>
|
|
+#include <assert.h>
|
|
+#include <debug.h>
|
|
+#include <delay_timer.h>
|
|
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
|
+#include <errno.h>
|
|
+#include <generic_delay_timer.h>
|
|
+#include <libfdt.h>
|
|
+#include <limits.h>
|
|
+#include <mmio.h>
|
|
+#include <platform.h>
|
|
+#include <spinlock.h>
|
|
+#include <stdint.h>
|
|
+#include <stdio.h>
|
|
+#include <stm32mp_clkfunc.h>
|
|
+#include <stm32mp_common.h>
|
|
+#include <stm32mp_dt.h>
|
|
+#include <stm32mp1_private.h>
|
|
+#include <stm32mp1_rcc.h>
|
|
+#include <stm32_timer.h>
|
|
+#include <utils_def.h>
|
|
+
|
|
+#define TIMEOUT_10MS ms2tick(10)
|
|
+#define CALIB_TIMEOUT TIMEOUT_10MS
|
|
+
|
|
+struct stm32mp1_trim_boundary_t {
|
|
+ /* Max boundary trim value around forbidden value */
|
|
+ unsigned int x1;
|
|
+ /* Min boundary trim value around forbidden value */
|
|
+ unsigned int x2;
|
|
+};
|
|
+
|
|
+struct stm32mp1_clk_cal {
|
|
+ uint16_t *fbv;
|
|
+ unsigned int cal_ref;
|
|
+ int trim_max;
|
|
+ int trim_min;
|
|
+ unsigned int boundary_max;
|
|
+ unsigned long ref_freq;
|
|
+ unsigned int freq_margin;
|
|
+ unsigned long (*get_freq)(void);
|
|
+ void (*set_trim)(unsigned int cal);
|
|
+ unsigned int (*get_trim)(void);
|
|
+ struct stm32mp1_trim_boundary_t boundary[16];
|
|
+};
|
|
+
|
|
+/* RCC Wakeup status */
|
|
+static bool rcc_wakeup;
|
|
+
|
|
+/* List of forbiden values for HSI */
|
|
+static uint16_t fbv_hsi[] = {
|
|
+ 512,
|
|
+ 480,
|
|
+ 448,
|
|
+ 416,
|
|
+ 384,
|
|
+ 352,
|
|
+ 320,
|
|
+ 288,
|
|
+ 256,
|
|
+ 224,
|
|
+ 192,
|
|
+ 160,
|
|
+ 128,
|
|
+ 96,
|
|
+ 64,
|
|
+ 32,
|
|
+ 0
|
|
+};
|
|
+
|
|
+/* List of forbiden values for CSI */
|
|
+static uint16_t fbv_csi[] = {
|
|
+ 256,
|
|
+ 240,
|
|
+ 224,
|
|
+ 208,
|
|
+ 192,
|
|
+ 176,
|
|
+ 160,
|
|
+ 144,
|
|
+ 128,
|
|
+ 112,
|
|
+ 96,
|
|
+ 80,
|
|
+ 64,
|
|
+ 48,
|
|
+ 32,
|
|
+ 16,
|
|
+ 0
|
|
+};
|
|
+
|
|
+static void hsi_set_trim(unsigned int cal);
|
|
+static unsigned int hsi_get_trimed_cal(void);
|
|
+static void csi_set_trim(unsigned int cal);
|
|
+static unsigned int csi_get_trimed_cal(void);
|
|
+
|
|
+static struct stm32mp1_clk_cal stm32mp1_clk_cal_hsi = {
|
|
+ .fbv = fbv_hsi,
|
|
+ .trim_max = 63,
|
|
+ .trim_min = -64,
|
|
+ .ref_freq = 0,
|
|
+ .freq_margin = 5,
|
|
+ .set_trim = hsi_set_trim,
|
|
+ .get_trim = hsi_get_trimed_cal,
|
|
+};
|
|
+
|
|
+static struct stm32mp1_clk_cal stm32mp1_clk_cal_csi = {
|
|
+ .fbv = fbv_csi,
|
|
+ .trim_max = 15,
|
|
+ .trim_min = -16,
|
|
+ .ref_freq = 0,
|
|
+ .freq_margin = 8,
|
|
+ .set_trim = csi_set_trim,
|
|
+ .get_trim = csi_get_trimed_cal,
|
|
+};
|
|
+
|
|
+static uint32_t timer_val;
|
|
+
|
|
+/*
|
|
+ * HSI Calibration part
|
|
+ */
|
|
+static int get_signed_value(uint8_t val)
|
|
+{
|
|
+ return ((int8_t)(val << 1)) >> 1;
|
|
+}
|
|
+
|
|
+static void hsi_set_trim(unsigned int cal)
|
|
+{
|
|
+ int clk_trim = (int)cal - (int)stm32mp1_clk_cal_hsi.cal_ref;
|
|
+ uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) &
|
|
+ RCC_HSICFGR_HSITRIM_MASK;
|
|
+
|
|
+ mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_HSICFGR,
|
|
+ RCC_HSICFGR_HSITRIM_MASK, trim);
|
|
+}
|
|
+
|
|
+static unsigned int hsi_get_trimed_cal(void)
|
|
+{
|
|
+ uint32_t utrim = (mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) &
|
|
+ RCC_HSICFGR_HSITRIM_MASK) >>
|
|
+ RCC_HSICFGR_HSITRIM_SHIFT;
|
|
+
|
|
+ int trim = get_signed_value((uint8_t)utrim);
|
|
+
|
|
+ if (trim + (int)stm32mp1_clk_cal_hsi.cal_ref < 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return stm32mp1_clk_cal_hsi.cal_ref + trim;
|
|
+}
|
|
+
|
|
+static void csi_set_trim(unsigned int cal)
|
|
+{
|
|
+ int clk_trim = (int)cal - (int)stm32mp1_clk_cal_csi.cal_ref +
|
|
+ stm32mp1_clk_cal_csi.trim_max + 1;
|
|
+ uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) &
|
|
+ RCC_CSICFGR_CSITRIM_MASK;
|
|
+
|
|
+ mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_CSICFGR,
|
|
+ RCC_CSICFGR_CSITRIM_MASK, trim);
|
|
+}
|
|
+
|
|
+static unsigned int csi_get_trimed_cal(void)
|
|
+{
|
|
+ uint32_t trim = (mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) &
|
|
+ RCC_CSICFGR_CSITRIM_MASK) >>
|
|
+ RCC_CSICFGR_CSITRIM_SHIFT;
|
|
+
|
|
+ return (int)trim - stm32mp1_clk_cal_csi.trim_max +
|
|
+ (int)stm32mp1_clk_cal_csi.cal_ref - 1;
|
|
+}
|
|
+
|
|
+static unsigned int trim_increase(struct stm32mp1_clk_cal *clk_cal,
|
|
+ unsigned int cal)
|
|
+{
|
|
+ struct stm32mp1_trim_boundary_t *boundary;
|
|
+ unsigned int new_cal;
|
|
+ int i;
|
|
+
|
|
+ /* By default: last calibration value */
|
|
+ new_cal = cal;
|
|
+
|
|
+ /* Start from Lowest cal value */
|
|
+ for (i = (int)clk_cal->boundary_max - 1; i >= 0; i--) {
|
|
+ boundary = &clk_cal->boundary[i];
|
|
+
|
|
+ if (cal < boundary->x2) {
|
|
+ new_cal = boundary->x2;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if ((cal >= boundary->x2) && (cal < boundary->x1)) {
|
|
+ new_cal = cal + 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return new_cal;
|
|
+}
|
|
+
|
|
+static unsigned int trim_decrease(struct stm32mp1_clk_cal *clk_cal,
|
|
+ unsigned int cal)
|
|
+{
|
|
+ struct stm32mp1_trim_boundary_t *boundary;
|
|
+ unsigned int new_cal;
|
|
+ unsigned int i;
|
|
+
|
|
+ /* By default: last calibration value */
|
|
+ new_cal = cal;
|
|
+
|
|
+ /* Start from Highest cal value */
|
|
+ for (i = 0; i < clk_cal->boundary_max; i++) {
|
|
+ boundary = &clk_cal->boundary[i];
|
|
+
|
|
+ if (cal > boundary->x1) {
|
|
+ new_cal = boundary->x1;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if ((cal > boundary->x2) && (cal <= boundary->x1)) {
|
|
+ new_cal = cal - 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return new_cal;
|
|
+}
|
|
+
|
|
+static void rcc_calibration(struct stm32mp1_clk_cal *clk_cal)
|
|
+{
|
|
+ unsigned long freq = clk_cal->get_freq();
|
|
+ unsigned long min = clk_cal->ref_freq -
|
|
+ ((clk_cal->ref_freq * clk_cal->freq_margin) / 1000);
|
|
+ unsigned long max = clk_cal->ref_freq +
|
|
+ ((clk_cal->ref_freq * clk_cal->freq_margin) / 1000);
|
|
+ int trim, new_trim;
|
|
+ unsigned long conv;
|
|
+ unsigned long min_conv = ULONG_MAX;
|
|
+ uint64_t start;
|
|
+
|
|
+ if ((freq >= min) && (freq <= max)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ trim = clk_cal->get_trim();
|
|
+ start = timeout_start();
|
|
+ do {
|
|
+ if (freq < clk_cal->ref_freq) {
|
|
+ new_trim = trim_increase(clk_cal, trim);
|
|
+ } else {
|
|
+ new_trim = trim_decrease(clk_cal, trim);
|
|
+ }
|
|
+
|
|
+ clk_cal->set_trim(new_trim);
|
|
+ freq = clk_cal->get_freq();
|
|
+ if (freq == 0U) {
|
|
+ /* Calibration will be stopped */
|
|
+ clk_cal->ref_freq = 0U;
|
|
+ return;
|
|
+ }
|
|
+ conv = (clk_cal->ref_freq < freq) ?
|
|
+ freq - clk_cal->ref_freq : clk_cal->ref_freq - freq;
|
|
+ if (conv < min_conv) {
|
|
+ min_conv = conv;
|
|
+ trim = new_trim;
|
|
+ }
|
|
+
|
|
+ if (timeout_elapsed(start, CALIB_TIMEOUT)) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ } while (conv == min_conv);
|
|
+
|
|
+ clk_cal->set_trim(trim);
|
|
+ freq = clk_cal->get_freq();
|
|
+ if ((freq < min) || (freq > max)) {
|
|
+ ERROR("%s Calibration : Freq %lu, trim %i\n",
|
|
+ (clk_cal->set_trim == hsi_set_trim) ? "HSI" : "CSI",
|
|
+ freq, trim);
|
|
+#if DEBUG
|
|
+ /*
|
|
+ * Show the steps around the selected trim value
|
|
+ * to correct the margin if needed
|
|
+ */
|
|
+ new_trim = trim_decrease(clk_cal, trim);
|
|
+ clk_cal->set_trim(new_trim);
|
|
+ ERROR("%s Calibration : Freq %lu, trim %i\n",
|
|
+ (clk_cal->set_trim == hsi_set_trim) ?
|
|
+ "HSI" : "CSI", clk_cal->get_freq(),
|
|
+ new_trim);
|
|
+ new_trim = trim_increase(clk_cal, trim);
|
|
+ clk_cal->set_trim(new_trim);
|
|
+ ERROR("%s Calibration : Freq %lu, trim %i\n",
|
|
+ (clk_cal->set_trim == hsi_set_trim) ?
|
|
+ "HSI" : "CSI", clk_cal->get_freq(),
|
|
+ new_trim);
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+static void save_trim(struct stm32mp1_clk_cal *clk_cal,
|
|
+ unsigned int i, unsigned int x1, unsigned int x2)
|
|
+{
|
|
+ clk_cal->boundary[i].x1 = x1;
|
|
+ clk_cal->boundary[i].x2 = x2;
|
|
+}
|
|
+
|
|
+static int trim_find_prev_boundary(struct stm32mp1_clk_cal *clk_cal,
|
|
+ unsigned int x1)
|
|
+{
|
|
+ unsigned int x = x1;
|
|
+ unsigned long freq;
|
|
+
|
|
+ clk_cal->set_trim(x1 + 1);
|
|
+ freq = clk_cal->get_freq();
|
|
+
|
|
+ while (x >= (clk_cal->cal_ref + clk_cal->trim_min)) {
|
|
+ x--;
|
|
+ clk_cal->set_trim(x);
|
|
+
|
|
+ if (clk_cal->get_freq() <= freq) {
|
|
+ break;
|
|
+ }
|
|
+ };
|
|
+
|
|
+ return x;
|
|
+}
|
|
+
|
|
+static void trim_table_init(struct stm32mp1_clk_cal *clk_cal)
|
|
+{
|
|
+ uint16_t *trim_fbv = clk_cal->fbv;
|
|
+ unsigned int min;
|
|
+ unsigned int max;
|
|
+ int boundary = 0;
|
|
+ int i = 0;
|
|
+
|
|
+ max = clk_cal->cal_ref + clk_cal->trim_max;
|
|
+ min = clk_cal->cal_ref + clk_cal->trim_min;
|
|
+
|
|
+ while (trim_fbv[i]) {
|
|
+ unsigned int x;
|
|
+ unsigned int x1 = trim_fbv[i];
|
|
+ unsigned int x2 = trim_fbv[i + 1];
|
|
+
|
|
+ if ((max <= x2) || (min >= x1)) {
|
|
+ i++;
|
|
+ if (boundary != 0) {
|
|
+ goto out;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Take forbiden value + 1 */
|
|
+ x2 = x2 + 1;
|
|
+ if (x2 < min) {
|
|
+ x2 = min;
|
|
+ }
|
|
+
|
|
+ if (boundary == 0) {
|
|
+ /* Save first boundary */
|
|
+ save_trim(clk_cal, boundary, max, x2);
|
|
+ boundary++;
|
|
+ i++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ x = trim_find_prev_boundary(clk_cal, x1);
|
|
+ /* Save boundary values */
|
|
+ save_trim(clk_cal, boundary, x - 1, x2);
|
|
+ boundary++;
|
|
+ i++;
|
|
+ };
|
|
+out:
|
|
+ clk_cal->boundary_max = boundary;
|
|
+}
|
|
+
|
|
+bool stm32mp1_calib_get_wakeup(void)
|
|
+{
|
|
+ return rcc_wakeup;
|
|
+}
|
|
+
|
|
+void stm32mp1_calib_set_wakeup(bool state)
|
|
+{
|
|
+ rcc_wakeup = state;
|
|
+}
|
|
+
|
|
+void stm32mp1_calib_it_handler(uint32_t id)
|
|
+{
|
|
+ uintptr_t rcc_base = stm32mp_rcc_base();
|
|
+
|
|
+ switch (id) {
|
|
+ case STM32MP1_IRQ_RCC_WAKEUP:
|
|
+ plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY);
|
|
+ mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF);
|
|
+ stm32mp1_calib_set_wakeup(true);
|
|
+ return;
|
|
+
|
|
+ case STM32MP1_IRQ_MCU_SEV:
|
|
+ stm32mp1_calib_set_wakeup(false);
|
|
+ if ((mmio_read_32(EXTI_BASE + EXTI_RPR3) &
|
|
+ EXTI_RPR3_RPIF65) != 0U) {
|
|
+ mmio_setbits_32(EXTI_BASE + EXTI_RPR3,
|
|
+ EXTI_RPR3_RPIF65);
|
|
+ }
|
|
+
|
|
+ if ((mmio_read_32(EXTI_BASE + EXTI_FPR3) &
|
|
+ EXTI_FPR3_FPIF65) != 0U) {
|
|
+ mmio_setbits_32(EXTI_BASE + EXTI_FPR3,
|
|
+ EXTI_FPR3_FPIF65);
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case ARM_IRQ_SEC_PHY_TIMER:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (stm32mp1_clk_cal_hsi.ref_freq != 0U) {
|
|
+ rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
+ }
|
|
+
|
|
+ if (stm32mp1_clk_cal_csi.ref_freq != 0U) {
|
|
+ rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
+ }
|
|
+
|
|
+ if (timer_val != 0U) {
|
|
+ write_cntp_tval(timer_val);
|
|
+ }
|
|
+}
|
|
+
|
|
+int stm32mp1_calib_start_hsi_cal(void)
|
|
+{
|
|
+ if (stm32mp1_clk_cal_hsi.ref_freq == 0U) {
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int stm32mp1_calib_start_csi_cal(void)
|
|
+{
|
|
+ if (stm32mp1_clk_cal_csi.ref_freq == 0U) {
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void init_hsi_cal(void)
|
|
+{
|
|
+ int len;
|
|
+
|
|
+ if (fdt_rcc_read_prop("st,hsi-cal", &len) == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ stm32_timer_freq_func(&stm32mp1_clk_cal_hsi.get_freq, HSI_CAL);
|
|
+ if (stm32mp1_clk_cal_hsi.get_freq == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ stm32mp1_clk_cal_hsi.ref_freq = stm32mp_clk_get_rate(CK_HSI);
|
|
+
|
|
+ /* Read initial value */
|
|
+ stm32mp1_clk_cal_hsi.cal_ref =
|
|
+ ((mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR)
|
|
+ & RCC_HSICFGR_HSICAL_MASK) >> RCC_HSICFGR_HSICAL_SHIFT);
|
|
+
|
|
+ trim_table_init(&stm32mp1_clk_cal_hsi);
|
|
+
|
|
+ stm32mp1_clk_cal_hsi.set_trim(stm32mp1_clk_cal_hsi.cal_ref);
|
|
+
|
|
+ rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
+}
|
|
+
|
|
+static void init_csi_cal(void)
|
|
+{
|
|
+ int len;
|
|
+
|
|
+ if (fdt_rcc_read_prop("st,csi-cal", &len) == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ stm32_timer_freq_func(&stm32mp1_clk_cal_csi.get_freq, CSI_CAL);
|
|
+ if (stm32mp1_clk_cal_csi.get_freq == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ stm32mp1_clk_cal_csi.ref_freq = stm32mp_clk_get_rate(CK_CSI);
|
|
+
|
|
+ /* Read initial value */
|
|
+ stm32mp1_clk_cal_csi.cal_ref =
|
|
+ ((mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) &
|
|
+ RCC_CSICFGR_CSICAL_MASK) >> RCC_CSICFGR_CSICAL_SHIFT);
|
|
+
|
|
+ trim_table_init(&stm32mp1_clk_cal_csi);
|
|
+
|
|
+ stm32mp1_clk_cal_csi.set_trim(stm32mp1_clk_cal_csi.cal_ref);
|
|
+
|
|
+ rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
+}
|
|
+
|
|
+void stm32mp1_calib_init(void)
|
|
+{
|
|
+ init_hsi_cal();
|
|
+ init_csi_cal();
|
|
+
|
|
+ timer_val = fdt_rcc_read_uint32_default("st,cal-sec", 0) *
|
|
+ plat_get_syscnt_freq2();
|
|
+
|
|
+ if (timer_val != 0U) {
|
|
+ /* Load & enable timer */
|
|
+ write_cntp_tval(timer_val);
|
|
+ write_cntp_ctl(BIT(0));
|
|
+ };
|
|
+
|
|
+ if (fdt_rcc_enable_it("mcu_sev") < 0) {
|
|
+ VERBOSE("No MCU calibration\n");
|
|
+ }
|
|
+}
|
|
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
|
|
index b304315..286234e 100644
|
|
--- a/drivers/st/clk/stm32mp1_clk.c
|
|
+++ b/drivers/st/clk/stm32mp1_clk.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
*/
|
|
@@ -13,6 +13,7 @@
|
|
#include <errno.h>
|
|
#include <generic_delay_timer.h>
|
|
#include <libfdt.h>
|
|
+#include <limits.h>
|
|
#include <mmio.h>
|
|
#include <platform.h>
|
|
#include <spinlock.h>
|
|
@@ -27,9 +28,6 @@
|
|
#include <stm32mp1_private.h>
|
|
#include <stm32mp1_rcc.h>
|
|
#include <stm32mp1_shared_resources.h>
|
|
-#if defined(IMAGE_BL32)
|
|
-#include <stm32_timer.h>
|
|
-#endif
|
|
#include <utils_def.h>
|
|
|
|
#define MAX_HSI_HZ 64000000
|
|
@@ -44,10 +42,6 @@
|
|
#define HSIDIV_TIMEOUT TIMEOUT_200MS
|
|
#define OSCRDY_TIMEOUT TIMEOUT_1S
|
|
|
|
-#if defined(IMAGE_BL32)
|
|
-#define CAL_MAX_RETRY 20U
|
|
-#endif
|
|
-
|
|
enum stm32mp1_parent_id {
|
|
/* Oscillators are defined in enum stm32mp_osc_id */
|
|
|
|
@@ -91,7 +85,7 @@ enum stm32mp1_parent_sel {
|
|
_STGEN_SEL,
|
|
_I2C46_SEL,
|
|
_SPI6_SEL,
|
|
- _USART1_SEL,
|
|
+ _UART1_SEL,
|
|
_RNG1_SEL,
|
|
_UART6_SEL,
|
|
_UART24_SEL,
|
|
@@ -101,8 +95,8 @@ enum stm32mp1_parent_sel {
|
|
_SDMMC3_SEL,
|
|
_QSPI_SEL,
|
|
_FMC_SEL,
|
|
- _ASS_SEL,
|
|
- _MSS_SEL,
|
|
+ _AXIS_SEL,
|
|
+ _MCUS_SEL,
|
|
_USBPHY_SEL,
|
|
_USBO_SEL,
|
|
_PARENT_SEL_NB,
|
|
@@ -210,32 +204,6 @@ struct stm32mp1_clk_pll {
|
|
enum stm32mp_osc_id refclk[REFCLK_SIZE];
|
|
};
|
|
|
|
-#if defined(IMAGE_BL32)
|
|
-struct stm32mp1_trim_boundary_t {
|
|
- /* Max boundary trim value around forbidden value */
|
|
- unsigned int x1;
|
|
- /* Min boundary trim value around forbidden value */
|
|
- unsigned int x2;
|
|
-};
|
|
-
|
|
-struct stm32mp1_clk_cal {
|
|
- uint16_t *fbv;
|
|
- unsigned int cal_ref;
|
|
- int trim_max;
|
|
- int trim_min;
|
|
- unsigned int boundary_max;
|
|
- unsigned long ref_freq;
|
|
- unsigned int freq_margin;
|
|
- unsigned long (*get_freq)(void);
|
|
- void (*set_trim)(unsigned int cal);
|
|
- unsigned int (*get_trim)(void);
|
|
- struct stm32mp1_trim_boundary_t boundary[16];
|
|
-};
|
|
-
|
|
-/* RCC Wakeup status */
|
|
-static bool rcc_wakeup;
|
|
-#endif
|
|
-
|
|
/* Clocks with selectable source and non set/clr register access */
|
|
#define _CLK_SELEC(off, b, idx, s) \
|
|
{ \
|
|
@@ -280,13 +248,13 @@ static bool rcc_wakeup;
|
|
.fixed = (f), \
|
|
}
|
|
|
|
-#define _CLK_PARENT(idx, off, s, m, p) \
|
|
- [(idx)] = { \
|
|
- .offset = (off), \
|
|
- .src = (s), \
|
|
- .msk = (m), \
|
|
- .parent = (p), \
|
|
- .nb_parent = ARRAY_SIZE(p) \
|
|
+#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \
|
|
+ [_ ## _label ## _SEL] = { \
|
|
+ .offset = _rcc_selr, \
|
|
+ .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \
|
|
+ .msk = _rcc_selr ## _ ## _label ## SRC_MASK, \
|
|
+ .parent = (_parents), \
|
|
+ .nb_parent = ARRAY_SIZE(_parents) \
|
|
}
|
|
|
|
#define _CLK_PLL(idx, type, off1, off2, off3, \
|
|
@@ -347,6 +315,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
|
_CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
|
|
_CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
|
|
|
|
+ _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
|
|
+
|
|
+ _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 0, LTDC_PX, _UNKNOWN_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
|
|
@@ -354,7 +325,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
|
_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
|
|
- _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _USART1_SEL),
|
|
+ _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
|
|
_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
|
|
_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
|
|
_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
|
|
@@ -363,6 +334,8 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
|
_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
|
|
_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
|
|
|
|
+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 0, DMA1, _UNKNOWN_SEL),
|
|
+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 1, DMA2, _UNKNOWN_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
|
|
|
|
@@ -384,6 +357,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
|
_CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
|
|
_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
|
|
|
|
+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 0, MDMA, _UNKNOWN_SEL),
|
|
+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 5, GPU, _UNKNOWN_SEL),
|
|
+ _CLK_SC_FIXED(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK),
|
|
_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
|
|
_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
|
|
@@ -462,25 +438,25 @@ static const uint8_t usbo_parents[] = {
|
|
};
|
|
|
|
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
|
- _CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
|
|
- _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents),
|
|
- _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
|
|
- _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents),
|
|
- _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents),
|
|
- _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents),
|
|
- _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents),
|
|
- _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents),
|
|
- _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents),
|
|
- _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents),
|
|
- _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents),
|
|
- _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents),
|
|
- _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents),
|
|
- _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents),
|
|
- _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents),
|
|
- _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents),
|
|
- _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents),
|
|
- _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents),
|
|
- _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents),
|
|
+ _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
|
|
+ _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
|
|
+ _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
|
|
+ _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
|
|
+ _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
|
|
+ _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
|
|
+ _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
|
|
+ _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
|
|
+ _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
|
|
+ _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
|
|
+ _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
|
|
+ _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
|
|
+ _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
|
|
+ _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
|
|
+ _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
|
|
+ _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents),
|
|
+ _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents),
|
|
+ _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
|
|
+ _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
|
|
};
|
|
|
|
/* Define characteristic of PLL according type */
|
|
@@ -587,7 +563,7 @@ const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = {
|
|
[_STGEN_SEL] = "STGEN",
|
|
[_I2C46_SEL] = "I2C46",
|
|
[_SPI6_SEL] = "SPI6",
|
|
- [_USART1_SEL] = "USART1",
|
|
+ [_UART1_SEL] = "USART1",
|
|
[_RNG1_SEL] = "RNG1",
|
|
[_UART6_SEL] = "UART6",
|
|
[_UART24_SEL] = "UART24",
|
|
@@ -597,8 +573,8 @@ const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = {
|
|
[_SDMMC3_SEL] = "SDMMC3",
|
|
[_QSPI_SEL] = "QSPI",
|
|
[_FMC_SEL] = "FMC",
|
|
- [_ASS_SEL] = "ASS",
|
|
- [_MSS_SEL] = "MSS",
|
|
+ [_AXIS_SEL] = "ASS",
|
|
+ [_MCUS_SEL] = "MSS",
|
|
[_USBPHY_SEL] = "USBPHY",
|
|
[_USBO_SEL] = "USBO",
|
|
};
|
|
@@ -625,41 +601,6 @@ static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
|
|
return &stm32mp1_clk_pll[idx];
|
|
}
|
|
|
|
-#if defined(IMAGE_BL32)
|
|
-/* List of forbiden values for hsi */
|
|
-static uint16_t fbv_hsi[] = { 512, 480, 448, 416, 384, 352, 320, 288, 256, 224,
|
|
- 192, 160, 128, 96, 64, 32, 0 };
|
|
-static uint16_t fbv_csi[] = { 256, 240, 224, 208, 192, 176, 160, 144, 128, 112,
|
|
- 96, 80, 64, 48, 32, 16, 0 };
|
|
-
|
|
-static void hsi_set_trim(unsigned int cal);
|
|
-static unsigned int hsi_get_trimed_cal(void);
|
|
-static void csi_set_trim(unsigned int cal);
|
|
-static unsigned int csi_get_trimed_cal(void);
|
|
-
|
|
-static struct stm32mp1_clk_cal stm32mp1_clk_cal_hsi = {
|
|
- .fbv = fbv_hsi,
|
|
- .trim_max = 63,
|
|
- .trim_min = -64,
|
|
- .ref_freq = 0,
|
|
- .freq_margin = 1,
|
|
- .set_trim = hsi_set_trim,
|
|
- .get_trim = hsi_get_trimed_cal,
|
|
-};
|
|
-
|
|
-static struct stm32mp1_clk_cal stm32mp1_clk_cal_csi = {
|
|
- .fbv = fbv_csi,
|
|
- .trim_max = 15,
|
|
- .trim_min = -16,
|
|
- .ref_freq = 0,
|
|
- .freq_margin = 2,
|
|
- .set_trim = csi_set_trim,
|
|
- .get_trim = csi_get_trimed_cal,
|
|
-};
|
|
-
|
|
-static uint32_t timer_val;
|
|
-#endif
|
|
-
|
|
static int stm32mp1_lock_available(void)
|
|
{
|
|
/* The spinlocks are used only when MMU is enabled */
|
|
@@ -799,7 +740,7 @@ static int stm32mp1_clk_get_parent(unsigned long id)
|
|
}
|
|
|
|
sel = clk_sel_ref(s);
|
|
- p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk;
|
|
+ p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src;
|
|
if (p_sel < sel->nb_parent) {
|
|
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
|
|
VERBOSE("%s: %s clock is the parent %s of clk id %ld\n",
|
|
@@ -1315,6 +1256,13 @@ static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
|
|
if (css) {
|
|
mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
|
|
}
|
|
+
|
|
+#if defined(STM32MP_USB) || defined(STM32MP_UART)
|
|
+ if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) &&
|
|
+ (!(digbyp || bypass))) {
|
|
+ panic();
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
static void stm32mp1_csi_set(bool enable)
|
|
@@ -1460,7 +1408,10 @@ static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
|
|
const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
|
|
uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
|
|
|
|
- mmio_write_32(pllxcr, RCC_PLLNCR_PLLON);
|
|
+ mmio_clrsetbits_32(pllxcr,
|
|
+ RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
|
|
+ RCC_PLLNCR_DIVREN,
|
|
+ RCC_PLLNCR_PLLON);
|
|
}
|
|
|
|
static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
|
|
@@ -1590,6 +1541,9 @@ static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
|
|
RCC_PLLNCSGR_SSCG_MODE_MASK;
|
|
|
|
mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
|
|
+
|
|
+ mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
|
|
+ RCC_PLLNCR_SSCG_CTRL);
|
|
}
|
|
|
|
static int stm32mp1_set_clksrc(unsigned int clksrc)
|
|
@@ -1799,6 +1753,32 @@ static void stm32mp1_pkcs_config(uint32_t pkcs)
|
|
mmio_clrsetbits_32(address, mask, value);
|
|
}
|
|
|
|
+#if defined(IMAGE_BL32)
|
|
+void stm32mp1_clk_mpu_suspend(void)
|
|
+{
|
|
+ uintptr_t mpckselr = stm32mp_rcc_base() + RCC_MPCKSELR;
|
|
+
|
|
+ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) ==
|
|
+ RCC_MPCKSELR_PLL) {
|
|
+ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P_DIV) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void stm32mp1_clk_mpu_resume(void)
|
|
+{
|
|
+ uintptr_t mpckselr = stm32mp_rcc_base() + RCC_MPCKSELR;
|
|
+
|
|
+ if (((mmio_read_32(mpckselr) & RCC_SELR_SRC_MASK)) ==
|
|
+ RCC_MPCKSELR_PLL_MPUDIV) {
|
|
+ if (stm32mp1_set_clksrc(CLK_MPU_PLL1P) != 0) {
|
|
+ panic();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
int stm32mp1_clk_init(void)
|
|
{
|
|
uint32_t rcc_base = stm32mp_rcc_base();
|
|
@@ -2138,365 +2118,6 @@ static void stm32mp1_osc_clk_init(const char *name,
|
|
}
|
|
}
|
|
|
|
-#if defined(IMAGE_BL32)
|
|
-/*
|
|
- * HSI Calibration part
|
|
- */
|
|
-static void hsi_set_trim(unsigned int cal)
|
|
-{
|
|
- int clk_trim = (int)cal - (int)stm32mp1_clk_cal_hsi.cal_ref;
|
|
- uint32_t trim = ((uint32_t)clk_trim << RCC_HSICFGR_HSITRIM_SHIFT) &
|
|
- RCC_HSICFGR_HSITRIM_MASK;
|
|
-
|
|
- mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_HSICFGR,
|
|
- RCC_HSICFGR_HSITRIM_MASK, trim);
|
|
-}
|
|
-
|
|
-static unsigned int hsi_get_trimed_cal(void)
|
|
-{
|
|
- uint32_t utrim = (mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR) &
|
|
- RCC_HSICFGR_HSITRIM_MASK) >>
|
|
- RCC_HSICFGR_HSITRIM_SHIFT;
|
|
- int trim = (int)utrim - stm32mp1_clk_cal_hsi.trim_max;
|
|
-
|
|
- if (trim + (int)stm32mp1_clk_cal_hsi.cal_ref < 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- return stm32mp1_clk_cal_hsi.cal_ref + trim;
|
|
-}
|
|
-
|
|
-static void csi_set_trim(unsigned int cal)
|
|
-{
|
|
- int clk_trim = (int)cal - (int)stm32mp1_clk_cal_csi.cal_ref +
|
|
- stm32mp1_clk_cal_csi.trim_max + 1;
|
|
- uint32_t trim = ((uint32_t)clk_trim << RCC_CSICFGR_CSITRIM_SHIFT) &
|
|
- RCC_CSICFGR_CSITRIM_MASK;
|
|
-
|
|
- mmio_clrsetbits_32(stm32mp_rcc_base() + RCC_CSICFGR,
|
|
- RCC_CSICFGR_CSITRIM_MASK, trim);
|
|
-}
|
|
-
|
|
-static unsigned int csi_get_trimed_cal(void)
|
|
-{
|
|
- uint32_t trim = (mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) &
|
|
- RCC_CSICFGR_CSITRIM_MASK) >>
|
|
- RCC_CSICFGR_CSITRIM_SHIFT;
|
|
-
|
|
- return (int)trim - stm32mp1_clk_cal_csi.trim_max +
|
|
- (int)stm32mp1_clk_cal_csi.cal_ref - 1;
|
|
-}
|
|
-
|
|
-static unsigned int trim_increase(struct stm32mp1_clk_cal *clk_cal,
|
|
- unsigned int cal)
|
|
-{
|
|
- struct stm32mp1_trim_boundary_t *boundary;
|
|
- unsigned int new_cal;
|
|
- int i;
|
|
-
|
|
- /* By default: last calibration value */
|
|
- new_cal = cal;
|
|
-
|
|
- /* Start from Lowest cal value */
|
|
- for (i = (int)clk_cal->boundary_max - 1; i >= 0; i--) {
|
|
- boundary = &clk_cal->boundary[i];
|
|
-
|
|
- if (cal < boundary->x2) {
|
|
- new_cal = boundary->x2;
|
|
- break;
|
|
- }
|
|
-
|
|
- if ((cal >= boundary->x2) && (cal < boundary->x1)) {
|
|
- new_cal = cal + 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- return new_cal;
|
|
-}
|
|
-
|
|
-static unsigned int trim_decrease(struct stm32mp1_clk_cal *clk_cal,
|
|
- unsigned int cal)
|
|
-{
|
|
- struct stm32mp1_trim_boundary_t *boundary;
|
|
- unsigned int new_cal;
|
|
- unsigned int i;
|
|
-
|
|
- /* By default: last calibration value */
|
|
- new_cal = cal;
|
|
-
|
|
- /* Start from Highest cal value */
|
|
- for (i = 0; i < clk_cal->boundary_max; i++) {
|
|
- boundary = &clk_cal->boundary[i];
|
|
-
|
|
- if (cal > boundary->x1) {
|
|
- new_cal = boundary->x1;
|
|
- break;
|
|
- }
|
|
-
|
|
- if ((cal > boundary->x2) && (cal <= boundary->x1)) {
|
|
- new_cal = cal - 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- return new_cal;
|
|
-}
|
|
-
|
|
-static void stm32mp1_rcc_calibration(struct stm32mp1_clk_cal *clk_cal)
|
|
-{
|
|
- unsigned long freq = clk_cal->get_freq();
|
|
- unsigned long min = clk_cal->ref_freq -
|
|
- ((clk_cal->ref_freq * clk_cal->freq_margin) / 100);
|
|
- unsigned long max = clk_cal->ref_freq +
|
|
- ((clk_cal->ref_freq * clk_cal->freq_margin) / 100);
|
|
- unsigned int nb_retries = CAL_MAX_RETRY;
|
|
- int cal = clk_cal->get_trim();
|
|
-
|
|
- VERBOSE("Freq is %lu min %lu max %lu\n", freq, min, max);
|
|
-
|
|
- while (((freq < min) || (freq > max)) && (nb_retries != 0U)) {
|
|
-
|
|
- if (freq < min) {
|
|
- cal = trim_increase(clk_cal, cal);
|
|
- } else {
|
|
- cal = trim_decrease(clk_cal, cal);
|
|
- }
|
|
-
|
|
- clk_cal->set_trim(cal);
|
|
-
|
|
- freq = clk_cal->get_freq();
|
|
-
|
|
- nb_retries--;
|
|
- }
|
|
-
|
|
- if (nb_retries == 0U) {
|
|
- ERROR("Calibration Failed\n");
|
|
- panic();
|
|
- }
|
|
-}
|
|
-
|
|
-static void save_trim(struct stm32mp1_clk_cal *clk_cal,
|
|
- unsigned int i, unsigned int x1, unsigned int x2)
|
|
-{
|
|
- clk_cal->boundary[i].x1 = x1;
|
|
- clk_cal->boundary[i].x2 = x2;
|
|
-}
|
|
-
|
|
-static int trim_find_prev_boundary(struct stm32mp1_clk_cal *clk_cal,
|
|
- unsigned int x1)
|
|
-{
|
|
- unsigned int x = x1;
|
|
- unsigned long freq;
|
|
-
|
|
- clk_cal->set_trim(x1 + 1);
|
|
- freq = clk_cal->get_freq();
|
|
-
|
|
- while (x >= (clk_cal->cal_ref + clk_cal->trim_min)) {
|
|
- x--;
|
|
- clk_cal->set_trim(x);
|
|
-
|
|
- if (clk_cal->get_freq() <= freq) {
|
|
- break;
|
|
- }
|
|
- };
|
|
-
|
|
- return x;
|
|
-}
|
|
-
|
|
-static void trim_table_init(struct stm32mp1_clk_cal *clk_cal)
|
|
-{
|
|
- uint16_t *trim_fbv = clk_cal->fbv;
|
|
- unsigned int min;
|
|
- unsigned int max;
|
|
- int boundary = 0;
|
|
- int i = 0;
|
|
-
|
|
- max = clk_cal->cal_ref + clk_cal->trim_max;
|
|
- min = clk_cal->cal_ref + clk_cal->trim_min;
|
|
-
|
|
- while (trim_fbv[i]) {
|
|
- unsigned int x;
|
|
- unsigned int x1 = trim_fbv[i];
|
|
- unsigned int x2 = trim_fbv[i + 1];
|
|
-
|
|
- if ((max <= x2) || (min >= x1)) {
|
|
- i++;
|
|
- if (boundary != 0) {
|
|
- goto out;
|
|
- }
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Take forbiden value + 1 */
|
|
- x2 = x2 + 1;
|
|
- if (x2 < min) {
|
|
- x2 = min;
|
|
- }
|
|
-
|
|
- if (boundary == 0) {
|
|
- /* Save first boundary */
|
|
- save_trim(clk_cal, boundary, max, x2);
|
|
- boundary++;
|
|
- i++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- x = trim_find_prev_boundary(clk_cal, x1);
|
|
- /* Save boundary values */
|
|
- save_trim(clk_cal, boundary, x - 1, x2);
|
|
- boundary++;
|
|
- i++;
|
|
- };
|
|
-out:
|
|
- clk_cal->boundary_max = boundary;
|
|
-}
|
|
-
|
|
-bool stm32mp1_rcc_get_wakeup(void)
|
|
-{
|
|
- return rcc_wakeup;
|
|
-}
|
|
-
|
|
-void stm32mp1_rcc_set_wakeup(bool state)
|
|
-{
|
|
- rcc_wakeup = state;
|
|
-}
|
|
-
|
|
-void stm32mp1_rcc_it_handler(uint32_t id)
|
|
-{
|
|
- uintptr_t rcc_base = stm32mp_rcc_base();
|
|
-
|
|
- switch (id) {
|
|
- case STM32MP1_IRQ_RCC_WAKEUP:
|
|
- plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY);
|
|
- mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF);
|
|
- stm32mp1_rcc_set_wakeup(true);
|
|
- return;
|
|
-
|
|
- case STM32MP1_IRQ_MCU_SEV:
|
|
- stm32mp1_rcc_set_wakeup(false);
|
|
- if ((mmio_read_32(EXTI_BASE + EXTI_RPR3) &
|
|
- EXTI_RPR3_RPIF65) != 0U) {
|
|
- mmio_setbits_32(EXTI_BASE + EXTI_RPR3,
|
|
- EXTI_RPR3_RPIF65);
|
|
- }
|
|
-
|
|
- if ((mmio_read_32(EXTI_BASE + EXTI_FPR3) &
|
|
- EXTI_FPR3_FPIF65) != 0U) {
|
|
- mmio_setbits_32(EXTI_BASE + EXTI_FPR3,
|
|
- EXTI_FPR3_FPIF65);
|
|
- }
|
|
-
|
|
- break;
|
|
-
|
|
- case ARM_IRQ_SEC_PHY_TIMER:
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- if (stm32mp1_clk_cal_hsi.ref_freq != 0U) {
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
- }
|
|
-
|
|
- if (stm32mp1_clk_cal_csi.ref_freq != 0U) {
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
- }
|
|
-
|
|
- if (timer_val != 0U) {
|
|
- write_cntptval(timer_val);
|
|
- }
|
|
-}
|
|
-
|
|
-int stm32mp1_rcc_start_hsi_cal(void)
|
|
-{
|
|
- if (stm32mp1_clk_cal_hsi.ref_freq == 0U) {
|
|
- return -ENOENT;
|
|
- }
|
|
-
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int stm32mp1_rcc_start_csi_cal(void)
|
|
-{
|
|
- if (stm32mp1_clk_cal_csi.ref_freq == 0U) {
|
|
- return -ENOENT;
|
|
- }
|
|
-
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void init_hsi_cal(void)
|
|
-{
|
|
- int len;
|
|
-
|
|
- if (fdt_rcc_read_prop("st,hsi-cal", &len) == NULL) {
|
|
- return;
|
|
- }
|
|
-
|
|
- stm32_timer_freq_func(&stm32mp1_clk_cal_hsi.get_freq, HSI_CAL);
|
|
- assert(stm32mp1_clk_cal_hsi.get_freq);
|
|
-
|
|
- stm32mp1_clk_cal_hsi.ref_freq = stm32mp_clk_get_rate(CK_HSI);
|
|
-
|
|
- /* Read initial value */
|
|
- stm32mp1_clk_cal_hsi.cal_ref =
|
|
- ((mmio_read_32(stm32mp_rcc_base() + RCC_HSICFGR)
|
|
- & RCC_HSICFGR_HSICAL_MASK) >> RCC_HSICFGR_HSICAL_SHIFT);
|
|
-
|
|
- trim_table_init(&stm32mp1_clk_cal_hsi);
|
|
-
|
|
- stm32mp1_clk_cal_hsi.set_trim(stm32mp1_clk_cal_hsi.cal_ref);
|
|
-
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_hsi);
|
|
-}
|
|
-
|
|
-static void init_csi_cal(void)
|
|
-{
|
|
- int len;
|
|
-
|
|
- if (fdt_rcc_read_prop("st,csi-cal", &len) == NULL) {
|
|
- return;
|
|
- }
|
|
-
|
|
- stm32_timer_freq_func(&stm32mp1_clk_cal_csi.get_freq, CSI_CAL);
|
|
- assert(stm32mp1_clk_cal_csi.get_freq);
|
|
-
|
|
- stm32mp1_clk_cal_csi.ref_freq = stm32mp_clk_get_rate(CK_CSI);
|
|
-
|
|
- /* Read initial value */
|
|
- stm32mp1_clk_cal_csi.cal_ref =
|
|
- ((mmio_read_32(stm32mp_rcc_base() + RCC_CSICFGR) &
|
|
- RCC_CSICFGR_CSICAL_MASK) >> RCC_CSICFGR_CSICAL_SHIFT);
|
|
-
|
|
- trim_table_init(&stm32mp1_clk_cal_csi);
|
|
-
|
|
- stm32mp1_clk_cal_csi.set_trim(stm32mp1_clk_cal_csi.cal_ref);
|
|
-
|
|
- stm32mp1_rcc_calibration(&stm32mp1_clk_cal_csi);
|
|
-}
|
|
-
|
|
-void stm32mp1_cal_init(void)
|
|
-{
|
|
- init_hsi_cal();
|
|
- init_csi_cal();
|
|
-
|
|
- timer_val = fdt_rcc_read_uint32_default("st,cal-sec", 0) *
|
|
- plat_get_syscnt_freq2();
|
|
-
|
|
- if (timer_val != 0U) {
|
|
- /* Load & enable timer */
|
|
- write_cntptval(timer_val);
|
|
- write_cntpctl(BIT(0));
|
|
- };
|
|
-
|
|
- if (fdt_rcc_enable_it("mcu_sev") < 0) {
|
|
- VERBOSE("No MCU calibration\n");
|
|
- }
|
|
-}
|
|
-#endif
|
|
-
|
|
static void stm32mp1_osc_init(void)
|
|
{
|
|
enum stm32mp_osc_id i;
|
|
@@ -2529,7 +2150,7 @@ static int get_parent_id_parent(unsigned int parent_id)
|
|
case _ACLK:
|
|
case _PCLK4:
|
|
case _PCLK5:
|
|
- s = _ASS_SEL;
|
|
+ s = _AXIS_SEL;
|
|
break;
|
|
case _PLL1_P:
|
|
case _PLL1_Q:
|
|
@@ -2743,7 +2364,6 @@ void stm32mp1_update_earlyboot_clocks_state(void)
|
|
static void sync_earlyboot_clocks_state(void)
|
|
{
|
|
unsigned int idx;
|
|
- int res;
|
|
|
|
for (idx = 0U; idx < NB_GATES; idx++) {
|
|
assert(gate_refcounts[idx] == 0);
|
|
@@ -2800,33 +2420,7 @@ static void sync_earlyboot_clocks_state(void)
|
|
stm32mp1_register_clock_parents_secure(BKPSRAM);
|
|
|
|
stm32mp1_register_clock_parents_secure(RTCAPB);
|
|
-
|
|
- res = stm32mp_is_single_core();
|
|
- if (res < 0) {
|
|
- panic();
|
|
- }
|
|
-
|
|
- if (res == 0) {
|
|
- stm32mp1_clk_enable_secure(RTCAPB);
|
|
- }
|
|
-}
|
|
-
|
|
-void stm32mp1_rcc_init_late(void)
|
|
-{
|
|
-#if defined(IMAGE_BL32)
|
|
- int irq_num;
|
|
-
|
|
- if (!stm32mp1_rcc_is_secure()) {
|
|
- return;
|
|
- }
|
|
-
|
|
- irq_num = fdt_rcc_enable_it("wakeup");
|
|
- if (irq_num < 0) {
|
|
- panic();
|
|
- }
|
|
-
|
|
- plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO);
|
|
-#endif
|
|
+ stm32mp1_clk_enable_secure(RTCAPB);
|
|
}
|
|
|
|
int stm32mp1_clk_probe(void)
|
|
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
|
|
index ae5668a..00ebb22 100644
|
|
--- a/drivers/st/ddr/stm32mp1_ddr.c
|
|
+++ b/drivers/st/ddr/stm32mp1_ddr.c
|
|
@@ -42,8 +42,22 @@ struct reg_desc {
|
|
.par_offset = offsetof(struct y, x) \
|
|
}
|
|
|
|
+/*
|
|
+ * PARAMETERS: value get from device tree :
|
|
+ * size / order need to be aligned with binding
|
|
+ * modification NOT ALLOWED !!!
|
|
+ */
|
|
+#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */
|
|
+#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */
|
|
+#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */
|
|
+#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */
|
|
+
|
|
+#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */
|
|
+#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */
|
|
+#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */
|
|
+
|
|
#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
|
|
-static const struct reg_desc ddr_reg[] = {
|
|
+static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = {
|
|
DDRCTL_REG_REG(mstr),
|
|
DDRCTL_REG_REG(mrctrl0),
|
|
DDRCTL_REG_REG(mrctrl1),
|
|
@@ -72,7 +86,7 @@ static const struct reg_desc ddr_reg[] = {
|
|
};
|
|
|
|
#define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing)
|
|
-static const struct reg_desc ddr_timing[] = {
|
|
+static const struct reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = {
|
|
DDRCTL_REG_TIMING(rfshtmg),
|
|
DDRCTL_REG_TIMING(dramtmg0),
|
|
DDRCTL_REG_TIMING(dramtmg1),
|
|
@@ -88,7 +102,7 @@ static const struct reg_desc ddr_timing[] = {
|
|
};
|
|
|
|
#define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map)
|
|
-static const struct reg_desc ddr_map[] = {
|
|
+static const struct reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = {
|
|
DDRCTL_REG_MAP(addrmap1),
|
|
DDRCTL_REG_MAP(addrmap2),
|
|
DDRCTL_REG_MAP(addrmap3),
|
|
@@ -101,7 +115,7 @@ static const struct reg_desc ddr_map[] = {
|
|
};
|
|
|
|
#define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf)
|
|
-static const struct reg_desc ddr_perf[] = {
|
|
+static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = {
|
|
DDRCTL_REG_PERF(sched),
|
|
DDRCTL_REG_PERF(sched1),
|
|
DDRCTL_REG_PERF(perfhpr1),
|
|
@@ -122,7 +136,7 @@ static const struct reg_desc ddr_perf[] = {
|
|
};
|
|
|
|
#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg)
|
|
-static const struct reg_desc ddrphy_reg[] = {
|
|
+static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {
|
|
DDRPHY_REG_REG(pgcr),
|
|
DDRPHY_REG_REG(aciocr),
|
|
DDRPHY_REG_REG(dxccr),
|
|
@@ -137,7 +151,7 @@ static const struct reg_desc ddrphy_reg[] = {
|
|
};
|
|
|
|
#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing)
|
|
-static const struct reg_desc ddrphy_timing[] = {
|
|
+static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = {
|
|
DDRPHY_REG_TIMING(ptr0),
|
|
DDRPHY_REG_TIMING(ptr1),
|
|
DDRPHY_REG_TIMING(ptr2),
|
|
@@ -151,7 +165,7 @@ static const struct reg_desc ddrphy_timing[] = {
|
|
};
|
|
|
|
#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal)
|
|
-static const struct reg_desc ddrphy_cal[] = {
|
|
+static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = {
|
|
DDRPHY_REG_CAL(dx0dllcr),
|
|
DDRPHY_REG_CAL(dx0dqtr),
|
|
DDRPHY_REG_CAL(dx0dqstr),
|
|
@@ -166,36 +180,9 @@ static const struct reg_desc ddrphy_cal[] = {
|
|
DDRPHY_REG_CAL(dx3dqstr),
|
|
};
|
|
|
|
-#define DDR_REG_DYN(x) \
|
|
- { \
|
|
- .name = #x, \
|
|
- .offset = offsetof(struct stm32mp1_ddrctl, x), \
|
|
- .par_offset = INVALID_OFFSET \
|
|
- }
|
|
-
|
|
-static const struct reg_desc ddr_dyn[] = {
|
|
- DDR_REG_DYN(stat),
|
|
- DDR_REG_DYN(init0),
|
|
- DDR_REG_DYN(dfimisc),
|
|
- DDR_REG_DYN(dfistat),
|
|
- DDR_REG_DYN(swctl),
|
|
- DDR_REG_DYN(swstat),
|
|
- DDR_REG_DYN(pctrl_0),
|
|
- DDR_REG_DYN(pctrl_1),
|
|
-};
|
|
-
|
|
-#define DDRPHY_REG_DYN(x) \
|
|
- { \
|
|
- .name = #x, \
|
|
- .offset = offsetof(struct stm32mp1_ddrphy, x), \
|
|
- .par_offset = INVALID_OFFSET \
|
|
- }
|
|
-
|
|
-static const struct reg_desc ddrphy_dyn[] = {
|
|
- DDRPHY_REG_DYN(pir),
|
|
- DDRPHY_REG_DYN(pgsr),
|
|
-};
|
|
-
|
|
+/*
|
|
+ * REGISTERS ARRAY: used to parse device tree and interactive mode
|
|
+ */
|
|
enum reg_type {
|
|
REG_REG,
|
|
REG_TIMING,
|
|
@@ -204,12 +191,6 @@ enum reg_type {
|
|
REGPHY_REG,
|
|
REGPHY_TIMING,
|
|
REGPHY_CAL,
|
|
-/*
|
|
- * Dynamic registers => managed in driver or not changed,
|
|
- * can be dumped in interactive mode.
|
|
- */
|
|
- REG_DYN,
|
|
- REGPHY_DYN,
|
|
REG_TYPE_NB
|
|
};
|
|
|
|
@@ -230,55 +211,43 @@ static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
|
|
[REG_REG] = {
|
|
.name = "static",
|
|
.desc = ddr_reg,
|
|
- .size = ARRAY_SIZE(ddr_reg),
|
|
+ .size = DDRCTL_REG_REG_SIZE,
|
|
.base = DDR_BASE
|
|
},
|
|
[REG_TIMING] = {
|
|
.name = "timing",
|
|
.desc = ddr_timing,
|
|
- .size = ARRAY_SIZE(ddr_timing),
|
|
+ .size = DDRCTL_REG_TIMING_SIZE,
|
|
.base = DDR_BASE
|
|
},
|
|
[REG_PERF] = {
|
|
.name = "perf",
|
|
.desc = ddr_perf,
|
|
- .size = ARRAY_SIZE(ddr_perf),
|
|
+ .size = DDRCTL_REG_PERF_SIZE,
|
|
.base = DDR_BASE
|
|
},
|
|
[REG_MAP] = {
|
|
.name = "map",
|
|
.desc = ddr_map,
|
|
- .size = ARRAY_SIZE(ddr_map),
|
|
+ .size = DDRCTL_REG_MAP_SIZE,
|
|
.base = DDR_BASE
|
|
},
|
|
[REGPHY_REG] = {
|
|
.name = "static",
|
|
.desc = ddrphy_reg,
|
|
- .size = ARRAY_SIZE(ddrphy_reg),
|
|
+ .size = DDRPHY_REG_REG_SIZE,
|
|
.base = DDRPHY_BASE
|
|
},
|
|
[REGPHY_TIMING] = {
|
|
.name = "timing",
|
|
.desc = ddrphy_timing,
|
|
- .size = ARRAY_SIZE(ddrphy_timing),
|
|
+ .size = DDRPHY_REG_TIMING_SIZE,
|
|
.base = DDRPHY_BASE
|
|
},
|
|
[REGPHY_CAL] = {
|
|
.name = "cal",
|
|
.desc = ddrphy_cal,
|
|
- .size = ARRAY_SIZE(ddrphy_cal),
|
|
- .base = DDRPHY_BASE
|
|
- },
|
|
- [REG_DYN] = {
|
|
- .name = "dyn",
|
|
- .desc = ddr_dyn,
|
|
- .size = ARRAY_SIZE(ddr_dyn),
|
|
- .base = DDR_BASE
|
|
- },
|
|
- [REGPHY_DYN] = {
|
|
- .name = "dyn",
|
|
- .desc = ddrphy_dyn,
|
|
- .size = ARRAY_SIZE(ddrphy_dyn),
|
|
+ .size = DDRPHY_REG_CAL_SIZE,
|
|
.base = DDRPHY_BASE
|
|
},
|
|
};
|
|
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
|
|
index 82b8fda..773c9f7 100644
|
|
--- a/drivers/st/ddr/stm32mp1_ram.c
|
|
+++ b/drivers/st/ddr/stm32mp1_ram.c
|
|
@@ -252,8 +252,8 @@ static int stm32mp1_ddr_setup(void)
|
|
VERBOSE("%s: %s[0x%x] = %d\n", __func__,
|
|
param[idx].name, param[idx].size, ret);
|
|
if (ret != 0) {
|
|
- ERROR("%s: Cannot read %s\n",
|
|
- __func__, param[idx].name);
|
|
+ ERROR("%s: Cannot read %s, error=%d\n",
|
|
+ __func__, param[idx].name, ret);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
|
|
index 694a76a..ce609ba 100644
|
|
--- a/drivers/st/i2c/stm32_i2c.c
|
|
+++ b/drivers/st/i2c/stm32_i2c.c
|
|
@@ -79,18 +79,18 @@ struct i2c_timing_s {
|
|
bool is_saved;
|
|
};
|
|
|
|
-/**
|
|
- * All these values are coming from I2C Specification, Version 6.0, 4th of
|
|
- * April 2014.
|
|
+/*
|
|
+ * I2C specification values as per version 6.0, 4th of April 2014 [1],
|
|
+ * table 10 page 48: Characteristics of the SDA and SCL bus lines for
|
|
+ * Standard, Fast, and Fast-mode Plus I2C-bus devices.
|
|
*
|
|
- * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast,
|
|
- * and Fast-mode Plus I2C-bus devices.
|
|
+ * [1] https://www.i2c-bus.org/specification/
|
|
*/
|
|
static const struct i2c_spec_s i2c_specs[] = {
|
|
[I2C_SPEED_STANDARD] = {
|
|
.rate = STANDARD_RATE,
|
|
- .rate_min = 8000,
|
|
- .rate_max = 120000,
|
|
+ .rate_min = (STANDARD_RATE * 80) / 100,
|
|
+ .rate_max = (STANDARD_RATE * 120) / 100,
|
|
.fall_max = 300,
|
|
.rise_max = 1000,
|
|
.hddat_min = 0,
|
|
@@ -101,8 +101,8 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
},
|
|
[I2C_SPEED_FAST] = {
|
|
.rate = FAST_RATE,
|
|
- .rate_min = 320000,
|
|
- .rate_max = 480000,
|
|
+ .rate_min = (FAST_RATE * 80) / 100,
|
|
+ .rate_max = (FAST_RATE * 120) / 100,
|
|
.fall_max = 300,
|
|
.rise_max = 300,
|
|
.hddat_min = 0,
|
|
@@ -113,8 +113,8 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
},
|
|
[I2C_SPEED_FAST_PLUS] = {
|
|
.rate = FAST_PLUS_RATE,
|
|
- .rate_min = 800000,
|
|
- .rate_max = 1200000,
|
|
+ .rate_min = (FAST_PLUS_RATE * 80) / 100,
|
|
+ .rate_max = (FAST_PLUS_RATE * 120) / 100,
|
|
.fall_max = 100,
|
|
.rise_max = 120,
|
|
.hddat_min = 0,
|
|
@@ -125,6 +125,9 @@ static const struct i2c_spec_s i2c_specs[] = {
|
|
},
|
|
};
|
|
|
|
+static uint32_t saved_timing;
|
|
+static unsigned long saved_frequency;
|
|
+
|
|
static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
|
|
uint16_t dev_addr, uint16_t mem_addr,
|
|
uint16_t mem_add_size,
|
|
@@ -376,7 +379,7 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
uint32_t *timing)
|
|
{
|
|
int rc = 0;
|
|
- uint32_t clock_src;
|
|
+ unsigned long clock_src;
|
|
|
|
clock_src = stm32mp_clk_get_rate(hi2c->clock);
|
|
if (clock_src == 0U) {
|
|
@@ -384,6 +387,15 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ /*
|
|
+ * If the timing has already been computed, and the frequency is the
|
|
+ * same as when it was computed, then use the saved timing.
|
|
+ */
|
|
+ if (clock_src == saved_frequency) {
|
|
+ *timing = saved_timing;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
do {
|
|
rc = i2c_compute_timing(init, clock_src, timing);
|
|
if (rc != 0) {
|
|
@@ -403,7 +415,7 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
return rc;
|
|
}
|
|
|
|
- VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\n",
|
|
+ VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%li)\n",
|
|
init->speed_mode, i2c_specs[init->speed_mode].rate, clock_src);
|
|
VERBOSE("I2C Rise(%i) and Fall(%i) Time\n",
|
|
init->rise_time, init->fall_time);
|
|
@@ -411,6 +423,9 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
|
|
(init->analog_filter ? "On" : "Off"),
|
|
init->digital_filter_coef);
|
|
|
|
+ saved_timing = *timing;
|
|
+ saved_frequency = clock_src;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
|
|
index 6d91a9f..1b5bfe3 100644
|
|
--- a/drivers/st/iwdg/stm32_iwdg.c
|
|
+++ b/drivers/st/iwdg/stm32_iwdg.c
|
|
@@ -182,6 +182,10 @@ void stm32_iwdg_refresh(uint32_t instance)
|
|
|
|
assert(iwdg);
|
|
|
|
+ if (iwdg->base == 0U) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
stm32mp_clk_enable(iwdg->clock);
|
|
|
|
mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
|
|
@@ -215,14 +219,14 @@ int stm32_iwdg_init(void)
|
|
iwdg->clock = (unsigned long)dt_info.clock;
|
|
|
|
/* DT can specify low power cases */
|
|
- if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) !=
|
|
+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) ==
|
|
NULL) {
|
|
- iwdg->flags |= IWDG_ENABLE_ON_STOP;
|
|
+ iwdg->flags |= IWDG_DISABLE_ON_STOP;
|
|
}
|
|
|
|
- if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) !=
|
|
+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) ==
|
|
NULL) {
|
|
- iwdg->flags |= IWDG_ENABLE_ON_STANDBY;
|
|
+ iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
|
|
}
|
|
|
|
/* Explicit list of supported bit flags */
|
|
@@ -243,12 +247,12 @@ int stm32_iwdg_init(void)
|
|
goto next;
|
|
}
|
|
|
|
- if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) {
|
|
- iwdg->flags |= IWDG_ENABLE_ON_STOP;
|
|
+ if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) {
|
|
+ iwdg->flags |= IWDG_DISABLE_ON_STOP;
|
|
}
|
|
|
|
- if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) {
|
|
- iwdg->flags |= IWDG_ENABLE_ON_STANDBY;
|
|
+ if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) {
|
|
+ iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
|
|
}
|
|
|
|
VERBOSE("IWDG%u found, %ssecure\n", idx + 1,
|
|
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
|
|
index 620087e..aab0582 100644
|
|
--- a/drivers/st/mmc/stm32_sdmmc2.c
|
|
+++ b/drivers/st/mmc/stm32_sdmmc2.c
|
|
@@ -70,20 +70,14 @@
|
|
#define SDMMC_DCTRLR_DTEN BIT(0)
|
|
#define SDMMC_DCTRLR_DTDIR BIT(1)
|
|
#define SDMMC_DCTRLR_DTMODE GENMASK(3, 2)
|
|
-#define SDMMC_DCTRLR_DBLOCKSIZE_0 BIT(4)
|
|
-#define SDMMC_DCTRLR_DBLOCKSIZE_1 BIT(5)
|
|
-#define SDMMC_DCTRLR_DBLOCKSIZE_3 BIT(7)
|
|
#define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4)
|
|
+#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4
|
|
#define SDMMC_DCTRLR_FIFORST BIT(13)
|
|
|
|
#define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \
|
|
SDMMC_DCTRLR_DTDIR | \
|
|
SDMMC_DCTRLR_DTMODE | \
|
|
SDMMC_DCTRLR_DBLOCKSIZE)
|
|
-#define SDMMC_DBLOCKSIZE_8 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \
|
|
- SDMMC_DCTRLR_DBLOCKSIZE_1)
|
|
-#define SDMMC_DBLOCKSIZE_512 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \
|
|
- SDMMC_DCTRLR_DBLOCKSIZE_3)
|
|
|
|
/* SDMMC status register */
|
|
#define SDMMC_STAR_CCRCFAIL BIT(0)
|
|
@@ -172,10 +166,15 @@ static void dump_registers(void)
|
|
static void stm32_sdmmc2_init(void)
|
|
{
|
|
uint32_t clock_div;
|
|
+ uint32_t freq = STM32MP_MMC_INIT_FREQ;
|
|
uintptr_t base = sdmmc2_params.reg_base;
|
|
|
|
+ if (sdmmc2_params.max_freq != 0U) {
|
|
+ freq = MIN(sdmmc2_params.max_freq, STM32MP_MMC_INIT_FREQ);
|
|
+ }
|
|
+
|
|
clock_div = div_round_up(sdmmc2_params.clk_rate,
|
|
- STM32MP_MMC_INIT_FREQ * 2);
|
|
+ freq * 2);
|
|
|
|
mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
|
|
sdmmc2_params.negedge |
|
|
@@ -426,7 +425,7 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
|
|
{
|
|
uintptr_t base = sdmmc2_params.reg_base;
|
|
uint32_t bus_cfg = 0;
|
|
- uint32_t clock_div, max_freq;
|
|
+ uint32_t clock_div, max_freq, freq;
|
|
uint32_t clk_rate = sdmmc2_params.clk_rate;
|
|
uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq;
|
|
|
|
@@ -458,7 +457,13 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
|
|
}
|
|
}
|
|
|
|
- clock_div = div_round_up(clk_rate, max_freq * 2);
|
|
+ if (sdmmc2_params.max_freq != 0U) {
|
|
+ freq = MIN(sdmmc2_params.max_freq, max_freq);
|
|
+ } else {
|
|
+ freq = max_freq;
|
|
+ }
|
|
+
|
|
+ clock_div = div_round_up(clk_rate, freq * 2);
|
|
|
|
mmio_write_32(base + SDMMC_CLKCR,
|
|
SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg |
|
|
@@ -474,11 +479,12 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
|
|
int ret;
|
|
uintptr_t base = sdmmc2_params.reg_base;
|
|
uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR;
|
|
+ uint32_t arg_size;
|
|
|
|
- if (size == 8U) {
|
|
- data_ctrl |= SDMMC_DBLOCKSIZE_8;
|
|
+ if (size > MMC_BLOCK_SIZE) {
|
|
+ arg_size = MMC_BLOCK_SIZE;
|
|
} else {
|
|
- data_ctrl |= SDMMC_DBLOCKSIZE_512;
|
|
+ arg_size = size;
|
|
}
|
|
|
|
sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf);
|
|
@@ -497,12 +503,7 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
|
|
zeromem(&cmd, sizeof(struct mmc_cmd));
|
|
|
|
cmd.cmd_idx = MMC_CMD(16);
|
|
- if (size > MMC_BLOCK_SIZE) {
|
|
- cmd.cmd_arg = MMC_BLOCK_SIZE;
|
|
- } else {
|
|
- cmd.cmd_arg = size;
|
|
- }
|
|
-
|
|
+ cmd.cmd_arg = arg_size;
|
|
cmd.resp_type = MMC_RESPONSE_R1;
|
|
|
|
ret = stm32_sdmmc2_send_cmd(&cmd);
|
|
@@ -524,6 +525,8 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
|
|
flush_dcache_range(buf, size);
|
|
}
|
|
|
|
+ data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT;
|
|
+
|
|
mmio_clrsetbits_32(base + SDMMC_DCTRLR,
|
|
SDMMC_DCTRLR_CLEAR_MASK,
|
|
data_ctrl);
|
|
@@ -714,6 +717,11 @@ static int stm32_sdmmc2_dt_get_config(void)
|
|
}
|
|
}
|
|
|
|
+ cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL);
|
|
+ if (cuint != NULL) {
|
|
+ sdmmc2_params.max_freq = fdt32_to_cpu(*cuint);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -745,6 +753,7 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
|
|
mdelay(1);
|
|
|
|
sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
|
|
+ sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4;
|
|
|
|
return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
|
|
sdmmc2_params.bus_width, sdmmc2_params.flags,
|
|
diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c
|
|
index 7f435cc..9198800 100644
|
|
--- a/drivers/st/nand/nand.c
|
|
+++ b/drivers/st/nand/nand.c
|
|
@@ -83,21 +83,16 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
nand_timings *tims = &hNand->Info.timings;
|
|
unsigned long hclk = stm32mp_clk_get_rate(FMC_K);
|
|
unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000);
|
|
- int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att;
|
|
-
|
|
- tar = hclkp;
|
|
- if (tar < FMC_TAR_MIN)
|
|
- tar = FMC_TAR_MIN;
|
|
- tims->tar = div_round_up(tar, hclkp) - 1;
|
|
- if (tims->tar > FMC_PCR_TIMING_MASK)
|
|
- tims->tar = FMC_PCR_TIMING_MASK;
|
|
-
|
|
- tclr = hclkp;
|
|
- if (tclr < FMC_TCLR_MIN)
|
|
- tclr = FMC_TCLR_MIN;
|
|
- tims->tclr = div_round_up(tclr, hclkp) - 1;
|
|
- if (tims->tclr > FMC_PCR_TIMING_MASK)
|
|
- tims->tclr = FMC_PCR_TIMING_MASK;
|
|
+ unsigned long timing, tar, tclr, thiz, twait;
|
|
+ unsigned long tset_mem, tset_att, thold_mem, thold_att;
|
|
+
|
|
+ tar = MAX(hclkp, FMC_TAR_MIN);
|
|
+ timing = div_round_up(tar, hclkp) - 1;
|
|
+ tims->tar = MIN(timing, FMC_PCR_TIMING_MASK);
|
|
+
|
|
+ tclr = MAX(hclkp, FMC_TCLR_MIN);
|
|
+ timing = div_round_up(tclr, hclkp) - 1;
|
|
+ tims->tclr = MIN(timing, FMC_PCR_TIMING_MASK);
|
|
|
|
tims->thiz = FMC_THIZ;
|
|
thiz = (tims->thiz + 1) * hclkp;
|
|
@@ -107,16 +102,11 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
* tWAIT > tWP
|
|
* tWAIT > tREA + tIO
|
|
*/
|
|
- twait = hclkp;
|
|
- if (twait < FMC_TRP_MIN)
|
|
- twait = FMC_TRP_MIN;
|
|
- if (twait < FMC_TWP_MIN)
|
|
- twait = FMC_TWP_MIN;
|
|
- if (twait < FMC_TREA_MAX + FMC_TIO)
|
|
- twait = FMC_TREA_MAX + FMC_TIO;
|
|
- tims->twait = div_round_up(twait, hclkp);
|
|
- if (tims->twait == 0)
|
|
- tims->twait = 1;
|
|
+ twait = MAX(hclkp, FMC_TRP_MIN);
|
|
+ twait = MAX(twait, FMC_TWP_MIN);
|
|
+ twait = MAX(twait, FMC_TREA_MAX + FMC_TIO);
|
|
+ timing = div_round_up(twait, hclkp);
|
|
+ tims->twait = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK);
|
|
|
|
/*
|
|
* tSETUP_MEM > tCS - tWAIT
|
|
@@ -124,37 +114,39 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
* tSETUP_MEM > tDS - (tWAIT - tHIZ)
|
|
*/
|
|
tset_mem = hclkp;
|
|
- if (twait < FMC_TCS_MIN && (tset_mem < FMC_TCS_MIN - twait))
|
|
+ if (twait < FMC_TCS_MIN && (tset_mem < FMC_TCS_MIN - twait)) {
|
|
tset_mem = FMC_TCS_MIN - twait;
|
|
- if (twait < FMC_TALS_MIN && (tset_mem < FMC_TALS_MIN - twait))
|
|
+ }
|
|
+ if (twait < FMC_TALS_MIN && (tset_mem < FMC_TALS_MIN - twait)) {
|
|
tset_mem = FMC_TALS_MIN - twait;
|
|
+ }
|
|
if (twait > thiz && (twait - thiz < FMC_TDS_MIN) &&
|
|
- (tset_mem < FMC_TDS_MIN - (twait - thiz)))
|
|
+ (tset_mem < FMC_TDS_MIN - (twait - thiz))) {
|
|
tset_mem = FMC_TDS_MIN - (twait - thiz);
|
|
- tims->tset_mem = div_round_up(tset_mem, hclkp);
|
|
- if (tims->tset_mem == 0)
|
|
- tims->tset_mem = 1;
|
|
+ }
|
|
+ timing = div_round_up(tset_mem, hclkp);
|
|
+ tims->tset_mem = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK);
|
|
|
|
/*
|
|
* tHOLD_MEM > tCH
|
|
* tHOLD_MEM > tREH - tSETUP_MEM
|
|
* tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
|
|
*/
|
|
- thold_mem = hclkp;
|
|
- if (thold_mem < FMC_TCH_MIN)
|
|
- thold_mem = FMC_TCH_MIN;
|
|
+ thold_mem = MAX(hclkp, FMC_TCH_MIN);
|
|
if (tset_mem < FMC_TREH_MIN &&
|
|
- (thold_mem < FMC_TREH_MIN - tset_mem))
|
|
+ (thold_mem < FMC_TREH_MIN - tset_mem)) {
|
|
thold_mem = FMC_TREH_MIN - tset_mem;
|
|
+ }
|
|
if ((tset_mem + twait < FMC_TRC_MIN) &&
|
|
- (thold_mem < FMC_TRC_MIN - (tset_mem + twait)))
|
|
+ (thold_mem < FMC_TRC_MIN - (tset_mem + twait))) {
|
|
thold_mem = FMC_TRC_MIN - (tset_mem + twait);
|
|
+ }
|
|
if ((tset_mem + twait < FMC_TWC_MIN) &&
|
|
- (thold_mem < FMC_TWC_MIN - (tset_mem + twait)))
|
|
+ (thold_mem < FMC_TWC_MIN - (tset_mem + twait))) {
|
|
thold_mem = FMC_TWC_MIN - (tset_mem + twait);
|
|
- tims->thold_mem = div_round_up(thold_mem, hclkp);
|
|
- if (tims->thold_mem == 0)
|
|
- tims->thold_mem = 1;
|
|
+ }
|
|
+ timing = div_round_up(thold_mem, hclkp);
|
|
+ tims->thold_mem = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK);
|
|
|
|
/*
|
|
* tSETUP_ATT > tCS - tWAIT
|
|
@@ -164,21 +156,25 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
* tSETUP_ATT > tDS - (tWAIT - tHIZ)
|
|
*/
|
|
tset_att = hclkp;
|
|
- if (twait < FMC_TCS_MIN && (tset_att < FMC_TCS_MIN - twait))
|
|
+ if (twait < FMC_TCS_MIN && (tset_att < FMC_TCS_MIN - twait)) {
|
|
tset_att = FMC_TCS_MIN - twait;
|
|
- if (twait < FMC_TCLS_MIN && (tset_att < FMC_TCLS_MIN - twait))
|
|
+ }
|
|
+ if (twait < FMC_TCLS_MIN && (tset_att < FMC_TCLS_MIN - twait)) {
|
|
tset_att = FMC_TCLS_MIN - twait;
|
|
- if (twait < FMC_TALS_MIN && (tset_att < FMC_TALS_MIN - twait))
|
|
+ }
|
|
+ if (twait < FMC_TALS_MIN && (tset_att < FMC_TALS_MIN - twait)) {
|
|
tset_att = FMC_TALS_MIN - twait;
|
|
+ }
|
|
if (thold_mem < FMC_TRHW_MIN &&
|
|
- (tset_att < FMC_TRHW_MIN - thold_mem))
|
|
+ (tset_att < FMC_TRHW_MIN - thold_mem)) {
|
|
tset_att = FMC_TRHW_MIN - thold_mem;
|
|
+ }
|
|
if (twait > thiz && (twait - thiz < FMC_TDS_MIN) &&
|
|
- (tset_att < FMC_TDS_MIN - (twait - thiz)))
|
|
+ (tset_att < FMC_TDS_MIN - (twait - thiz))) {
|
|
tset_att = FMC_TDS_MIN - (twait - thiz);
|
|
- tims->tset_att = div_round_up(tset_att, hclkp);
|
|
- if (tims->tset_att == 0)
|
|
- tims->tset_att = 1;
|
|
+ }
|
|
+ timing = div_round_up(tset_att, hclkp);
|
|
+ tims->tset_att = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK);
|
|
|
|
/*
|
|
* tHOLD_ATT > tALH
|
|
@@ -193,38 +189,42 @@ static void nand_calc_timing(NAND_HandleTypeDef *hNand)
|
|
* tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
|
|
* tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
|
|
*/
|
|
- thold_att = hclkp;
|
|
- if (thold_att < FMC_TALH_MIN)
|
|
- thold_att = FMC_TALH_MIN;
|
|
- if (thold_att < FMC_TCH_MIN)
|
|
- thold_att = FMC_TCH_MIN;
|
|
- if (thold_att < FMC_TCLH_MIN)
|
|
- thold_att = FMC_TCLH_MIN;
|
|
- if (thold_att < FMC_TCOH_MIN)
|
|
- thold_att = FMC_TCOH_MIN;
|
|
- if (thold_att < FMC_TDH_MIN)
|
|
- thold_att = FMC_TDH_MIN;
|
|
+ thold_att = MAX(hclkp, FMC_TALH_MIN);
|
|
+ thold_att = MAX(hclkp, FMC_TCH_MIN);
|
|
+ thold_att = MAX(hclkp, FMC_TCLH_MIN);
|
|
+ thold_att = MAX(hclkp, FMC_TCOH_MIN);
|
|
+ thold_att = MAX(hclkp, FMC_TDH_MIN);
|
|
if ((FMC_TWB_MAX + FMC_TIO + FMC_TSYNC > tset_mem) &&
|
|
- (thold_att < FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem))
|
|
+ (thold_att < FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem)) {
|
|
thold_att = FMC_TWB_MAX + FMC_TIO + FMC_TSYNC - tset_mem;
|
|
+ }
|
|
if (tset_mem < FMC_TADL_MIN &&
|
|
- (thold_att < FMC_TADL_MIN - tset_mem))
|
|
+ (thold_att < FMC_TADL_MIN - tset_mem)) {
|
|
thold_att = FMC_TADL_MIN - tset_mem;
|
|
+ }
|
|
if (tset_mem < FMC_TWH_MIN &&
|
|
- (thold_att < FMC_TWH_MIN - tset_mem))
|
|
+ (thold_att < FMC_TWH_MIN - tset_mem)) {
|
|
thold_att = FMC_TWH_MIN - tset_mem;
|
|
+ }
|
|
if (tset_mem < FMC_TWHR_MIN &&
|
|
- (thold_att < FMC_TWHR_MIN - tset_mem))
|
|
+ (thold_att < FMC_TWHR_MIN - tset_mem)) {
|
|
thold_att = FMC_TWHR_MIN - tset_mem;
|
|
+ }
|
|
if (tset_att + twait < FMC_TRC_MIN &&
|
|
- (thold_att < FMC_TRC_MIN - (tset_att + twait)))
|
|
+ (thold_att < FMC_TRC_MIN - (tset_att + twait))) {
|
|
thold_att = FMC_TRC_MIN - (tset_att + twait);
|
|
+ }
|
|
if (tset_att + twait < FMC_TWC_MIN &&
|
|
- (thold_att < FMC_TWC_MIN - (tset_att + twait)))
|
|
+ (thold_att < FMC_TWC_MIN - (tset_att + twait))) {
|
|
thold_att = FMC_TWC_MIN - (tset_att + twait);
|
|
- tims->thold_att = div_round_up(thold_att, hclkp);
|
|
- if (tims->thold_att == 0)
|
|
- tims->thold_att = 1;
|
|
+ }
|
|
+ timing = div_round_up(thold_att, hclkp);
|
|
+ tims->thold_att = MIN(MAX(timing, 1UL), FMC_PMEM_PATT_TIMING_MASK);
|
|
+
|
|
+ VERBOSE("Nand timings: %u - %u - %u - %u - %u - %u - %u - %u\n",
|
|
+ tims->tclr, tims->tar, tims->thiz, tims->twait,
|
|
+ tims->thold_mem, tims->tset_mem,
|
|
+ tims->thold_att, tims->tset_att);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c
|
|
index 6d36e31..4c58000 100644
|
|
--- a/drivers/st/timer/stm32_timer.c
|
|
+++ b/drivers/st/timer/stm32_timer.c
|
|
@@ -59,6 +59,7 @@
|
|
#define TIM_TIMEOUT_STEP_US 10
|
|
#define TIM_PRESCAL_HSI 10U
|
|
#define TIM_PRESCAL_CSI 7U
|
|
+#define TIM_MIN_FREQ_CALIB 50000000U
|
|
|
|
struct stm32_timer_instance {
|
|
uintptr_t base;
|
|
@@ -84,12 +85,18 @@ static int stm32_timer_get_dt_node(struct dt_node_info *info, int offset)
|
|
return node;
|
|
}
|
|
|
|
-static void stm32_timer_config(struct stm32_timer_instance *timer)
|
|
+static int stm32_timer_config(struct stm32_timer_instance *timer)
|
|
{
|
|
stm32mp_clk_enable(timer->clk);
|
|
|
|
timer->freq = stm32mp_clk_timer_get_rate(timer->clk);
|
|
|
|
+ if (timer->freq < TIM_MIN_FREQ_CALIB) {
|
|
+ WARN("Timer is not accurate enough for calibration\n");
|
|
+ stm32mp_clk_disable(timer->clk);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
if ((mmio_read_32(timer->base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) !=
|
|
timer->cal_input) {
|
|
mmio_clrsetbits_32(timer->base + TIM_CCMR1,
|
|
@@ -110,6 +117,8 @@ static void stm32_timer_config(struct stm32_timer_instance *timer)
|
|
}
|
|
|
|
stm32mp_clk_disable(timer->clk);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer)
|
|
@@ -119,7 +128,9 @@ static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer)
|
|
uint32_t old_counter = 0U;
|
|
int twice = 0;
|
|
|
|
- stm32_timer_config(timer);
|
|
+ if (stm32_timer_config(timer) < 0) {
|
|
+ return 0U;
|
|
+ }
|
|
|
|
stm32mp_clk_enable(timer->clk);
|
|
|
|
@@ -268,10 +279,13 @@ int stm32_timer_init(void)
|
|
stm32mp_clk_timer_get_rate(timer->clk);
|
|
timer->cal_input =
|
|
(uint8_t)fdt32_to_cpu(*cuint);
|
|
- stm32_timer_config(timer);
|
|
+ if (stm32_timer_config(timer) < 0) {
|
|
+ timer->base = 0;
|
|
+ continue;
|
|
+ }
|
|
}
|
|
|
|
- cuint = fdt_getprop(fdt, node, "st,csi_cal-input",
|
|
+ cuint = fdt_getprop(fdt, node, "st,csi-cal-input",
|
|
NULL);
|
|
if (cuint != NULL) {
|
|
timer = &stm32_timer[CSI_CAL];
|
|
@@ -281,7 +295,10 @@ int stm32_timer_init(void)
|
|
stm32mp_clk_timer_get_rate(timer->clk);
|
|
timer->cal_input =
|
|
(uint8_t)fdt32_to_cpu(*cuint);
|
|
- stm32_timer_config(timer);
|
|
+ if (stm32_timer_config(timer) < 0) {
|
|
+ timer->base = 0;
|
|
+ continue;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
|
|
index 16b8cf6..11e8f2b 100644
|
|
--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
|
|
+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
|
|
@@ -1,8 +1,8 @@
|
|
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
/*
|
|
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
|
- */
|
|
-/* STM32MP157C DK1/DK2 BOARD configuration
|
|
+ *
|
|
+ * STM32MP157C DK1/DK2 BOARD configuration
|
|
* 1x DDR3L 4Gb, 16-bit, 533MHz.
|
|
* Reference used NT5CC256M16DP-DI from NANYA
|
|
*
|
|
@@ -16,8 +16,7 @@
|
|
* address mapping : RBC
|
|
* Tc > + 85C : N
|
|
*/
|
|
-
|
|
-#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41"
|
|
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45"
|
|
#define DDR_MEM_SPEED 533000
|
|
#define DDR_MEM_SIZE 0x20000000
|
|
|
|
@@ -90,7 +89,7 @@
|
|
#define DDR_PTR2 0x042DA068
|
|
#define DDR_ACIOCR 0x10400812
|
|
#define DDR_DXCCR 0x00000C40
|
|
-#define DDR_DSGCR 0xF200001F
|
|
+#define DDR_DSGCR 0xF200011F
|
|
#define DDR_DCR 0x0000000B
|
|
#define DDR_DTPR0 0x38D488D0
|
|
#define DDR_DTPR1 0x098B00D8
|
|
@@ -109,11 +108,11 @@
|
|
#define DDR_DX1DLLCR 0x40000000
|
|
#define DDR_DX1DQTR 0xFFFFFFFF
|
|
#define DDR_DX1DQSTR 0x3DB02000
|
|
-#define DDR_DX2GCR 0x0000CE81
|
|
+#define DDR_DX2GCR 0x0000CE80
|
|
#define DDR_DX2DLLCR 0x40000000
|
|
#define DDR_DX2DQTR 0xFFFFFFFF
|
|
#define DDR_DX2DQSTR 0x3DB02000
|
|
-#define DDR_DX3GCR 0x0000CE81
|
|
+#define DDR_DX3GCR 0x0000CE80
|
|
#define DDR_DX3DLLCR 0x40000000
|
|
#define DDR_DX3DQTR 0xFFFFFFFF
|
|
#define DDR_DX3DQSTR 0x3DB02000
|
|
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
|
|
index 82e7104..4b70b60 100644
|
|
--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
|
|
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
|
|
@@ -1,9 +1,8 @@
|
|
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
/*
|
|
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
|
|
- */
|
|
-
|
|
-/* STM32MP157C ED1 BOARD configuration
|
|
+ *
|
|
+ * STM32MP157C ED1 BOARD configuration
|
|
* 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
|
|
* Reference used NT5CC256M16DP-DI from NANYA
|
|
*
|
|
@@ -17,8 +16,7 @@
|
|
* address mapping : RBC
|
|
* Tc > + 85C : N
|
|
*/
|
|
-
|
|
-#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41"
|
|
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45"
|
|
#define DDR_MEM_SPEED 533000
|
|
#define DDR_MEM_SIZE 0x40000000
|
|
|
|
@@ -91,7 +89,7 @@
|
|
#define DDR_PTR2 0x042DA068
|
|
#define DDR_ACIOCR 0x10400812
|
|
#define DDR_DXCCR 0x00000C40
|
|
-#define DDR_DSGCR 0xF200001F
|
|
+#define DDR_DSGCR 0xF200011F
|
|
#define DDR_DCR 0x0000000B
|
|
#define DDR_DTPR0 0x38D488D0
|
|
#define DDR_DTPR1 0x098B00D8
|
|
diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts
|
|
index fadb442..f081575 100644
|
|
--- a/fdts/stm32mp157a-dk1.dts
|
|
+++ b/fdts/stm32mp157a-dk1.dts
|
|
@@ -149,7 +149,9 @@
|
|
};
|
|
|
|
&pwr {
|
|
- pwr-supply = <&vdd>;
|
|
+ pwr-regulators {
|
|
+ vdd-supply = <&vdd>;
|
|
+ };
|
|
};
|
|
|
|
&rng1 {
|
|
@@ -269,7 +271,7 @@
|
|
CLK_UART6_HSI
|
|
CLK_UART78_HSI
|
|
CLK_SPDIF_PLL4P
|
|
- CLK_FDCAN_PLL4Q
|
|
+ CLK_FDCAN_PLL4R
|
|
CLK_SAI1_PLL3Q
|
|
CLK_SAI2_PLL3Q
|
|
CLK_SAI3_PLL3Q
|
|
@@ -306,6 +308,14 @@
|
|
};
|
|
|
|
/* Security specific */
|
|
+&bsec {
|
|
+ board_id: board_id@ec {
|
|
+ reg = <0xec 0x4>;
|
|
+ status = "okay";
|
|
+ secure-status = "okay";
|
|
+ };
|
|
+};
|
|
+
|
|
&etzpc {
|
|
st,decprot = <
|
|
DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
|
|
@@ -335,7 +345,7 @@
|
|
&timers15 {
|
|
secure-status = "okay";
|
|
st,hsi-cal-input = <7>;
|
|
- st,csi_cal-input = <8>;
|
|
+ st,csi-cal-input = <8>;
|
|
};
|
|
|
|
/* Low-power states of regulators */
|
|
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
|
|
index 0daf4be..61d5301 100644
|
|
--- a/fdts/stm32mp157c-ed1.dts
|
|
+++ b/fdts/stm32mp157c-ed1.dts
|
|
@@ -144,7 +144,9 @@
|
|
};
|
|
|
|
&pwr {
|
|
- pwr-supply = <&vdd>;
|
|
+ pwr-regulators {
|
|
+ vdd-supply = <&vdd>;
|
|
+ };
|
|
};
|
|
|
|
&rng1 {
|
|
@@ -274,7 +276,7 @@
|
|
CLK_UART6_HSI
|
|
CLK_UART78_HSI
|
|
CLK_SPDIF_PLL4P
|
|
- CLK_FDCAN_PLL4Q
|
|
+ CLK_FDCAN_PLL4R
|
|
CLK_SAI1_PLL3Q
|
|
CLK_SAI2_PLL3Q
|
|
CLK_SAI3_PLL3Q
|
|
@@ -311,6 +313,14 @@
|
|
};
|
|
|
|
/* Security specific */
|
|
+&bsec {
|
|
+ board_id: board_id@ec {
|
|
+ reg = <0xec 0x4>;
|
|
+ status = "okay";
|
|
+ secure-status = "okay";
|
|
+ };
|
|
+};
|
|
+
|
|
&etzpc {
|
|
st,decprot = <
|
|
DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
|
|
@@ -331,6 +341,7 @@
|
|
system_suspend_supported_soc_modes = <
|
|
STM32_PM_CSLEEP_RUN
|
|
STM32_PM_CSTOP_ALLOW_LP_STOP
|
|
+ STM32_PM_CSTOP_ALLOW_LPLV_STOP
|
|
STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR
|
|
>;
|
|
system_off_soc_mode = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
|
|
@@ -339,7 +350,7 @@
|
|
&timers15 {
|
|
secure-status = "okay";
|
|
st,hsi-cal-input = <7>;
|
|
- st,csi_cal-input = <8>;
|
|
+ st,csi-cal-input = <8>;
|
|
};
|
|
|
|
/* Low-power states of regulators */
|
|
@@ -348,6 +359,10 @@
|
|
regulator-on-in-suspend;
|
|
regulator-suspend-microvolt = <1200000>;
|
|
};
|
|
+ lplv-stop {
|
|
+ regulator-on-in-suspend;
|
|
+ regulator-suspend-microvolt = <900000>;
|
|
+ };
|
|
standby-ddr-sr {
|
|
regulator-off-in-suspend;
|
|
};
|
|
@@ -361,6 +376,10 @@
|
|
regulator-suspend-microvolt = <1350000>;
|
|
regulator-on-in-suspend;
|
|
};
|
|
+ lplv-stop {
|
|
+ regulator-suspend-microvolt = <1350000>;
|
|
+ regulator-on-in-suspend;
|
|
+ };
|
|
standby-ddr-sr {
|
|
regulator-suspend-microvolt = <1350000>;
|
|
regulator-on-in-suspend;
|
|
@@ -375,6 +394,10 @@
|
|
regulator-suspend-microvolt = <3300000>;
|
|
regulator-on-in-suspend;
|
|
};
|
|
+ lplv-stop {
|
|
+ regulator-suspend-microvolt = <3300000>;
|
|
+ regulator-on-in-suspend;
|
|
+ };
|
|
standby-ddr-sr {
|
|
regulator-suspend-microvolt = <3300000>;
|
|
regulator-on-in-suspend;
|
|
@@ -416,6 +439,9 @@
|
|
lp-stop {
|
|
regulator-off-in-suspend;
|
|
};
|
|
+ lplv-stop {
|
|
+ regulator-off-in-suspend;
|
|
+ };
|
|
standby-ddr-sr {
|
|
regulator-off-in-suspend;
|
|
};
|
|
@@ -455,6 +481,9 @@
|
|
lp-stop {
|
|
regulator-on-in-suspend;
|
|
};
|
|
+ lplv-stop {
|
|
+ regulator-on-in-suspend;
|
|
+ };
|
|
standby-ddr-sr {
|
|
regulator-on-in-suspend;
|
|
};
|
|
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
|
|
index 8d45a33..124ed53 100644
|
|
--- a/fdts/stm32mp157c-security.dtsi
|
|
+++ b/fdts/stm32mp157c-security.dtsi
|
|
@@ -8,7 +8,7 @@
|
|
|
|
/ {
|
|
soc {
|
|
- iwdg1: iwdg@5C003000 {
|
|
+ iwdg1: watchdog@5C003000 {
|
|
compatible = "st,stm32mp1-iwdg";
|
|
reg = <0x5C003000 0x400>;
|
|
clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
|
|
@@ -41,9 +41,6 @@
|
|
spare_ns_ea: spare_ns_ea@ea {
|
|
reg = <0xea 0x2>;
|
|
};
|
|
- board_id: board_id@ec {
|
|
- reg = <0xec 0x4>;
|
|
- };
|
|
};
|
|
|
|
&iwdg2 {
|
|
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
|
|
index 06c2cf1..e649c3a 100644
|
|
--- a/fdts/stm32mp157c.dtsi
|
|
+++ b/fdts/stm32mp157c.dtsi
|
|
@@ -290,6 +290,27 @@
|
|
status = "disabled";
|
|
};
|
|
|
|
+ usbphyc: usbphyc@5a006000 {
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
+ #clock-cells = <0>;
|
|
+ compatible = "st,stm32mp1-usbphyc";
|
|
+ reg = <0x5a006000 0x1000>;
|
|
+ clocks = <&rcc USBPHY_K>;
|
|
+ resets = <&rcc USBPHY_R>;
|
|
+ status = "disabled";
|
|
+
|
|
+ usbphyc_port0: usb-phy@0 {
|
|
+ #phy-cells = <0>;
|
|
+ reg = <0>;
|
|
+ };
|
|
+
|
|
+ usbphyc_port1: usb-phy@1 {
|
|
+ #phy-cells = <1>;
|
|
+ reg = <1>;
|
|
+ };
|
|
+ };
|
|
+
|
|
usart1: serial@5c000000 {
|
|
compatible = "st,stm32h7-uart";
|
|
reg = <0x5c000000 0x400>;
|
|
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
|
|
index 9900630..38553b9 100644
|
|
--- a/include/drivers/mmc.h
|
|
+++ b/include/drivers/mmc.h
|
|
@@ -219,6 +219,7 @@ struct mmc_device_info {
|
|
unsigned long long device_size; /* Size of device in bytes */
|
|
unsigned int block_size; /* Block size in bytes */
|
|
unsigned int max_bus_freq; /* Max bus freq in Hz */
|
|
+ unsigned int ocr_voltage; /* OCR voltage */
|
|
enum mmc_device_type mmc_dev_type; /* Type of MMC */
|
|
};
|
|
|
|
diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h
|
|
index b21bde8..71a68c2 100644
|
|
--- a/include/drivers/st/bsec.h
|
|
+++ b/include/drivers/st/bsec.h
|
|
@@ -135,7 +135,7 @@
|
|
*/
|
|
#define BSEC_LOCK_UPPER_OTP 0x00
|
|
#define BSEC_LOCK_DEBUG 0x02
|
|
-#define BSEC_LOCK_PROGRAM 0x03
|
|
+#define BSEC_LOCK_PROGRAM 0x04
|
|
|
|
/* Values for struct bsec_config::freq */
|
|
#define FREQ_10_20_MHZ 0x0
|
|
@@ -189,16 +189,15 @@ uint32_t bsec_get_version(void);
|
|
uint32_t bsec_get_id(void);
|
|
uint32_t bsec_get_magic_id(void);
|
|
|
|
-bool bsec_write_sr_lock(uint32_t otp, uint32_t value);
|
|
-bool bsec_read_sr_lock(uint32_t otp);
|
|
-bool bsec_write_sw_lock(uint32_t otp, uint32_t value);
|
|
-bool bsec_read_sw_lock(uint32_t otp);
|
|
-bool bsec_write_sp_lock(uint32_t otp, uint32_t value);
|
|
-bool bsec_read_sp_lock(uint32_t otp);
|
|
-bool bsec_wr_lock(uint32_t otp);
|
|
-uint32_t bsec_otp_lock(uint32_t service, uint32_t value);
|
|
+uint32_t bsec_set_sr_lock(uint32_t otp);
|
|
+uint32_t bsec_read_sr_lock(uint32_t otp, bool *value);
|
|
+uint32_t bsec_set_sw_lock(uint32_t otp);
|
|
+uint32_t bsec_read_sw_lock(uint32_t otp, bool *value);
|
|
+uint32_t bsec_set_sp_lock(uint32_t otp);
|
|
+uint32_t bsec_read_sp_lock(uint32_t otp, bool *value);
|
|
+uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value);
|
|
+uint32_t bsec_otp_lock(uint32_t service);
|
|
|
|
-bool bsec_mode_is_closed_device(void);
|
|
uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word);
|
|
uint32_t bsec_check_nsec_access_rights(uint32_t otp);
|
|
|
|
diff --git a/include/drivers/st/nand.h b/include/drivers/st/nand.h
|
|
index f92511d..23d2dd2 100644
|
|
--- a/include/drivers/st/nand.h
|
|
+++ b/include/drivers/st/nand.h
|
|
@@ -120,8 +120,8 @@
|
|
#define FMC_THIZ 1
|
|
#define FMC_TIO 8000
|
|
#define FMC_TSYNC 3000
|
|
-#define FMC_PCR_TIMING_MASK 0xf
|
|
-#define FMC_PMEM_PATT_TIMING_MASK 0xff
|
|
+#define FMC_PCR_TIMING_MASK 0xFUL
|
|
+#define FMC_PMEM_PATT_TIMING_MASK 0xFFUL
|
|
|
|
/* Register: FMC_PCR */
|
|
#define FMC_PCR_TCLR(x) (((x) & 0xf) << 9)
|
|
@@ -140,28 +140,28 @@
|
|
#define FMC_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
|
|
|
|
/* NAND ONFI Default Value Mode 0 */
|
|
-#define FMC_TADL_MIN 200000
|
|
-#define FMC_TALH_MIN 20000
|
|
-#define FMC_TALS_MIN 50000
|
|
-#define FMC_TAR_MIN 25000
|
|
-#define FMC_TCH_MIN 20000
|
|
-#define FMC_TCLH_MIN 20000
|
|
-#define FMC_TCLR_MIN 20000
|
|
-#define FMC_TCLS_MIN 50000
|
|
-#define FMC_TCOH_MIN 0
|
|
-#define FMC_TCS_MIN 70000
|
|
-#define FMC_TDH_MIN 20000
|
|
-#define FMC_TDS_MIN 40000
|
|
-#define FMC_TRC_MIN 100000
|
|
-#define FMC_TREA_MAX 40000
|
|
-#define FMC_TREH_MIN 30000
|
|
-#define FMC_TRHW_MIN 200000
|
|
-#define FMC_TRP_MIN 50000
|
|
-#define FMC_TWB_MAX 200000
|
|
-#define FMC_TWC_MIN 100000
|
|
-#define FMC_TWH_MIN 30000
|
|
-#define FMC_TWHR_MIN 120000
|
|
-#define FMC_TWP_MIN 50000
|
|
+#define FMC_TADL_MIN 400000UL
|
|
+#define FMC_TALH_MIN 20000UL
|
|
+#define FMC_TALS_MIN 50000UL
|
|
+#define FMC_TAR_MIN 25000UL
|
|
+#define FMC_TCH_MIN 20000UL
|
|
+#define FMC_TCLH_MIN 20000UL
|
|
+#define FMC_TCLR_MIN 20000UL
|
|
+#define FMC_TCLS_MIN 50000UL
|
|
+#define FMC_TCOH_MIN 0UL
|
|
+#define FMC_TCS_MIN 70000UL
|
|
+#define FMC_TDH_MIN 20000UL
|
|
+#define FMC_TDS_MIN 40000UL
|
|
+#define FMC_TRC_MIN 100000UL
|
|
+#define FMC_TREA_MAX 40000UL
|
|
+#define FMC_TREH_MIN 30000UL
|
|
+#define FMC_TRHW_MIN 200000UL
|
|
+#define FMC_TRP_MIN 50000UL
|
|
+#define FMC_TWB_MAX 200000UL
|
|
+#define FMC_TWC_MIN 100000UL
|
|
+#define FMC_TWH_MIN 30000UL
|
|
+#define FMC_TWHR_MIN 120000UL
|
|
+#define FMC_TWP_MIN 50000UL
|
|
|
|
|
|
#define FMC_EBP2_MASK 16
|
|
diff --git a/include/drivers/st/stm32_iwdg.h b/include/drivers/st/stm32_iwdg.h
|
|
index b6d4769..06ad9d5 100644
|
|
--- a/include/drivers/st/stm32_iwdg.h
|
|
+++ b/include/drivers/st/stm32_iwdg.h
|
|
@@ -10,8 +10,8 @@
|
|
#include <stdint.h>
|
|
|
|
#define IWDG_HW_ENABLED BIT(0)
|
|
-#define IWDG_ENABLE_ON_STOP BIT(1)
|
|
-#define IWDG_ENABLE_ON_STANDBY BIT(2)
|
|
+#define IWDG_DISABLE_ON_STOP BIT(1)
|
|
+#define IWDG_DISABLE_ON_STANDBY BIT(2)
|
|
|
|
int stm32_iwdg_init(void);
|
|
void stm32_iwdg_refresh(uint32_t instance);
|
|
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
|
|
index b172659..7fa9c5d 100644
|
|
--- a/include/drivers/st/stm32_sdmmc2.h
|
|
+++ b/include/drivers/st/stm32_sdmmc2.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -21,6 +21,7 @@ struct stm32_sdmmc2_params {
|
|
unsigned int dirpol;
|
|
unsigned int clock_id;
|
|
unsigned int reset_id;
|
|
+ unsigned int max_freq;
|
|
bool use_dma;
|
|
};
|
|
|
|
diff --git a/include/drivers/st/stm32mp1_calib.h b/include/drivers/st/stm32mp1_calib.h
|
|
new file mode 100644
|
|
index 0000000..ef69cb4
|
|
--- /dev/null
|
|
+++ b/include/drivers/st/stm32mp1_calib.h
|
|
@@ -0,0 +1,20 @@
|
|
+/*
|
|
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef STM32MP1_CALIB_H
|
|
+#define STM32MP1_CALIB_H
|
|
+
|
|
+#include <stdbool.h>
|
|
+#include <stdint.h>
|
|
+
|
|
+bool stm32mp1_calib_get_wakeup(void);
|
|
+void stm32mp1_calib_set_wakeup(bool state);
|
|
+void stm32mp1_calib_it_handler(uint32_t id);
|
|
+int stm32mp1_calib_start_hsi_cal(void);
|
|
+int stm32mp1_calib_start_csi_cal(void);
|
|
+void stm32mp1_calib_init(void);
|
|
+
|
|
+#endif /* STM32MP1_CLK_H */
|
|
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
|
|
index 0c8583a..4f6930b 100644
|
|
--- a/include/drivers/st/stm32mp1_clk.h
|
|
+++ b/include/drivers/st/stm32mp1_clk.h
|
|
@@ -56,18 +56,11 @@ void stm32mp1_clk_rcc_regs_lock(void);
|
|
void stm32mp1_clk_rcc_regs_unlock(void);
|
|
|
|
unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit);
|
|
-
|
|
#if defined(IMAGE_BL32)
|
|
-bool stm32mp1_rcc_get_wakeup(void);
|
|
-void stm32mp1_rcc_set_wakeup(bool state);
|
|
-void stm32mp1_rcc_it_handler(uint32_t id);
|
|
-int stm32mp1_rcc_start_hsi_cal(void);
|
|
-int stm32mp1_rcc_start_csi_cal(void);
|
|
-void stm32mp1_cal_init(void);
|
|
+void stm32mp1_clk_mpu_suspend(void);
|
|
+void stm32mp1_clk_mpu_resume(void);
|
|
#endif
|
|
|
|
-void stm32mp1_rcc_init_late(void);
|
|
-
|
|
void stm32mp1_register_clock_parents_secure(unsigned long id);
|
|
|
|
void stm32mp1_update_earlyboot_clocks_state(void);
|
|
diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h
|
|
index 1a22824..9753d7c 100644
|
|
--- a/include/drivers/st/stm32mp1_pwr.h
|
|
+++ b/include/drivers/st/stm32mp1_pwr.h
|
|
@@ -26,6 +26,8 @@
|
|
|
|
#define PWR_CR2_BREN BIT(0)
|
|
#define PWR_CR2_RREN BIT(1)
|
|
+#define PWR_CR2_BRRDY BIT(16)
|
|
+#define PWR_CR2_RRRDY BIT(17)
|
|
|
|
#define PWR_CR3_VBE BIT(8)
|
|
#define PWR_CR3_VBRS BIT(9)
|
|
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
|
|
index 7e1b337..903a0d3 100644
|
|
--- a/include/drivers/st/stm32mp1_rcc.h
|
|
+++ b/include/drivers/st/stm32mp1_rcc.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -387,7 +387,8 @@
|
|
#define RCC_HSICFGR_HSITRIM_SHIFT 8
|
|
#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8)
|
|
#define RCC_HSICFGR_HSICAL_SHIFT 16
|
|
-#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16)
|
|
+#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16)
|
|
+#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25)
|
|
|
|
/* Fields of RCC_CSICFGR register */
|
|
#define RCC_CSICFGR_CSITRIM_SHIFT 8
|
|
@@ -470,6 +471,9 @@
|
|
#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5)
|
|
#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6)
|
|
|
|
+/* Values of RCC_AHB6RSTSETR register */
|
|
+#define RCC_AHB6RSTSETR_GPURST BIT(5)
|
|
+
|
|
/* Values of RCC_MP_IWDGFZSETR register */
|
|
#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0)
|
|
#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1)
|
|
@@ -477,4 +481,82 @@
|
|
/* Values of RCC_PWRLPDLYCR register */
|
|
#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0)
|
|
|
|
+/* RCC_I2C46CKSELR register fields */
|
|
+#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0
|
|
+
|
|
+/* RCC_SPI6CKSELR register fields */
|
|
+#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0
|
|
+
|
|
+/* RCC_UART1CKSELR register fields */
|
|
+#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_UART1CKSELR_UART1SRC_SHIFT 0
|
|
+
|
|
+/* RCC_RNG1CKSELR register fields */
|
|
+#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0)
|
|
+#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0
|
|
+
|
|
+/* RCC_STGENCKSELR register fields */
|
|
+#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0)
|
|
+#define RCC_STGENCKSELR_STGENSRC_SHIFT 0
|
|
+
|
|
+/* RCC_I2C12CKSELR register fields */
|
|
+#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0
|
|
+
|
|
+/* RCC_I2C35CKSELR register fields */
|
|
+#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0
|
|
+
|
|
+/* RCC_UART6CKSELR register fields */
|
|
+#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_UART6CKSELR_UART6SRC_SHIFT 0
|
|
+
|
|
+/* RCC_UART24CKSELR register fields */
|
|
+#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_UART24CKSELR_UART24SRC_SHIFT 0
|
|
+
|
|
+/* RCC_UART35CKSELR register fields */
|
|
+#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_UART35CKSELR_UART35SRC_SHIFT 0
|
|
+
|
|
+/* RCC_UART78CKSELR register fields */
|
|
+#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_UART78CKSELR_UART78SRC_SHIFT 0
|
|
+
|
|
+/* RCC_SDMMC12CKSELR register fields */
|
|
+#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0
|
|
+
|
|
+/* RCC_SDMMC3CKSELR register fields */
|
|
+#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0)
|
|
+#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0
|
|
+
|
|
+/* RCC_ETHCKSELR register fields */
|
|
+#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0)
|
|
+#define RCC_ETHCKSELR_ETHSRC_SHIFT 0
|
|
+
|
|
+/* RCC_QSPICKSELR register fields */
|
|
+#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0)
|
|
+#define RCC_QSPICKSELR_QSPISRC_SHIFT 0
|
|
+
|
|
+/* RCC_FMCCKSELR register fields */
|
|
+#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0)
|
|
+#define RCC_FMCCKSELR_FMCSRC_SHIFT 0
|
|
+
|
|
+/* RCC_ASSCKSELR register fields */
|
|
+#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0)
|
|
+#define RCC_ASSCKSELR_AXISSRC_SHIFT 0
|
|
+
|
|
+/* RCC_MSSCKSELR register fields */
|
|
+#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(2, 0)
|
|
+#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0
|
|
+
|
|
+/* RCC_USBCKSELR register fields */
|
|
+#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0)
|
|
+#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0
|
|
+#define RCC_USBCKSELR_USBOSRC_MASK BIT(4)
|
|
+#define RCC_USBCKSELR_USBOSRC_SHIFT 4
|
|
+
|
|
#endif /* STM32MP1_RCC_H */
|
|
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
|
|
index aa34b9c..f3ded20 100644
|
|
--- a/include/lib/aarch32/arch.h
|
|
+++ b/include/lib/aarch32/arch.h
|
|
@@ -460,8 +460,9 @@
|
|
#define HSTR p15, 4, c1, c1, 3
|
|
#define CNTHCTL p15, 4, c14, c1, 0
|
|
#define CNTKCTL p15, 0, c14, c1, 0
|
|
-#define CNTPTVAL p15, 0, c14, c2, 0
|
|
-#define CNTPCTL p15, 0, c14, c2, 1
|
|
+#define CNTP_TVAL p15, 0, c14, c2, 0
|
|
+#define CNTP_CTL p15, 0, c14, c2, 1
|
|
+#define CNTV_CTL p15, 0, c14, c3, 1
|
|
#define VPIDR p15, 4, c0, c0, 0
|
|
#define VMPIDR p15, 4, c0, c0, 5
|
|
#define ISR p15, 0, c12, c1, 0
|
|
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
|
|
index e48123c..9d56fc5 100644
|
|
--- a/include/lib/aarch32/arch_helpers.h
|
|
+++ b/include/lib/aarch32/arch_helpers.h
|
|
@@ -261,8 +261,9 @@ DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64)
|
|
DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64)
|
|
DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR)
|
|
DEFINE_COPROCR_RW_FUNCS(hstr, HSTR)
|
|
-DEFINE_COPROCR_RW_FUNCS(cntptval, CNTPTVAL)
|
|
-DEFINE_COPROCR_RW_FUNCS(cntpctl, CNTPCTL)
|
|
+DEFINE_COPROCR_RW_FUNCS(cntp_tval, CNTP_TVAL)
|
|
+DEFINE_COPROCR_RW_FUNCS(cntp_ctl, CNTP_CTL)
|
|
+DEFINE_COPROCR_RW_FUNCS(cntv_ctl, CNTV_CTL)
|
|
|
|
DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE)
|
|
DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE)
|
|
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
|
|
index 263c3ba..d483c18 100644
|
|
--- a/plat/st/common/bl2_io_storage.c
|
|
+++ b/plat/st/common/bl2_io_storage.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -159,7 +159,7 @@ enum {
|
|
IMG_IDX_NUM
|
|
};
|
|
|
|
-static struct stm32image_device_info stm32image_dev_info_spec = {
|
|
+static struct stm32image_device_info stm32image_dev_info_spec __unused = {
|
|
.lba_size = MMC_BLOCK_SIZE,
|
|
.part_info[IMG_IDX_BL33] = {
|
|
.name = BL33_IMAGE_NAME,
|
|
@@ -186,7 +186,7 @@ static io_block_spec_t stm32image_block_spec = {
|
|
.length = 0,
|
|
};
|
|
|
|
-static const io_dev_connector_t *stm32image_dev_con;
|
|
+static const io_dev_connector_t *stm32image_dev_con __unused;
|
|
|
|
static int open_dummy(const uintptr_t spec);
|
|
static int open_image(const uintptr_t spec);
|
|
@@ -305,7 +305,7 @@ static void print_boot_device(boot_api_context_t *boot_context)
|
|
}
|
|
}
|
|
|
|
-#if STM32MP_EMMC || STM32MP_SDMMC
|
|
+#if STM32MP_SDMMC
|
|
static void print_bootrom_sd_status(boot_api_context_t *boot_context)
|
|
{
|
|
if (boot_context->sd_err_internal_timeout_cnt != 0U) {
|
|
@@ -338,7 +338,9 @@ static void print_bootrom_sd_status(boot_api_context_t *boot_context)
|
|
boot_context->sd_overall_retry_cnt);
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
+#if STM32MP_EMMC
|
|
static void print_bootrom_emmc_status(boot_api_context_t *boot_context)
|
|
{
|
|
INFO("BootROM: %d (0x%x) bytes copied from eMMC\n",
|
|
@@ -399,342 +401,344 @@ static void print_bootrom_emmc_status(boot_api_context_t *boot_context)
|
|
}
|
|
#endif
|
|
|
|
-
|
|
-void stm32mp_io_setup(void)
|
|
+#if STM32MP_EMMC || STM32MP_SDMMC
|
|
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
|
|
+ uint16_t boot_interface_instance)
|
|
{
|
|
int io_result __unused;
|
|
uint8_t idx;
|
|
struct stm32image_part_info *part;
|
|
-#if STM32MP_UART_PROGRAMMER
|
|
- uintptr_t uart_addr;
|
|
-#endif
|
|
-#if STM32MP_SDMMC || STM32MP_EMMC
|
|
struct stm32_sdmmc2_params params;
|
|
struct mmc_device_info device_info;
|
|
- uintptr_t mmc_default_instance;
|
|
const partition_entry_t *entry;
|
|
-#endif
|
|
-#ifdef STM32MP_USB
|
|
- struct usb_ctx *usb_context;
|
|
-#endif
|
|
- boot_api_context_t *boot_context =
|
|
- (boot_api_context_t *)stm32mp_get_boot_ctx_address();
|
|
|
|
- print_boot_device(boot_context);
|
|
+ zeromem(&device_info, sizeof(struct mmc_device_info));
|
|
+ zeromem(¶ms, sizeof(struct stm32_sdmmc2_params));
|
|
|
|
- if ((boot_context->boot_partition_used_toboot == 1U) ||
|
|
- (boot_context->boot_partition_used_toboot == 2U)) {
|
|
- INFO("Boot used partition fsbl%d\n",
|
|
- boot_context->boot_partition_used_toboot);
|
|
- }
|
|
+ device_info.mmc_dev_type = mmc_dev_type;
|
|
|
|
- io_result = register_io_dev_dummy(&dummy_dev_con);
|
|
- assert(io_result == 0);
|
|
+ switch (boot_interface_instance) {
|
|
+ case 1:
|
|
+ params.reg_base = STM32MP_SDMMC1_BASE;
|
|
+ break;
|
|
+ case 2:
|
|
+ params.reg_base = STM32MP_SDMMC2_BASE;
|
|
+ break;
|
|
+ case 3:
|
|
+ params.reg_base = STM32MP_SDMMC3_BASE;
|
|
+ break;
|
|
+ default:
|
|
+ WARN("SDMMC instance not found, using default\n");
|
|
+ if (mmc_dev_type == MMC_IS_SD) {
|
|
+ params.reg_base = STM32MP_SDMMC1_BASE;
|
|
+ } else {
|
|
+ params.reg_base = STM32MP_SDMMC2_BASE;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
|
|
- io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
|
|
- &dummy_dev_handle);
|
|
- assert(io_result == 0);
|
|
+ params.device_info = &device_info;
|
|
+ if (stm32_sdmmc2_mmc_init(¶ms) != 0) {
|
|
+ ERROR("SDMMC%u init failed\n", boot_interface_instance);
|
|
+ panic();
|
|
+ }
|
|
|
|
- switch (boot_context->boot_interface_selected) {
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
|
|
- dmbsy();
|
|
+ /* Open MMC as a block device to read GPT table */
|
|
+ io_result = register_io_dev_block(&mmc_dev_con);
|
|
+ if (io_result != 0) {
|
|
+ panic();
|
|
+ }
|
|
|
|
-#if STM32MP_EMMC || STM32MP_SDMMC
|
|
- memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params));
|
|
+ io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
|
|
+ &storage_dev_handle);
|
|
+ assert(io_result == 0);
|
|
|
|
- if (boot_context->boot_interface_selected ==
|
|
- BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) {
|
|
- device_info.mmc_dev_type = MMC_IS_EMMC;
|
|
- print_bootrom_emmc_status(boot_context);
|
|
-#if STM32MP_EMMC
|
|
- mmc_default_instance = STM32MP_SDMMC2_BASE;
|
|
-#else
|
|
- ERROR("MMC driver is not enabled\n");
|
|
- panic();
|
|
-#endif
|
|
- } else {
|
|
- device_info.mmc_dev_type = MMC_IS_SD;
|
|
- print_bootrom_sd_status(boot_context);
|
|
-#if STM32MP_SDMMC
|
|
- mmc_default_instance = STM32MP_SDMMC1_BASE;
|
|
-#else
|
|
- ERROR("MMC driver is not enabled\n");
|
|
- panic();
|
|
-#endif
|
|
- }
|
|
+ partition_init(GPT_IMAGE_ID);
|
|
|
|
- switch (boot_context->boot_interface_instance) {
|
|
- case 1:
|
|
- params.reg_base = STM32MP_SDMMC1_BASE;
|
|
- break;
|
|
- case 2:
|
|
- params.reg_base = STM32MP_SDMMC2_BASE;
|
|
- break;
|
|
- case 3:
|
|
- params.reg_base = STM32MP_SDMMC3_BASE;
|
|
- break;
|
|
- default:
|
|
- WARN("SDMMC instance not found, using default\n");
|
|
- params.reg_base = mmc_default_instance;
|
|
- break;
|
|
- }
|
|
+ io_result = io_dev_close(storage_dev_handle);
|
|
+ assert(io_result == 0);
|
|
|
|
- params.device_info = &device_info;
|
|
- if (stm32_sdmmc2_mmc_init(¶ms) != 0) {
|
|
- ERROR("SDMMC%u init failed\n",
|
|
- boot_context->boot_interface_instance);
|
|
- panic();
|
|
- }
|
|
+ stm32image_dev_info_spec.device_size =
|
|
+ stm32_sdmmc2_mmc_get_device_size();
|
|
|
|
- /* Open MMC as a block device to read GPT table */
|
|
- io_result = register_io_dev_block(&mmc_dev_con);
|
|
- if (io_result != 0) {
|
|
+ for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ entry = get_partition_entry(part->name);
|
|
+ if (entry == NULL) {
|
|
+ ERROR("Partition %s not found\n", part->name);
|
|
panic();
|
|
}
|
|
|
|
- io_result = io_dev_open(mmc_dev_con,
|
|
- (uintptr_t)&mmc_block_dev_spec,
|
|
- &storage_dev_handle);
|
|
- assert(io_result == 0);
|
|
-
|
|
- partition_init(GPT_IMAGE_ID);
|
|
-
|
|
- io_result = io_dev_close(storage_dev_handle);
|
|
- assert(io_result == 0);
|
|
+ part->part_offset = entry->start;
|
|
+ part->bkp_offset = 0U;
|
|
+ }
|
|
|
|
- stm32image_dev_info_spec.device_size =
|
|
- stm32_sdmmc2_mmc_get_device_size();
|
|
+ /*
|
|
+ * Re-open MMC with io_mmc, for better perfs compared to
|
|
+ * io_block.
|
|
+ */
|
|
+ io_result = register_io_dev_mmc(&mmc_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- entry = get_partition_entry(part->name);
|
|
- if (entry == NULL) {
|
|
- ERROR("Partition %s not found\n",
|
|
- part->name);
|
|
- panic();
|
|
- }
|
|
+ io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
|
|
+ assert(io_result == 0);
|
|
|
|
- part->part_offset = entry->start;
|
|
- part->bkp_offset = 0U;
|
|
- }
|
|
+ io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- /*
|
|
- * Re-open MMC with io_mmc, for better perfs compared to
|
|
- * io_block.
|
|
- */
|
|
- io_result = register_io_dev_mmc(&mmc_dev_con);
|
|
- assert(io_result == 0);
|
|
-
|
|
- io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
|
|
- assert(io_result == 0);
|
|
-
|
|
- io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
- assert(io_result == 0);
|
|
-
|
|
- io_result = io_dev_open(stm32image_dev_con,
|
|
- (uintptr_t)&stm32image_dev_info_spec,
|
|
- &image_dev_handle);
|
|
- assert(io_result == 0);
|
|
-#else /* STM32MP_EMMC || STM32MP_SDMMC */
|
|
- ERROR("EMMC or SDMMC driver not enabled\n");
|
|
- panic();
|
|
-#endif /* STM32MP_EMMC || STM32MP_SDMMC */
|
|
- break;
|
|
+ io_result = io_dev_open(stm32image_dev_con,
|
|
+ (uintptr_t)&stm32image_dev_info_spec,
|
|
+ &image_dev_handle);
|
|
+ assert(io_result == 0);
|
|
+}
|
|
+#endif
|
|
|
|
#if STM32MP1_QSPI_NOR
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
|
|
- dmbsy();
|
|
+static void boot_qspi_nor(boot_api_context_t *boot_context)
|
|
+{
|
|
+ int io_result __unused;
|
|
+ uint8_t idx;
|
|
+ struct stm32image_part_info *part;
|
|
|
|
- io_result = register_io_dev_qspi(&qspi_dev_con);
|
|
+ io_result = register_io_dev_qspi(&qspi_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- assert(io_result == 0);
|
|
- switch (boot_context->boot_interface_instance) {
|
|
- case 1:
|
|
- qspi_dev_spec.instance =
|
|
- (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE;
|
|
- break;
|
|
- default:
|
|
- WARN("NOR instance not found, using default\n");
|
|
- qspi_dev_spec.instance =
|
|
- (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE;
|
|
- break;
|
|
- }
|
|
- qspi_dev_spec.is_dual = boot_context->nor_isdual;
|
|
+ if (boot_context->boot_interface_instance != 1U) {
|
|
+ WARN("NOR instance not found, using default\n");
|
|
+ }
|
|
|
|
- /* Open connections to devices and cache the handles */
|
|
- io_result = io_dev_open(qspi_dev_con,
|
|
- (uintptr_t)&qspi_dev_spec,
|
|
- &storage_dev_handle);
|
|
- assert(io_result == 0);
|
|
+ qspi_dev_spec.instance = (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE;
|
|
+ qspi_dev_spec.is_dual = boot_context->nor_isdual;
|
|
|
|
- stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE;
|
|
- stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE;
|
|
+ /* Open connections to devices */
|
|
+ io_result = io_dev_open(qspi_dev_con,
|
|
+ (uintptr_t)&qspi_dev_spec,
|
|
+ &storage_dev_handle);
|
|
+ assert(io_result == 0);
|
|
|
|
- idx = IMG_IDX_BL33;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NOR_BL33_OFFSET;
|
|
- part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
+ stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE;
|
|
+ stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE;
|
|
|
|
-#ifdef AARCH32_SP_OPTEE
|
|
- idx = IMG_IDX_OPTEE_HEADER;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NOR_TEEH_OFFSET;
|
|
- part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
-
|
|
- idx = IMG_IDX_OPTEE_PAGED;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NOR_TEED_OFFSET;
|
|
- part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
+ idx = IMG_IDX_BL33;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NOR_BL33_OFFSET;
|
|
+ part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
|
|
- idx = IMG_IDX_OPTEE_PAGER;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NOR_TEEX_OFFSET;
|
|
- part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
+#ifdef AARCH32_SP_OPTEE
|
|
+ idx = IMG_IDX_OPTEE_HEADER;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NOR_TEEH_OFFSET;
|
|
+ part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
+
|
|
+ idx = IMG_IDX_OPTEE_PAGED;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NOR_TEED_OFFSET;
|
|
+ part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
+
|
|
+ idx = IMG_IDX_OPTEE_PAGER;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NOR_TEEX_OFFSET;
|
|
+ part->bkp_offset = QSPI_NOR_BLK_SIZE;
|
|
#endif
|
|
|
|
- io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
- assert(io_result == 0);
|
|
+ io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- io_result = io_dev_open(stm32image_dev_con,
|
|
- (uintptr_t)&stm32image_dev_info_spec,
|
|
- &image_dev_handle);
|
|
- assert(io_result == 0);
|
|
- break;
|
|
+ io_result = io_dev_open(stm32image_dev_con,
|
|
+ (uintptr_t)&stm32image_dev_info_spec,
|
|
+ &image_dev_handle);
|
|
+ assert(io_result == 0);
|
|
+}
|
|
#endif
|
|
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
|
|
-
|
|
#if STM32MP_FMC_NAND
|
|
- dmbsy();
|
|
-
|
|
- /* Register the IO devices on this platform */
|
|
- io_result = register_io_dev_nand(&nand_dev_con);
|
|
- assert(io_result == 0);
|
|
-
|
|
- nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE;
|
|
- nand_dev_spec.Info.PageSize = boot_context->nand_page_size;
|
|
- nand_dev_spec.Info.BlockSize = boot_context->nand_block_size;
|
|
- nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb;
|
|
- nand_dev_spec.Info.BusWidth = boot_context->nand_data_width;
|
|
- nand_dev_spec.Info.ECCcorrectability =
|
|
- boot_context->nand_ecc_bits;
|
|
-
|
|
- /* Open connections to devices and cache the handles */
|
|
- io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
|
|
- &storage_dev_handle);
|
|
- assert(io_result == 0);
|
|
-
|
|
- stm32image_dev_info_spec.device_size =
|
|
- nand_dev_spec.Info.PageSize *
|
|
- nand_dev_spec.Info.BlockSize *
|
|
- nand_dev_spec.Info.BlockNb;
|
|
- stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR;
|
|
-
|
|
- idx = IMG_IDX_BL33;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NAND_BL33_OFFSET;
|
|
- part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
- nand_dev_spec.Info.BlockSize;
|
|
+static void boot_fmc_nand(boot_api_context_t *boot_context)
|
|
+{
|
|
+ int io_result __unused;
|
|
+ uint8_t idx;
|
|
+ struct stm32image_part_info *part;
|
|
|
|
-#ifdef AARCH32_SP_OPTEE
|
|
- idx = IMG_IDX_OPTEE_HEADER;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NAND_TEEH_OFFSET;
|
|
- part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
- nand_dev_spec.Info.BlockSize;
|
|
+ /* Register the IO devices on this platform */
|
|
+ io_result = register_io_dev_nand(&nand_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- idx = IMG_IDX_OPTEE_PAGED;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NAND_TEED_OFFSET;
|
|
- part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
- nand_dev_spec.Info.BlockSize;
|
|
+ nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE;
|
|
+ nand_dev_spec.Info.PageSize = boot_context->nand_page_size;
|
|
+ nand_dev_spec.Info.BlockSize = boot_context->nand_block_size;
|
|
+ nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb;
|
|
+ nand_dev_spec.Info.BusWidth = boot_context->nand_data_width;
|
|
+ nand_dev_spec.Info.ECCcorrectability =
|
|
+ boot_context->nand_ecc_bits;
|
|
+
|
|
+ /* Open connections to devices */
|
|
+ io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
|
|
+ &storage_dev_handle);
|
|
+ assert(io_result == 0);
|
|
|
|
- idx = IMG_IDX_OPTEE_PAGER;
|
|
- part = &stm32image_dev_info_spec.part_info[idx];
|
|
- part->part_offset = STM32MP_NAND_TEEX_OFFSET;
|
|
- part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
- nand_dev_spec.Info.BlockSize;
|
|
+ stm32image_dev_info_spec.device_size =
|
|
+ nand_dev_spec.Info.PageSize *
|
|
+ nand_dev_spec.Info.BlockSize *
|
|
+ nand_dev_spec.Info.BlockNb;
|
|
+ stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR;
|
|
+
|
|
+ idx = IMG_IDX_BL33;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NAND_BL33_OFFSET;
|
|
+ part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
+ nand_dev_spec.Info.BlockSize;
|
|
+
|
|
+#ifdef AARCH32_SP_OPTEE
|
|
+ idx = IMG_IDX_OPTEE_HEADER;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NAND_TEEH_OFFSET;
|
|
+ part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
+ nand_dev_spec.Info.BlockSize;
|
|
+
|
|
+ idx = IMG_IDX_OPTEE_PAGED;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NAND_TEED_OFFSET;
|
|
+ part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
+ nand_dev_spec.Info.BlockSize;
|
|
+
|
|
+ idx = IMG_IDX_OPTEE_PAGER;
|
|
+ part = &stm32image_dev_info_spec.part_info[idx];
|
|
+ part->part_offset = STM32MP_NAND_TEEX_OFFSET;
|
|
+ part->bkp_offset = nand_dev_spec.Info.PageSize *
|
|
+ nand_dev_spec.Info.BlockSize;
|
|
#endif
|
|
|
|
- io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
- assert(io_result == 0);
|
|
+ io_result = register_io_dev_stm32image(&stm32image_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- io_result = io_dev_open(stm32image_dev_con,
|
|
- (uintptr_t)&stm32image_dev_info_spec,
|
|
- &image_dev_handle);
|
|
- assert(io_result == 0);
|
|
-#else
|
|
- ERROR("FMC NAND driver is not enabled\n");
|
|
- panic();
|
|
+ io_result = io_dev_open(stm32image_dev_con,
|
|
+ (uintptr_t)&stm32image_dev_info_spec,
|
|
+ &image_dev_handle);
|
|
+ assert(io_result == 0);
|
|
+}
|
|
#endif
|
|
- break;
|
|
|
|
#if STM32MP_UART_PROGRAMMER
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
|
|
+static void flash_uart(uint16_t boot_interface_instance)
|
|
+{
|
|
+ int io_result __unused;
|
|
+ uintptr_t uart_addr;
|
|
|
|
- /* Register the IO devices on this platform */
|
|
- io_result = register_io_dev_uart(&uart_dev_con);
|
|
- assert(io_result == 0);
|
|
+ /* Register the IO devices on this platform */
|
|
+ io_result = register_io_dev_uart(&uart_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- uart_programmer.Init.WordLength = UART_WORDLENGTH_9B;
|
|
- uart_programmer.Init.Parity = UART_PARITY_EVEN;
|
|
- uart_addr =
|
|
- get_uart_address(boot_context->boot_interface_instance);
|
|
+ uart_programmer.Init.WordLength = UART_WORDLENGTH_9B;
|
|
+ uart_programmer.Init.Parity = UART_PARITY_EVEN;
|
|
+ uart_addr = get_uart_address(boot_interface_instance);
|
|
|
|
- if (uart_addr) {
|
|
- uart_programmer.Instance = (USART_TypeDef *)uart_addr;
|
|
- } else {
|
|
- WARN("UART instance not found, using default\n");
|
|
- uart_programmer.Instance = (USART_TypeDef *)USART2_BASE;
|
|
- }
|
|
+ if (uart_addr != 0U) {
|
|
+ uart_programmer.Instance = (USART_TypeDef *)uart_addr;
|
|
+ } else {
|
|
+ WARN("UART instance not found, using default\n");
|
|
+ uart_programmer.Instance = (USART_TypeDef *)USART2_BASE;
|
|
+ }
|
|
|
|
- /* Open connections to devices and cache the handles */
|
|
- io_result = io_dev_open(uart_dev_con,
|
|
- (uintptr_t)&uart_programmer,
|
|
- &image_dev_handle);
|
|
- assert(!io_result);
|
|
- break;
|
|
+ /* Open connections to devices */
|
|
+ io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer,
|
|
+ &image_dev_handle);
|
|
+ assert(!io_result);
|
|
+}
|
|
#endif
|
|
|
|
#ifdef STM32MP_USB
|
|
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
|
|
- usb_context = (struct usb_ctx *)boot_context->usb_context;
|
|
+static void flash_usb(struct usb_ctx *usb_context)
|
|
+{
|
|
+ int io_result __unused;
|
|
|
|
- pcd_handle.in_ep[0].maxpacket = 0x40;
|
|
- pcd_handle.out_ep[0].maxpacket = 0x40;
|
|
+ pcd_handle.in_ep[0].maxpacket = 0x40;
|
|
+ pcd_handle.out_ep[0].maxpacket = 0x40;
|
|
|
|
- pcd_handle.state = HAL_PCD_STATE_READY;
|
|
+ pcd_handle.state = HAL_PCD_STATE_READY;
|
|
|
|
- usb_core_handle.data = &pcd_handle;
|
|
+ usb_core_handle.data = &pcd_handle;
|
|
|
|
- usb_dwc2_init_driver(&usb_core_handle,
|
|
- (uint32_t *)USB_OTG_BASE);
|
|
+ usb_dwc2_init_driver(&usb_core_handle,
|
|
+ (uint32_t *)USB_OTG_BASE);
|
|
|
|
- usb_dfu_register_callback(&usb_core_handle);
|
|
+ usb_dfu_register_callback(&usb_core_handle);
|
|
|
|
- stm32mp_usb_init_desc(&usb_core_handle);
|
|
+ stm32mp_usb_init_desc(&usb_core_handle);
|
|
|
|
- usb_core_handle.ep_in[0].maxpacket = 0x40;
|
|
- usb_core_handle.ep_out[0].maxpacket = 0x40;
|
|
+ usb_core_handle.ep_in[0].maxpacket = 0x40;
|
|
+ usb_core_handle.ep_out[0].maxpacket = 0x40;
|
|
|
|
- usb_core_handle.ep0_state =
|
|
- usb_context->pusbd_device_ctx->ep0_state;
|
|
- usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
|
|
+ usb_core_handle.ep0_state =
|
|
+ usb_context->pusbd_device_ctx->ep0_state;
|
|
+ usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
|
|
|
|
- usb_core_handle.class_data = &usb_dfu_handle;
|
|
- usb_dfu_handle.dev_state = DFU_STATE_IDLE;
|
|
+ usb_core_handle.class_data = &usb_dfu_handle;
|
|
+ usb_dfu_handle.dev_state = DFU_STATE_IDLE;
|
|
|
|
- /* Register the IO devices on this platform */
|
|
- io_result = register_io_dev_usb(&usb_dev_con);
|
|
- assert(io_result == 0);
|
|
+ /* Register the IO devices on this platform */
|
|
+ io_result = register_io_dev_usb(&usb_dev_con);
|
|
+ assert(io_result == 0);
|
|
|
|
- /* Open connections to devices and cache the handles */
|
|
- io_result = io_dev_open(usb_dev_con,
|
|
- (uintptr_t)&usb_core_handle,
|
|
- &image_dev_handle);
|
|
+ /* Open connections to devices */
|
|
+ io_result = io_dev_open(usb_dev_con,
|
|
+ (uintptr_t)&usb_core_handle,
|
|
+ &image_dev_handle);
|
|
|
|
- assert(io_result == 0);
|
|
+ assert(io_result == 0);
|
|
+}
|
|
+#endif
|
|
+
|
|
+void stm32mp_io_setup(void)
|
|
+{
|
|
+ int io_result __unused;
|
|
+ boot_api_context_t *boot_context =
|
|
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
|
|
+
|
|
+ print_boot_device(boot_context);
|
|
+
|
|
+ if ((boot_context->boot_partition_used_toboot == 1U) ||
|
|
+ (boot_context->boot_partition_used_toboot == 2U)) {
|
|
+ INFO("Boot used partition fsbl%d\n",
|
|
+ boot_context->boot_partition_used_toboot);
|
|
+ }
|
|
+
|
|
+ io_result = register_io_dev_dummy(&dummy_dev_con);
|
|
+ assert(io_result == 0);
|
|
+
|
|
+ io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
|
|
+ &dummy_dev_handle);
|
|
+ assert(io_result == 0);
|
|
+
|
|
+ switch (boot_context->boot_interface_selected) {
|
|
+#if STM32MP_SDMMC
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
|
|
+ print_bootrom_sd_status(boot_context);
|
|
+ boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
|
|
+ break;
|
|
+#endif
|
|
+#if STM32MP_EMMC
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
|
|
+ print_bootrom_emmc_status(boot_context);
|
|
+ boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
|
|
+ break;
|
|
+#endif
|
|
+#if STM32MP1_QSPI_NOR
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
|
|
+ boot_qspi_nor(boot_context);
|
|
+ break;
|
|
+#endif
|
|
+#if STM32MP_FMC_NAND
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
|
|
+ boot_fmc_nand(boot_context);
|
|
+ break;
|
|
+#endif
|
|
+#if STM32MP_UART_PROGRAMMER
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
|
|
+ flash_uart(boot_context->boot_interface_instance);
|
|
+ break;
|
|
+#endif
|
|
+#ifdef STM32MP_USB
|
|
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
|
|
+ flash_usb((struct usb_ctx *)boot_context->usb_context);
|
|
break;
|
|
#endif
|
|
#ifdef STM32MP1_QSPI_NAND
|
|
diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h
|
|
index 70f8202..b5a2bf9 100644
|
|
--- a/plat/st/common/include/stm32mp_auth.h
|
|
+++ b/plat/st/common/include/stm32mp_auth.h
|
|
@@ -9,6 +9,14 @@
|
|
|
|
#include <boot_api.h>
|
|
|
|
+struct auth_ops {
|
|
+ uint32_t (*check_key)(uint8_t *p_pub_key_in,
|
|
+ uint8_t *p_pub_key_out);
|
|
+ uint32_t (*verify_signature)(uint8_t *p_hash_in, uint8_t *p_pub_key_in,
|
|
+ uint8_t *p_signature, uint32_t ecc_algo);
|
|
+};
|
|
+
|
|
+void stm32mp_init_auth(struct auth_ops *init_ptr);
|
|
int check_header(boot_api_image_header_t *header, uintptr_t buffer);
|
|
int check_authentication(boot_api_image_header_t *header, uintptr_t buffer);
|
|
|
|
diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c
|
|
index 773c95e..aa784cf 100644
|
|
--- a/plat/st/common/stm32mp_auth.c
|
|
+++ b/plat/st/common/stm32mp_auth.c
|
|
@@ -12,6 +12,19 @@
|
|
#include <stm32mp_auth.h>
|
|
#include <stm32mp_common.h>
|
|
|
|
+static const struct auth_ops *stm32mp_auth_ops;
|
|
+
|
|
+void stm32mp_init_auth(struct auth_ops *init_ptr)
|
|
+{
|
|
+ if ((init_ptr == NULL) ||
|
|
+ (init_ptr->check_key == NULL) ||
|
|
+ (init_ptr->verify_signature == NULL)) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ stm32mp_auth_ops = init_ptr;
|
|
+}
|
|
+
|
|
int check_header(boot_api_image_header_t *header, uintptr_t buffer)
|
|
{
|
|
uint32_t i;
|
|
@@ -55,8 +68,6 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer)
|
|
uint32_t header_skip_cksum = sizeof(header->magic) +
|
|
sizeof(header->image_signature) +
|
|
sizeof(header->payload_checksum);
|
|
- boot_api_context_t *boot_context =
|
|
- (boot_api_context_t *)stm32mp_get_boot_ctx_address();
|
|
|
|
uret = bsec_read_otp(&sec_closed, BOOT_API_OTP_MODE_WORD_NB);
|
|
if (uret != 0) {
|
|
@@ -74,8 +85,7 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer)
|
|
}
|
|
|
|
/* Check Public Key */
|
|
- if (boot_context->p_bootrom_ext_service_ecdsa_check_key
|
|
- (header->ecc_pubk, NULL) != STD_OK) {
|
|
+ if (stm32mp_auth_ops->check_key(header->ecc_pubk, NULL) != STD_OK) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -110,8 +120,9 @@ int check_authentication(boot_api_image_header_t *header, uintptr_t buffer)
|
|
}
|
|
|
|
/* Verify signature */
|
|
- if (boot_context->p_bootrom_ext_service_ecdsa_verify_signature
|
|
- (image_hash, header->ecc_pubk, header->image_signature,
|
|
+ if (stm32mp_auth_ops->verify_signature
|
|
+ (image_hash, header->ecc_pubk,
|
|
+ header->image_signature,
|
|
header->ecc_algo_type) != STD_OK) {
|
|
return -EINVAL;
|
|
}
|
|
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
|
|
index 48529cb..2f9951b 100644
|
|
--- a/plat/st/common/stm32mp_dt.c
|
|
+++ b/plat/st/common/stm32mp_dt.c
|
|
@@ -106,12 +106,9 @@ int fdt_get_interrupt(int node, const fdt32_t **array, int *len, bool *extended)
|
|
}
|
|
break;
|
|
|
|
- case DT_SHARED:
|
|
+ default:
|
|
*array = fdt_getprop(fdt, node, "secure-interrupts", len);
|
|
break;
|
|
-
|
|
- default:
|
|
- return -FDT_ERR_NOTFOUND;
|
|
}
|
|
|
|
if (*array == NULL) {
|
|
@@ -429,7 +426,7 @@ uintptr_t dt_get_pwr_base(void)
|
|
******************************************************************************/
|
|
uint32_t dt_get_pwr_vdd_voltage(void)
|
|
{
|
|
- int node;
|
|
+ int node, pwr_regulators_node;
|
|
const fdt32_t *cuint;
|
|
|
|
node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
|
|
@@ -438,7 +435,13 @@ uint32_t dt_get_pwr_vdd_voltage(void)
|
|
return 0;
|
|
}
|
|
|
|
- cuint = fdt_getprop(fdt, node, "pwr-supply", NULL);
|
|
+ pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
|
|
+ if (node < 0) {
|
|
+ INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
|
|
if (cuint == NULL) {
|
|
return 0;
|
|
}
|
|
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
|
|
index cd5d5b3..1a2e2d6 100644
|
|
--- a/plat/st/stm32mp1/bl2_plat_setup.c
|
|
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
|
|
@@ -22,6 +22,7 @@
|
|
#include <stm32_console.h>
|
|
#include <stm32_gpio.h>
|
|
#include <stm32_iwdg.h>
|
|
+#include <stm32mp_auth.h>
|
|
#include <stm32mp_common.h>
|
|
#include <stm32mp_dt.h>
|
|
#include <stm32mp_pmic.h>
|
|
@@ -42,6 +43,7 @@
|
|
|
|
static struct console_stm32 console;
|
|
static enum boot_device_e boot_device = BOOT_DEVICE_BOARD;
|
|
+static struct auth_ops stm32mp_auth_ops;
|
|
|
|
static void print_reset_reason(void)
|
|
{
|
|
@@ -280,13 +282,17 @@ void bl2_el3_plat_arch_setup(void)
|
|
RCC_PWRLPDLYCR_PWRLP_DLY_MASK,
|
|
PWRLP_TEMPO_5_HSI);
|
|
|
|
- /* Keep retention and backup ram content in standby */
|
|
- mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN);
|
|
- mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_RREN);
|
|
+ /* Disable retention and backup RAM content after standby */
|
|
+ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN);
|
|
|
|
/* Disable MCKPROT */
|
|
mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
|
|
|
|
+ /* Enable BKP Register protection */
|
|
+ mmio_write_32(TAMP_SMCR,
|
|
+ TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_WDPROT_SHIFT |
|
|
+ TAMP_BKP_SEC_NUMBER << TAMP_BKP_SEC_RWDPROT_SHIFT);
|
|
+
|
|
if ((boot_context->boot_action !=
|
|
BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY) &&
|
|
(boot_context->boot_action !=
|
|
@@ -323,6 +329,8 @@ void bl2_el3_plat_arch_setup(void)
|
|
panic();
|
|
}
|
|
|
|
+ stm32mp1_syscfg_init();
|
|
+
|
|
result = dt_get_stdout_uart_info(&dt_uart_info);
|
|
|
|
if ((result <= 0) ||
|
|
@@ -399,13 +407,18 @@ skip_console_init:
|
|
ERROR("Cannot save boot interface\n");
|
|
}
|
|
|
|
+ stm32mp_auth_ops.check_key =
|
|
+ boot_context->p_bootrom_ext_service_ecdsa_check_key;
|
|
+ stm32mp_auth_ops.verify_signature =
|
|
+ boot_context->p_bootrom_ext_service_ecdsa_verify_signature;
|
|
+
|
|
+ stm32mp_init_auth(&stm32mp_auth_ops);
|
|
+
|
|
stm32mp1_arch_security_setup();
|
|
|
|
print_reset_reason();
|
|
|
|
stm32mp_io_setup();
|
|
-
|
|
- stm32mp1_syscfg_init();
|
|
}
|
|
|
|
#if defined(AARCH32_SP_OPTEE)
|
|
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
|
|
index cc6c9e7..0983575 100644
|
|
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
|
|
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
|
|
@@ -18,6 +18,9 @@ enum boot_device_e {
|
|
|
|
void configure_mmu(void);
|
|
|
|
+void stm32mp_mask_timer(void);
|
|
+void __dead2 stm32mp_wait_cpu_reset(void);
|
|
+
|
|
void stm32mp1_arch_security_setup(void);
|
|
void stm32mp1_security_setup(void);
|
|
void stm32mp1_sp_min_security_setup(void);
|
|
@@ -34,5 +37,7 @@ void stm32mp1_gic_init(void);
|
|
enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode);
|
|
|
|
void stm32mp1_syscfg_init(void);
|
|
+void stm32mp1_syscfg_enable_io_compensation(void);
|
|
+void stm32mp1_syscfg_disable_io_compensation(void);
|
|
|
|
#endif /* STM32MP1_PRIVATE_H */
|
|
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
|
|
index 06594f0..91bb1ca 100644
|
|
--- a/plat/st/stm32mp1/platform.mk
|
|
+++ b/plat/st/stm32mp1/platform.mk
|
|
@@ -10,6 +10,10 @@ BL2_AT_EL3 := 1
|
|
USE_COHERENT_MEM := 0
|
|
MULTI_CONSOLE_API := 1
|
|
|
|
+# Add specific ST version
|
|
+ST_VERSION := r1.5
|
|
+VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}-${ST_VERSION}(${BUILD_TYPE}):${BUILD_STRING}
|
|
+
|
|
# Please don't increment this value without good understanding of
|
|
# the monotonic counter
|
|
STM32_TF_VERSION ?= 0
|
|
@@ -42,6 +46,25 @@ PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1)))
|
|
endif
|
|
$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
|
|
|
|
+STM32MP_BOOT_ONLY ?= 0
|
|
+STM32MP_FLASHLOADER_ONLY ?= 0
|
|
+
|
|
+ifeq (${STM32MP_BOOT_ONLY},1)
|
|
+ifeq (${STM32MP_FLASHLOADER_ONLY},1)
|
|
+$(error "You cannot choose both STM32MP_BOOT_ONLY and STM32MP_FLASHLOADER_ONLY")
|
|
+endif
|
|
+STM32MP_BOOT_DEVICES = 1
|
|
+STM32MP_FLASHLOADER = 0
|
|
+endif
|
|
+ifeq (${STM32MP_FLASHLOADER_ONLY},1)
|
|
+STM32MP_BOOT_DEVICES = 0
|
|
+STM32MP_FLASHLOADER = 1
|
|
+endif
|
|
+
|
|
+STM32MP_BOOT_DEVICES ?= 1
|
|
+STM32MP_FLASHLOADER ?= 1
|
|
+
|
|
+ifeq (${STM32MP_BOOT_DEVICES},1)
|
|
# Boot devices
|
|
STM32MP1_QSPI_NOR := 1
|
|
$(eval $(call add_define,STM32MP1_QSPI_NOR))
|
|
@@ -57,9 +80,15 @@ $(eval $(call add_define,STM32MP1_QSPI_NAND))
|
|
ifeq ($(filter 1,${STM32MP1_QSPI_NOR} ${STM32MP_FMC_NAND} ${STM32MP_EMMC} ${STM32MP_SDMMC}),)
|
|
$(error "No boot device driver is enabled")
|
|
endif
|
|
+endif #STM32MP_BOOT_DEVICES
|
|
+
|
|
+ifeq (${STM32MP_FLASHLOADER},1)
|
|
+STM32MP_USB := 1
|
|
+$(eval $(call add_define,STM32MP_USB))
|
|
|
|
STM32MP_UART_PROGRAMMER := 1
|
|
$(eval $(call add_define,STM32MP_UART_PROGRAMMER))
|
|
+endif #STM32MP_FLASHLOADER
|
|
|
|
PLAT_INCLUDES := -Iinclude/common/tbbr
|
|
PLAT_INCLUDES += -Iinclude/drivers/partition
|
|
@@ -69,8 +98,6 @@ PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
|
|
|
|
PLAT_INCLUDES += -Iinclude/lib/usb
|
|
|
|
-STM32MP_USB := 1
|
|
-
|
|
# Device tree
|
|
DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
|
|
FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME)))
|
|
@@ -114,7 +141,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \
|
|
plat/st/stm32mp1/stm32mp1_dbgmcu.c \
|
|
plat/st/stm32mp1/stm32mp1_helper.S \
|
|
plat/st/stm32mp1/stm32mp1_security.c \
|
|
- plat/st/stm32mp1/stm32mp1_shared_resources.c
|
|
+ plat/st/stm32mp1/stm32mp1_shared_resources.c \
|
|
+ plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
|
|
BL2_SOURCES += drivers/io/io_block.c \
|
|
drivers/io/io_dummy.c \
|
|
@@ -123,8 +151,7 @@ BL2_SOURCES += drivers/io/io_block.c \
|
|
drivers/st/io/io_stm32image.c \
|
|
plat/st/common/bl2_io_storage.c \
|
|
plat/st/common/stm32mp_auth.c \
|
|
- plat/st/stm32mp1/bl2_plat_setup.c \
|
|
- plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
+ plat/st/stm32mp1/bl2_plat_setup.c
|
|
|
|
ifeq (${STM32MP1_QSPI_NOR},1)
|
|
BL2_SOURCES += drivers/st/qspi/io_qspi.c
|
|
@@ -155,14 +182,12 @@ BL2_SOURCES += common/desc_image_load.c \
|
|
plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
|
|
plat/st/stm32mp1/plat_image_load.c
|
|
|
|
-ifneq (${STM32MP_USB},0)
|
|
+ifeq (${STM32MP_USB},1)
|
|
BL2_SOURCES += drivers/st/io/io_programmer_st_usb.c \
|
|
drivers/st/usb_dwc2/usb_dwc2.c \
|
|
lib/usb/usb_core.c \
|
|
lib/usb/usb_st_dfu.c \
|
|
plat/st/stm32mp1/stm32mp1_usb_desc.c
|
|
-
|
|
-TF_CFLAGS += -DSTM32MP_USB
|
|
endif
|
|
|
|
ifeq ($(AARCH32_SP),optee)
|
|
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
|
|
index e4f86a2..b13580d 100644
|
|
--- a/plat/st/stm32mp1/services/bsec_svc.c
|
|
+++ b/plat/st/stm32mp1/services/bsec_svc.c
|
|
@@ -295,7 +295,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
|
|
|
|
value = (exchange->programming_lock[j] >> i) & 1U;
|
|
if (value != 0U) {
|
|
- if (!bsec_write_sp_lock((32U * j) + i, 1U)) {
|
|
+ if (bsec_set_sp_lock((32U * j) + i) !=
|
|
+ BSEC_OK) {
|
|
return BSEC_ERROR;
|
|
}
|
|
}
|
|
@@ -315,7 +316,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
|
|
|
|
value = (exchange->shadow_write_lock[j] >> i) & 1U;
|
|
if (value != 0U) {
|
|
- if (!bsec_write_sw_lock((32U * j) + i, 1U)) {
|
|
+ if (bsec_set_sw_lock((32U * j) + i) !=
|
|
+ BSEC_OK) {
|
|
return BSEC_ERROR;
|
|
}
|
|
}
|
|
@@ -335,7 +337,8 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
|
|
|
|
value = (exchange->shadow_read_lock[j] >> i) & 1U;
|
|
if (value != 0U) {
|
|
- if (!bsec_write_sr_lock((32U * j) + i, 1U)) {
|
|
+ if (bsec_set_sr_lock((32U * j) + i) !=
|
|
+ BSEC_OK) {
|
|
return BSEC_ERROR;
|
|
}
|
|
}
|
|
@@ -366,12 +369,9 @@ static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
|
|
(uint8_t)(exchange->general_lock & GPLOCK_LOCK_MASK) >>
|
|
GPLOCK_LOCK_SHIFT;
|
|
|
|
- if (!bsec_mode_is_closed_device()) {
|
|
- config_param.upper_otp_lock =
|
|
- (uint8_t)(exchange->general_lock &
|
|
- UPPER_OTP_LOCK_MASK) >>
|
|
- UPPER_OTP_LOCK_SHIFT;
|
|
- }
|
|
+ config_param.upper_otp_lock =
|
|
+ (uint8_t)(exchange->general_lock & UPPER_OTP_LOCK_MASK) >>
|
|
+ UPPER_OTP_LOCK_SHIFT;
|
|
|
|
ret = bsec_set_config(&config_param);
|
|
if (ret != BSEC_OK) {
|
|
@@ -388,7 +388,6 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
{
|
|
uint32_t result;
|
|
uint32_t tmp_data = 0U;
|
|
- struct otp_exchange *otp_exch = (struct otp_exchange *)(uintptr_t)x2;
|
|
|
|
if ((x1 != STM32_SMC_READ_ALL) && (x1 != STM32_SMC_WRITE_ALL) &&
|
|
(bsec_check_nsec_access_rights(x2) != BSEC_OK)) {
|
|
@@ -413,8 +412,7 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
break;
|
|
}
|
|
|
|
- *ret_otp_value = (uint32_t)bsec_check_ssp(tmp_data,
|
|
- otp_exch->otp_value[x2]);
|
|
+ *ret_otp_value = (uint32_t)bsec_check_ssp(tmp_data, x3);
|
|
if (*ret_otp_value == (uint32_t)BSEC_SSP_ERROR) {
|
|
result = BSEC_OK;
|
|
break;
|
|
@@ -446,10 +444,11 @@ uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
|
|
result = bsec_write_otp(tmp_data, x2);
|
|
break;
|
|
case STM32_SMC_READ_ALL:
|
|
- result = bsec_read_all_bsec(otp_exch);
|
|
+ result = bsec_read_all_bsec((struct otp_exchange *)x2);
|
|
break;
|
|
case STM32_SMC_WRITE_ALL:
|
|
- result = bsec_write_all_bsec(otp_exch, ret_otp_value);
|
|
+ result = bsec_write_all_bsec((struct otp_exchange *)x2,
|
|
+ ret_otp_value);
|
|
break;
|
|
default:
|
|
result = BSEC_ERROR;
|
|
diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c
|
|
index 1df6903..6e8f9d0 100644
|
|
--- a/plat/st/stm32mp1/services/rcc_svc.c
|
|
+++ b/plat/st/stm32mp1/services/rcc_svc.c
|
|
@@ -457,13 +457,13 @@ uint32_t rcc_cal_scv_handler(uint32_t x1)
|
|
|
|
switch (x1) {
|
|
case CK_CSI:
|
|
- if (stm32mp1_rcc_start_csi_cal() == 0) {
|
|
+ if (stm32mp1_calib_start_csi_cal() == 0) {
|
|
ret = STM32_SMC_OK;
|
|
}
|
|
break;
|
|
|
|
case CK_HSI:
|
|
- if (stm32mp1_rcc_start_hsi_cal() == 0) {
|
|
+ if (stm32mp1_calib_start_hsi_cal() == 0) {
|
|
ret = STM32_SMC_OK;
|
|
}
|
|
break;
|
|
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
|
|
index 322d389..416b5a2 100644
|
|
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
|
|
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
|
|
@@ -7,6 +7,7 @@
|
|
SP_MIN_WITH_SECURE_FIQ := 1
|
|
|
|
BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
|
|
+ drivers/st/clk/stm32mp1_calib.c \
|
|
drivers/st/etzpc/etzpc.c \
|
|
drivers/st/rng/stm32_rng.c \
|
|
drivers/st/rtc/stm32_rtc.c \
|
|
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
index e8dc409..8748b68 100644
|
|
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -68,6 +68,8 @@ static void stm32_sgi1_it_handler(void)
|
|
{
|
|
uint32_t id;
|
|
|
|
+ stm32mp_mask_timer();
|
|
+
|
|
gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1);
|
|
|
|
do {
|
|
@@ -80,17 +82,19 @@ static void stm32_sgi1_it_handler(void)
|
|
}
|
|
} while (id <= MAX_SPI_ID);
|
|
|
|
+ stm32mp_wait_cpu_reset();
|
|
+}
|
|
|
|
- isb();
|
|
- dsb();
|
|
-
|
|
- /* Flush L1/L2 data caches */
|
|
- write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
|
|
- dcsw_op_all(DC_OP_CISW);
|
|
+static void configure_wakeup_interrupt(void)
|
|
+{
|
|
+ int irq_num = fdt_rcc_enable_it("wakeup");
|
|
|
|
- for ( ; ; ) {
|
|
- wfi();
|
|
+ if (irq_num < 0) {
|
|
+ ERROR("irq_num = %d\n", irq_num);
|
|
+ panic();
|
|
}
|
|
+
|
|
+ plat_ic_set_interrupt_priority(irq_num, STM32MP1_IRQ_RCC_SEC_PRIO);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
@@ -104,7 +108,7 @@ void sp_min_plat_fiq_handler(uint32_t id)
|
|
case ARM_IRQ_SEC_PHY_TIMER:
|
|
case STM32MP1_IRQ_MCU_SEV:
|
|
case STM32MP1_IRQ_RCC_WAKEUP:
|
|
- stm32mp1_rcc_it_handler(id);
|
|
+ stm32mp1_calib_it_handler(id);
|
|
break;
|
|
case STM32MP1_IRQ_TZC400:
|
|
tzc400_init(STM32MP1_TZC_BASE);
|
|
@@ -232,6 +236,22 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
|
|
|
bl_params_node_t *bl_params = params_from_bl2->head;
|
|
|
|
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
|
+ 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_LIMIT - BL_RO_DATA_BASE,
|
|
+ MT_RO_DATA | MT_SECURE);
|
|
+#endif
|
|
+
|
|
+ mmap_add_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
|
|
+ dt_get_ddr_size() - STM32MP_DDR_S_SIZE,
|
|
+ MT_MEMORY | MT_RW | MT_NS);
|
|
+
|
|
+ configure_mmu();
|
|
+
|
|
/*
|
|
* Copy BL33 entry point information.
|
|
* They are stored in Secure RAM, in BL2's address space.
|
|
@@ -319,7 +339,7 @@ void stm32mp1_sp_min_security_setup(void)
|
|
}
|
|
|
|
if (stm32_timer_init() == 0) {
|
|
- stm32mp1_cal_init();
|
|
+ stm32mp1_calib_init();
|
|
}
|
|
}
|
|
|
|
@@ -328,22 +348,6 @@ void stm32mp1_sp_min_security_setup(void)
|
|
******************************************************************************/
|
|
void sp_min_platform_setup(void)
|
|
{
|
|
- mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
|
- 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_LIMIT - BL_RO_DATA_BASE,
|
|
- MT_RO_DATA | MT_SECURE);
|
|
-#endif
|
|
-
|
|
- mmap_add_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
|
|
- dt_get_ddr_size() - STM32MP_DDR_S_SIZE,
|
|
- MT_MEMORY | MT_RW | MT_NS);
|
|
-
|
|
- configure_mmu();
|
|
-
|
|
/* Initialize tzc400 after DDR initialization */
|
|
stm32mp1_security_setup();
|
|
|
|
@@ -358,6 +362,8 @@ void sp_min_platform_setup(void)
|
|
panic();
|
|
}
|
|
|
|
+ configure_wakeup_interrupt();
|
|
+
|
|
stm32mp1_driver_init_late();
|
|
}
|
|
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
|
|
index a6b1a7b..7d7d773 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_def.h
|
|
+++ b/plat/st/stm32mp1/stm32mp1_def.h
|
|
@@ -14,6 +14,7 @@
|
|
#include <dt-bindings/reset/stm32mp1-resets.h>
|
|
#include <dt-bindings/soc/st,stm32-etzpc.h>
|
|
#include <etzpc.h>
|
|
+#include <stm32mp1_calib.h>
|
|
#include <stm32mp1_clkfunc.h>
|
|
#include <stm32mp1_clk.h>
|
|
#include <stm32mp1_context.h>
|
|
@@ -203,9 +204,9 @@ enum ddr_type {
|
|
|
|
#define STM32MP_NAND_BL33_OFFSET U(0x00200000)
|
|
#ifdef AARCH32_SP_OPTEE
|
|
-#define STM32MP_NAND_TEEH_OFFSET U(0x00400000)
|
|
-#define STM32MP_NAND_TEED_OFFSET U(0x00480000)
|
|
-#define STM32MP_NAND_TEEX_OFFSET U(0x00500000)
|
|
+#define STM32MP_NAND_TEEH_OFFSET U(0x00600000)
|
|
+#define STM32MP_NAND_TEED_OFFSET U(0x00680000)
|
|
+#define STM32MP_NAND_TEEX_OFFSET U(0x00700000)
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
@@ -374,7 +375,6 @@ enum ddr_type {
|
|
#define UID2_OTP U(15)
|
|
#define PACKAGE_OTP U(16)
|
|
#define HW2_OTP U(18) /* HW watchdog OTP */
|
|
-#define BOARD_OTP U(59)
|
|
|
|
/* OTP mask */
|
|
/* DATA0 */
|
|
@@ -393,6 +393,9 @@ enum ddr_type {
|
|
#define IWDG_FZ_STOP_POS 5
|
|
#define IWDG_FZ_STANDBY_POS 7
|
|
|
|
+/* HW2 OTP */
|
|
+#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13)
|
|
+
|
|
/* NAND OTP */
|
|
/* NAND parameter storage flag */
|
|
#define NAND_PARAM_STORED_IN_OTP U(0x80000000)
|
|
@@ -447,7 +450,12 @@ enum ddr_type {
|
|
#define PLAT_MAX_TAMP_INT U(5)
|
|
#define PLAT_MAX_TAMP_EXT U(3)
|
|
#define TAMP_BASE U(0x5C00A000)
|
|
+#define TAMP_SMCR (TAMP_BASE + U(0x20))
|
|
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
|
|
+#define TAMP_BKP_SEC_NUMBER U(10)
|
|
+#define TAMP_BKP_SEC_WDPROT_SHIFT U(16)
|
|
+#define TAMP_BKP_SEC_RWDPROT_SHIFT U(0)
|
|
+
|
|
|
|
#if !(defined(__LINKER__) || defined(__ASSEMBLY__))
|
|
static inline uint32_t tamp_bkpr(uint32_t idx)
|
|
@@ -523,6 +531,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
|
|
/*******************************************************************************
|
|
* Device Tree defines
|
|
******************************************************************************/
|
|
+#define DT_BSEC_COMPAT "st,stm32mp15-bsec"
|
|
#define DT_PWR_COMPAT "st,stm32mp1-pwr"
|
|
#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
|
|
#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg"
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
|
|
index 1adaaee..afaa1f4 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_helper.S
|
|
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -311,15 +311,20 @@ func plat_crash_console_putc
|
|
b console_stm32_core_putc
|
|
endfunc plat_crash_console_putc
|
|
|
|
- /* -----------------------------------------------------
|
|
+ /* ----------------------------------------------------------
|
|
* void plat_panic_handler(void) __dead2;
|
|
* Report exception + endless loop.
|
|
- * -----------------------------------------------------
|
|
+ *
|
|
+ * r6 holds the address where the fault occurred.
|
|
+ * Filling lr with this value allows debuggers to reconstruct
|
|
+ * the backtrace.
|
|
+ * ----------------------------------------------------------
|
|
*/
|
|
func plat_panic_handler
|
|
mrs r0, cpsr
|
|
and r0, #MODE32_MASK
|
|
bl plat_report_exception
|
|
+ mov lr, r6
|
|
b .
|
|
endfunc plat_panic_handler
|
|
|
|
@@ -363,8 +368,8 @@ func wfi_svc_int_enable
|
|
str r4, [sp, #SMC_CTX_SCR]
|
|
cps #MODE32_svc
|
|
cpsie af
|
|
- isb
|
|
dsb
|
|
+ isb
|
|
wfi
|
|
cpsid af
|
|
cps #MODE32_mon
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
index de9035c..f8b35dd 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_low_power.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -129,6 +129,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
uintptr_t pwr_base = stm32mp_pwr_base();
|
|
uintptr_t rcc_base = stm32mp_rcc_base();
|
|
|
|
+ stm32mp1_syscfg_disable_io_compensation();
|
|
+
|
|
dcsw_op_all(DC_OP_CISW);
|
|
|
|
stm32_clean_context();
|
|
@@ -141,6 +143,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
stm32_save_ddr_training_area();
|
|
}
|
|
|
|
+ stm32mp1_clk_mpu_suspend();
|
|
+
|
|
if (dt_pmic_status() > 0) {
|
|
stm32_apply_pmic_suspend_config(mode);
|
|
|
|
@@ -186,7 +190,6 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
mmio_write_32(bkpr_core1_magic, 0);
|
|
|
|
if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) {
|
|
-
|
|
/*
|
|
* Save non-secure world entrypoint after standby in Backup
|
|
* register
|
|
@@ -198,6 +201,14 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
if (stm32_save_context(zq0cr0_zdata) != 0) {
|
|
panic();
|
|
}
|
|
+
|
|
+ /* Keep retention and backup RAM content in standby */
|
|
+ mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN |
|
|
+ PWR_CR2_RREN);
|
|
+ while ((mmio_read_32(pwr_base + PWR_CR2) &
|
|
+ (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) {
|
|
+ ;
|
|
+ }
|
|
}
|
|
|
|
stm32mp_clk_disable(RTCAPB);
|
|
@@ -212,6 +223,7 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
|
|
*/
|
|
void stm32_exit_cstop(void)
|
|
{
|
|
+ uintptr_t pwr_base = stm32mp_pwr_base();
|
|
uintptr_t rcc_base = stm32mp_rcc_base();
|
|
|
|
if (!enter_cstop_done) {
|
|
@@ -220,6 +232,8 @@ void stm32_exit_cstop(void)
|
|
|
|
enter_cstop_done = false;
|
|
|
|
+ stm32mp1_clk_mpu_resume();
|
|
+
|
|
if (ddr_sw_self_refresh_exit() != 0) {
|
|
panic();
|
|
}
|
|
@@ -236,6 +250,9 @@ void stm32_exit_cstop(void)
|
|
dsb();
|
|
isb();
|
|
|
|
+ /* Disable retention and backup RAM content after stop */
|
|
+ mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN);
|
|
+
|
|
/* Update STGEN counter with low power mode duration */
|
|
stm32_rtc_get_calendar(¤t_calendar);
|
|
|
|
@@ -243,10 +260,17 @@ void stm32_exit_cstop(void)
|
|
&sleep_time);
|
|
|
|
stm32mp1_stgen_increment(stdby_time_in_ms);
|
|
+
|
|
+ stm32mp1_syscfg_enable_io_compensation();
|
|
}
|
|
|
|
static void enter_shutdown(void)
|
|
{
|
|
+ /* Set DDR in Self-refresh before shutting down the platform */
|
|
+ if (ddr_standby_sr_entry(NULL) != 0) {
|
|
+ WARN("DDR can't be set in Self-refresh mode\n");
|
|
+ }
|
|
+
|
|
if (dt_pmic_status() > 0) {
|
|
if (!initialize_pmic_i2c()) {
|
|
panic();
|
|
@@ -294,10 +318,10 @@ void stm32_pwr_down_wfi(void)
|
|
{
|
|
uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
|
|
|
|
- stm32mp1_rcc_set_wakeup(false);
|
|
+ stm32mp1_calib_set_wakeup(false);
|
|
|
|
while (interrupt == GIC_SPURIOUS_INTERRUPT &&
|
|
- !stm32mp1_rcc_get_wakeup()) {
|
|
+ !stm32mp1_calib_get_wakeup()) {
|
|
wfi_svc_int_enable((uintptr_t)&int_stack[0]);
|
|
|
|
interrupt = gicv2_acknowledge_interrupt();
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
|
|
index 20a2f5c..b95bc3d 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_pm.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
|
|
@@ -40,11 +40,12 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state)
|
|
assert(cpu_state == ARM_LOCAL_STATE_RET);
|
|
|
|
/*
|
|
- * Enter standby state
|
|
- * dsb is good practice before using wfi to enter low power states
|
|
+ * Enter standby state.
|
|
+ * Synchronize on memory accesses and instruction flow before the WFI
|
|
+ * instruction.
|
|
*/
|
|
- isb();
|
|
dsb();
|
|
+ isb();
|
|
while (interrupt == GIC_SPURIOUS_INTERRUPT) {
|
|
wfi();
|
|
|
|
@@ -85,6 +86,9 @@ static int stm32_pwr_domain_on(u_register_t mpidr)
|
|
return PSCI_E_INVALID_PARAMS;
|
|
}
|
|
|
|
+ /* Reset backup register content */
|
|
+ mmio_write_32(bkpr_core1_magic, 0);
|
|
+
|
|
/* Need to send additional IT 0 after individual core 1 reset */
|
|
gicv2_raise_sgi(ARM_IRQ_NON_SEC_SGI_0, STM32MP_SECONDARY_CPU);
|
|
|
|
@@ -183,9 +187,12 @@ static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
|
|
mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
|
|
RCC_MP_GRSTCSETR_MPUP1RST);
|
|
|
|
- /* wfi is required for an auto-reset */
|
|
- isb();
|
|
+ /*
|
|
+ * Synchronize on memory accesses and instruction flow before
|
|
+ * auto-reset from the WFI instruction.
|
|
+ */
|
|
dsb();
|
|
+ isb();
|
|
wfi();
|
|
|
|
/* This shouldn't be reached */
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
|
|
index c1f4c82..aae537f 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_private.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_private.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
@@ -15,8 +15,26 @@
|
|
#include <stm32_iwdg.h>
|
|
#include <stm32mp_common.h>
|
|
#include <stm32mp_dt.h>
|
|
+#include <stm32mp_reset.h>
|
|
#include <xlat_tables_v2.h>
|
|
|
|
+/* Internal layout of the 32bit OTP word board_id */
|
|
+#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16)
|
|
+#define BOARD_ID_BOARD_NB_SHIFT 16
|
|
+#define BOARD_ID_VARIANT_MASK GENMASK(15, 12)
|
|
+#define BOARD_ID_VARIANT_SHIFT 12
|
|
+#define BOARD_ID_REVISION_MASK GENMASK(11, 8)
|
|
+#define BOARD_ID_REVISION_SHIFT 8
|
|
+#define BOARD_ID_BOM_MASK GENMASK(3, 0)
|
|
+
|
|
+#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \
|
|
+ BOARD_ID_BOARD_NB_SHIFT)
|
|
+#define BOARD_ID2VAR(_id) (((_id) & BOARD_ID_VARIANT_MASK) >> \
|
|
+ BOARD_ID_VARIANT_SHIFT)
|
|
+#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \
|
|
+ BOARD_ID_REVISION_SHIFT)
|
|
+#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
|
|
+
|
|
#define MAP_ROM MAP_REGION_FLAT(STM32MP_ROM_BASE, \
|
|
STM32MP_ROM_SIZE, \
|
|
MT_MEMORY | \
|
|
@@ -119,9 +137,111 @@ uintptr_t get_uart_address(uint32_t instance_nb)
|
|
}
|
|
#endif
|
|
|
|
+#define ARM_CNTXCTL_IMASK BIT(1)
|
|
+
|
|
+void stm32mp_mask_timer(void)
|
|
+{
|
|
+ /* Mask timer interrupts */
|
|
+ write_cntp_ctl(read_cntp_ctl() | ARM_CNTXCTL_IMASK);
|
|
+ write_cntv_ctl(read_cntv_ctl() | ARM_CNTXCTL_IMASK);
|
|
+}
|
|
+
|
|
+void __dead2 stm32mp_wait_cpu_reset(void)
|
|
+{
|
|
+ uint32_t id;
|
|
+
|
|
+ dcsw_op_all(DC_OP_CISW);
|
|
+ write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
|
|
+ dcsw_op_all(DC_OP_CISW);
|
|
+ __asm__("clrex");
|
|
+
|
|
+ dsb();
|
|
+ isb();
|
|
+
|
|
+ for ( ; ; ) {
|
|
+ do {
|
|
+ id = plat_ic_get_pending_interrupt_id();
|
|
+
|
|
+ if (id <= MAX_SPI_ID) {
|
|
+ gicv2_end_of_interrupt(id);
|
|
+
|
|
+ plat_ic_disable_interrupt(id);
|
|
+ }
|
|
+ } while (id <= MAX_SPI_ID);
|
|
+
|
|
+ wfi();
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * tzc_source_ip contains the TZC transaction source IPs that need to be reset
|
|
+ * before a C-A7 subsystem is reset (i.e. independent reset):
|
|
+ * - C-A7 subsystem is reset separately later in the sequence,
|
|
+ * - C-M4 subsystem is not concerned here,
|
|
+ * - DAP is excluded for debug purpose,
|
|
+ * - IPs are stored with their ETZPC IDs (STM32MP1_ETZPC_MAX_ID if not
|
|
+ * applicable) because some of them need to be reset only if they are not
|
|
+ * configured in MCU isolation mode inside ETZPC device tree.
|
|
+ */
|
|
+struct tzc_source_ip {
|
|
+ uint32_t reset_id;
|
|
+ uint32_t clock_id;
|
|
+ uint32_t decprot_id;
|
|
+};
|
|
+
|
|
+#define _TZC_FIXED(res, clk) \
|
|
+ { \
|
|
+ .reset_id = (res), \
|
|
+ .clock_id = (clk), \
|
|
+ .decprot_id = STM32MP1_ETZPC_MAX_ID, \
|
|
+ }
|
|
+
|
|
+#define _TZC_COND(res, clk, decprot) \
|
|
+ { \
|
|
+ .reset_id = (res), \
|
|
+ .clock_id = (clk), \
|
|
+ .decprot_id = (decprot), \
|
|
+ }
|
|
+
|
|
+static const struct tzc_source_ip tzc_source_ip[] = {
|
|
+ _TZC_FIXED(LTDC_R, LTDC_PX),
|
|
+ _TZC_FIXED(GPU_R, GPU),
|
|
+ _TZC_FIXED(USBH_R, USBH),
|
|
+ _TZC_FIXED(SDMMC1_R, SDMMC1_K),
|
|
+ _TZC_FIXED(SDMMC2_R, SDMMC2_K),
|
|
+ _TZC_FIXED(MDMA_R, MDMA),
|
|
+ _TZC_COND(USBO_R, USBO_K, STM32MP1_ETZPC_OTG_ID),
|
|
+ _TZC_COND(SDMMC3_R, SDMMC3_K, STM32MP1_ETZPC_SDMMC3_ID),
|
|
+ _TZC_COND(ETHMAC_R, ETHMAC, STM32MP1_ETZPC_ETH_ID),
|
|
+ _TZC_COND(DMA1_R, DMA1, STM32MP1_ETZPC_DMA1_ID),
|
|
+ _TZC_COND(DMA2_R, DMA2, STM32MP1_ETZPC_DMA2_ID),
|
|
+};
|
|
+
|
|
void __dead2 stm32mp_plat_reset(int cpu)
|
|
{
|
|
uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST;
|
|
+ uint32_t id;
|
|
+
|
|
+ /* Mask timer interrupts */
|
|
+ stm32mp_mask_timer();
|
|
+
|
|
+ for (id = 0U; id < ARRAY_SIZE(tzc_source_ip); id++) {
|
|
+ if ((!stm32mp1_clk_is_enabled(tzc_source_ip[id].clock_id)) ||
|
|
+ ((tzc_source_ip[id].decprot_id != STM32MP1_ETZPC_MAX_ID) &&
|
|
+ (etzpc_get_decprot(tzc_source_ip[id].decprot_id) ==
|
|
+ TZPC_DECPROT_MCU_ISOLATION))) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (tzc_source_ip[id].reset_id != GPU_R) {
|
|
+ stm32mp_reset_assert(tzc_source_ip[id].reset_id);
|
|
+ stm32mp_reset_deassert(tzc_source_ip[id].reset_id);
|
|
+ } else {
|
|
+ /* GPU reset automatically cleared by hardware */
|
|
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_AHB6RSTSETR,
|
|
+ RCC_AHB6RSTSETR_GPURST);
|
|
+ }
|
|
+ }
|
|
|
|
if (stm32mp_is_single_core() == 0) {
|
|
unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ?
|
|
@@ -131,18 +251,19 @@ void __dead2 stm32mp_plat_reset(int cpu)
|
|
reg |= RCC_MP_GRSTCSETR_MPUP1RST;
|
|
}
|
|
|
|
- mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg);
|
|
+ do {
|
|
+ id = plat_ic_get_pending_interrupt_id();
|
|
|
|
- isb();
|
|
- dsb();
|
|
+ if (id <= MAX_SPI_ID) {
|
|
+ gicv2_end_of_interrupt(id);
|
|
|
|
- /* Flush L1/L2 data caches */
|
|
- write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
|
|
- dcsw_op_all(DC_OP_CISW);
|
|
+ plat_ic_disable_interrupt(id);
|
|
+ }
|
|
+ } while (id <= MAX_SPI_ID);
|
|
|
|
- for ( ; ; ) {
|
|
- wfi();
|
|
- }
|
|
+ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg);
|
|
+
|
|
+ stm32mp_wait_cpu_reset();
|
|
}
|
|
|
|
static uint32_t get_part_number(void)
|
|
@@ -237,23 +358,49 @@ void stm32mp_print_cpuinfo(void)
|
|
|
|
void stm32mp_print_boardinfo(void)
|
|
{
|
|
- uint32_t board;
|
|
- int res = 0;
|
|
+ uint32_t board_id = 0;
|
|
+ uint32_t board_otp;
|
|
+ int bsec_node, bsec_board_id_node;
|
|
+ void *fdt;
|
|
+ const fdt32_t *cuint;
|
|
+
|
|
+ if (fdt_get_address(&fdt) == 0) {
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ bsec_node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT);
|
|
+ if (bsec_node < 0) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ bsec_board_id_node = fdt_subnode_offset(fdt, bsec_node, "board_id");
|
|
+ if (bsec_board_id_node <= 0) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ cuint = fdt_getprop(fdt, bsec_board_id_node, "reg", NULL);
|
|
+ if (cuint == NULL) {
|
|
+ ERROR("board_id node without reg property\n");
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
|
|
|
|
- if (bsec_shadow_read_otp(&board, BOARD_OTP) != BSEC_OK) {
|
|
+ if (bsec_shadow_read_otp(&board_id, board_otp) != BSEC_OK) {
|
|
ERROR("BSEC: PART_NUMBER_OTP Error\n");
|
|
- res = -1;
|
|
+ return;
|
|
}
|
|
|
|
- if ((res == 0) && (board != 0U)) {
|
|
- char rev[1];
|
|
+ if (board_id != 0U) {
|
|
+ char rev[2];
|
|
|
|
- *rev = ((board >> 8) & 0xF) - 1 + 'A';
|
|
+ rev[0] = BOARD_ID2REV(board_id) - 1 + 'A';
|
|
+ rev[1] = '\0';
|
|
NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n",
|
|
- board >> 16,
|
|
- (board >> 12) & 0xF,
|
|
+ BOARD_ID2NB(board_id),
|
|
+ BOARD_ID2VAR(board_id),
|
|
rev,
|
|
- board & 0xF);
|
|
+ BOARD_ID2BOM(board_id));
|
|
}
|
|
}
|
|
|
|
@@ -309,12 +456,12 @@ uint32_t stm32_iwdg_get_otp_config(uintptr_t base)
|
|
iwdg_cfg |= IWDG_HW_ENABLED;
|
|
}
|
|
|
|
- if ((otp_value & BIT(idx + IWDG_FZ_STOP_POS)) == 0U) {
|
|
- iwdg_cfg |= IWDG_ENABLE_ON_STOP;
|
|
+ if ((otp_value & BIT(idx + IWDG_FZ_STOP_POS)) != 0U) {
|
|
+ iwdg_cfg |= IWDG_DISABLE_ON_STOP;
|
|
}
|
|
|
|
- if ((otp_value & BIT(idx + IWDG_FZ_STANDBY_POS)) == 0U) {
|
|
- iwdg_cfg |= IWDG_ENABLE_ON_STANDBY;
|
|
+ if ((otp_value & BIT(idx + IWDG_FZ_STANDBY_POS)) != 0U) {
|
|
+ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY;
|
|
}
|
|
|
|
return iwdg_cfg;
|
|
@@ -333,11 +480,11 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags)
|
|
|
|
idx = stm32_iwdg_get_instance(base);
|
|
|
|
- if ((flags & IWDG_ENABLE_ON_STOP) != 0) {
|
|
+ if ((flags & IWDG_DISABLE_ON_STOP) != 0) {
|
|
otp |= BIT(idx + IWDG_FZ_STOP_POS);
|
|
}
|
|
|
|
- if ((flags & IWDG_ENABLE_ON_STANDBY) != 0) {
|
|
+ if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) {
|
|
otp |= BIT(idx + IWDG_FZ_STANDBY_POS);
|
|
}
|
|
|
|
@@ -347,8 +494,8 @@ uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags)
|
|
}
|
|
|
|
/* Sticky lock OTP_IWDG (read and write) */
|
|
- if (!bsec_write_sr_lock(HW2_OTP, 1U) ||
|
|
- !bsec_write_sw_lock(HW2_OTP, 1U)) {
|
|
+ if ((bsec_set_sr_lock(HW2_OTP) != BSEC_OK) ||
|
|
+ (bsec_set_sw_lock(HW2_OTP) != BSEC_OK)) {
|
|
return BSEC_LOCK_FAIL;
|
|
}
|
|
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
|
|
index 8dfbe71..d2da110 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_security.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_security.c
|
|
@@ -30,7 +30,8 @@ static void init_tzc400(void)
|
|
tzc400_disable_filters();
|
|
|
|
#ifdef AARCH32_SP_OPTEE
|
|
- /* Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
|
|
+ /*
|
|
+ * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
|
|
* same configuration to all filters in the TZC.
|
|
*/
|
|
region_base = ddr_base;
|
|
@@ -38,7 +39,7 @@ static void init_tzc400(void)
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
|
region_base,
|
|
region_top,
|
|
- 0,
|
|
+ TZC_REGION_S_NONE,
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
|
|
@@ -66,7 +67,7 @@ static void init_tzc400(void)
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
|
|
region_base,
|
|
region_top,
|
|
- 0,
|
|
+ TZC_REGION_S_NONE,
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
|
|
@@ -79,7 +80,8 @@ static void init_tzc400(void)
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
|
|
#else
|
|
- /* Region 1 set to cover all DRAM at 0xC000_0000. Apply the
|
|
+ /*
|
|
+ * Region 1 set to cover all DRAM at 0xC000_0000. Apply the
|
|
* same configuration to all filters in the TZC.
|
|
*/
|
|
region_base = ddr_base;
|
|
@@ -87,7 +89,7 @@ static void init_tzc400(void)
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
|
region_base,
|
|
region_top,
|
|
- TZC_REGION_S_RDWR,
|
|
+ TZC_REGION_S_NONE,
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
|
|
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
|
|
@@ -121,10 +123,7 @@ static void early_init_tzc400(void)
|
|
|
|
tzc400_disable_filters();
|
|
|
|
- /*
|
|
- * Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
|
|
- * same configuration to all filters in the TZC.
|
|
- */
|
|
+ /* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */
|
|
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
|
STM32MP_DDR_BASE,
|
|
STM32MP_DDR_BASE +
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
|
|
index 2c95de0..09d9136 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
|
|
@@ -1,6 +1,6 @@
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
/*
|
|
- * Copyright (c) 2017-2018, STMicroelectronics
|
|
+ * Copyright (c) 2017-2019, STMicroelectronics
|
|
*/
|
|
|
|
#include <arch.h>
|
|
@@ -765,8 +765,6 @@ static void check_rcc_secure_configuration(void)
|
|
bool mckprot = stm32mp1_rcc_is_mckprot();
|
|
bool secure = stm32mp1_rcc_is_secure();
|
|
|
|
- stm32mp1_rcc_init_late();
|
|
-
|
|
for (n = 0; n < ARRAY_SIZE(shres_state); n++) {
|
|
if ((shres_state[n] == SHRES_SECURE) ||
|
|
(shres_state[n] == SHRES_SHARED)) {
|
|
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
index 3eb9893..3276870 100644
|
|
--- a/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
|
|
@@ -6,9 +6,11 @@
|
|
|
|
#include <bsec.h>
|
|
#include <debug.h>
|
|
+#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
#include <mmio.h>
|
|
#include <platform_def.h>
|
|
#include <stm32mp_dt.h>
|
|
+#include <stm32mp1_clk.h>
|
|
#include <stm32mp1_private.h>
|
|
#include <stpmic1.h>
|
|
|
|
@@ -45,14 +47,16 @@
|
|
*/
|
|
#define SYSCFG_CMPCR_SW_CTRL BIT(1)
|
|
#define SYSCFG_CMPCR_READY BIT(8)
|
|
+#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
|
|
+#define SYSCFG_CMPCR_RANSRC_SHIFT 16
|
|
+#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
|
|
+#define SYSCFG_CMPCR_ANSRC_SHIFT 24
|
|
|
|
/*
|
|
* SYSCFG_CMPENSETR Register
|
|
*/
|
|
#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
|
|
|
|
-#define PRODUCT_BELOW_2V5 BIT(13)
|
|
-
|
|
void stm32mp1_syscfg_init(void)
|
|
{
|
|
uint32_t bootr;
|
|
@@ -81,28 +85,30 @@ void stm32mp1_syscfg_init(void)
|
|
/*
|
|
* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
|
|
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
|
|
- * The customer will have to disable this for low frequencies
|
|
- * or if AFMUX is selected but the function not used, typically for
|
|
- * TRACE. Otherwise, impact on power consumption.
|
|
+ * It could be disabled for low frequencies or if AFMUX is selected
|
|
+ * but the function not used, typically for TRACE.
|
|
+ * Otherwise, impact on power consumption.
|
|
*
|
|
* WARNING:
|
|
* Enabling High Speed mode while VDD > 2.7V
|
|
* with the OTP product_below_2v5 (OTP 18, BIT 13)
|
|
* erroneously set to 1 can damage the IC!
|
|
- * => TF-A sets the register only if VDD < 2.7V (in DT)
|
|
+ * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
|
|
* but this value needs to be consistent with board design.
|
|
*/
|
|
if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) {
|
|
- otp = otp & PRODUCT_BELOW_2V5;
|
|
+ panic();
|
|
}
|
|
|
|
- /* Get VDD = pwr-supply */
|
|
+ otp = otp & HW2_OTP_PRODUCT_BELOW_2V5;
|
|
+
|
|
+ /* Get VDD supply */
|
|
vdd_voltage = dt_get_pwr_vdd_voltage();
|
|
VERBOSE("VDD regulator voltage = %d\n", vdd_voltage);
|
|
|
|
/* Check if VDD is Low Voltage */
|
|
if (vdd_voltage == 0U) {
|
|
- INFO("VDD unknown");
|
|
+ WARN("VDD unknown");
|
|
} else if (vdd_voltage < 2700000U) {
|
|
mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR,
|
|
SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
|
|
@@ -116,8 +122,8 @@ void stm32mp1_syscfg_init(void)
|
|
}
|
|
} else {
|
|
if (otp != 0U) {
|
|
- INFO("Product_below_2v5=1: HSLVEN update is\n");
|
|
- INFO(" destructive, no update as VDD>2.7V\n");
|
|
+ ERROR("Product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
|
|
+ panic();
|
|
}
|
|
}
|
|
|
|
@@ -125,14 +131,25 @@ void stm32mp1_syscfg_init(void)
|
|
(uint32_t)syscfg_base + SYSCFG_IOCTRLSETR,
|
|
mmio_read_32(syscfg_base + SYSCFG_IOCTRLSETR));
|
|
|
|
+ stm32mp1_syscfg_enable_io_compensation();
|
|
+}
|
|
+
|
|
+void stm32mp1_syscfg_enable_io_compensation(void)
|
|
+{
|
|
+ uintptr_t syscfg_base = dt_get_syscfg_base();
|
|
+
|
|
/*
|
|
* Activate automatic I/O compensation.
|
|
* Warning: need to ensure CSI enabled and ready in clock driver.
|
|
+ * Enable non-secure clock, we assume non-secure is suspended.
|
|
*/
|
|
- mmio_write_32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN);
|
|
+ stm32mp1_clk_enable_non_secure(SYSCFG);
|
|
+
|
|
+ mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR,
|
|
+ SYSCFG_CMPENSETR_MPU_EN);
|
|
|
|
while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) &
|
|
- SYSCFG_CMPCR_READY) != 0U) {
|
|
+ SYSCFG_CMPCR_READY) == 0U) {
|
|
;
|
|
}
|
|
|
|
@@ -142,3 +159,37 @@ void stm32mp1_syscfg_init(void)
|
|
(uint32_t)syscfg_base + SYSCFG_CMPCR,
|
|
mmio_read_32(syscfg_base + SYSCFG_CMPCR));
|
|
}
|
|
+
|
|
+void stm32mp1_syscfg_disable_io_compensation(void)
|
|
+{
|
|
+ uintptr_t syscfg_base = dt_get_syscfg_base();
|
|
+ uint32_t value;
|
|
+
|
|
+ /*
|
|
+ * Deactivate automatic I/O compensation.
|
|
+ * Warning: CSI is disabled automatically in STOP if not
|
|
+ * requested for other usages and always OFF in STANDBY.
|
|
+ * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
|
|
+ */
|
|
+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >>
|
|
+ SYSCFG_CMPCR_ANSRC_SHIFT;
|
|
+
|
|
+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR,
|
|
+ SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
|
|
+
|
|
+ value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) |
|
|
+ (value << SYSCFG_CMPCR_RANSRC_SHIFT);
|
|
+
|
|
+ mmio_write_32(syscfg_base + SYSCFG_CMPCR, value);
|
|
+
|
|
+ mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
|
|
+
|
|
+ VERBOSE("[0x%x] SYSCFG.cmpcr = 0x%08x\n",
|
|
+ (uint32_t)syscfg_base + SYSCFG_CMPCR,
|
|
+ mmio_read_32(syscfg_base + SYSCFG_CMPCR));
|
|
+
|
|
+ mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR,
|
|
+ SYSCFG_CMPENSETR_MPU_EN);
|
|
+
|
|
+ stm32mp1_clk_disable_non_secure(SYSCFG);
|
|
+}
|
|
--
|
|
2.7.4
|
|
|