meta-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp/0002-st-update-r1.1.0.patch

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(&params, 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(&params) != 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(&params, 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(&params) != 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(&current_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