From 74771d5557e59fd428c2a6df2323601da27c19ea Mon Sep 17 00:00:00 2001 From: Romuald JEANNE 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 #include #include +#include #include #include #include @@ -27,9 +28,6 @@ #include #include #include -#if defined(IMAGE_BL32) -#include -#endif #include #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 = ; @@ -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 #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 +#include + +bool stm32mp1_calib_get_wakeup(void); +void stm32mp1_calib_set_wakeup(bool state); +void stm32mp1_calib_it_handler(uint32_t id); +int stm32mp1_calib_start_hsi_cal(void); +int stm32mp1_calib_start_csi_cal(void); +void stm32mp1_calib_init(void); + +#endif /* STM32MP1_CLK_H */ diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 0c8583a..4f6930b 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -56,18 +56,11 @@ void stm32mp1_clk_rcc_regs_lock(void); void stm32mp1_clk_rcc_regs_unlock(void); unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit); - #if defined(IMAGE_BL32) -bool stm32mp1_rcc_get_wakeup(void); -void stm32mp1_rcc_set_wakeup(bool state); -void stm32mp1_rcc_it_handler(uint32_t id); -int stm32mp1_rcc_start_hsi_cal(void); -int stm32mp1_rcc_start_csi_cal(void); -void stm32mp1_cal_init(void); +void stm32mp1_clk_mpu_suspend(void); +void stm32mp1_clk_mpu_resume(void); #endif -void stm32mp1_rcc_init_late(void); - void stm32mp1_register_clock_parents_secure(unsigned long id); void stm32mp1_update_earlyboot_clocks_state(void); diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h index 1a22824..9753d7c 100644 --- a/include/drivers/st/stm32mp1_pwr.h +++ b/include/drivers/st/stm32mp1_pwr.h @@ -26,6 +26,8 @@ #define PWR_CR2_BREN BIT(0) #define PWR_CR2_RREN BIT(1) +#define PWR_CR2_BRRDY BIT(16) +#define PWR_CR2_RRRDY BIT(17) #define PWR_CR3_VBE BIT(8) #define PWR_CR3_VBRS BIT(9) diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h index 7e1b337..903a0d3 100644 --- a/include/drivers/st/stm32mp1_rcc.h +++ b/include/drivers/st/stm32mp1_rcc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -387,7 +387,8 @@ #define RCC_HSICFGR_HSITRIM_SHIFT 8 #define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) #define RCC_HSICFGR_HSICAL_SHIFT 16 -#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) +#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) +#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) /* Fields of RCC_CSICFGR register */ #define RCC_CSICFGR_CSITRIM_SHIFT 8 @@ -470,6 +471,9 @@ #define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) #define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +/* Values of RCC_AHB6RSTSETR register */ +#define RCC_AHB6RSTSETR_GPURST BIT(5) + /* Values of RCC_MP_IWDGFZSETR register */ #define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) #define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) @@ -477,4 +481,82 @@ /* Values of RCC_PWRLPDLYCR register */ #define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +/* RCC_I2C46CKSELR register fields */ +#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0) +#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0 + +/* RCC_SPI6CKSELR register fields */ +#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0) +#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0 + +/* RCC_UART1CKSELR register fields */ +#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART1CKSELR_UART1SRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C35CKSELR register fields */ +#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0) +#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART24CKSELR register fields */ +#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0) +#define RCC_UART24CKSELR_UART24SRC_SHIFT 0 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0 + +/* RCC_SDMMC3CKSELR register fields */ +#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0 + +/* RCC_ETHCKSELR register fields */ +#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0) +#define RCC_ETHCKSELR_ETHSRC_SHIFT 0 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(2, 0) +#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + #endif /* STM32MP1_RCC_H */ diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index aa34b9c..f3ded20 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -460,8 +460,9 @@ #define HSTR p15, 4, c1, c1, 3 #define CNTHCTL p15, 4, c14, c1, 0 #define CNTKCTL p15, 0, c14, c1, 0 -#define CNTPTVAL p15, 0, c14, c2, 0 -#define CNTPCTL p15, 0, c14, c2, 1 +#define CNTP_TVAL p15, 0, c14, c2, 0 +#define CNTP_CTL p15, 0, c14, c2, 1 +#define CNTV_CTL p15, 0, c14, c3, 1 #define VPIDR p15, 4, c0, c0, 0 #define VMPIDR p15, 4, c0, c0, 5 #define ISR p15, 0, c12, c1, 0 diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h index e48123c..9d56fc5 100644 --- a/include/lib/aarch32/arch_helpers.h +++ b/include/lib/aarch32/arch_helpers.h @@ -261,8 +261,9 @@ DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64) DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64) DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR) DEFINE_COPROCR_RW_FUNCS(hstr, HSTR) -DEFINE_COPROCR_RW_FUNCS(cntptval, CNTPTVAL) -DEFINE_COPROCR_RW_FUNCS(cntpctl, CNTPCTL) +DEFINE_COPROCR_RW_FUNCS(cntp_tval, CNTP_TVAL) +DEFINE_COPROCR_RW_FUNCS(cntp_ctl, CNTP_CTL) +DEFINE_COPROCR_RW_FUNCS(cntv_ctl, CNTV_CTL) DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE) DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c index 263c3ba..d483c18 100644 --- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -159,7 +159,7 @@ enum { IMG_IDX_NUM }; -static struct stm32image_device_info stm32image_dev_info_spec = { +static struct stm32image_device_info stm32image_dev_info_spec __unused = { .lba_size = MMC_BLOCK_SIZE, .part_info[IMG_IDX_BL33] = { .name = BL33_IMAGE_NAME, @@ -186,7 +186,7 @@ static io_block_spec_t stm32image_block_spec = { .length = 0, }; -static const io_dev_connector_t *stm32image_dev_con; +static const io_dev_connector_t *stm32image_dev_con __unused; static int open_dummy(const uintptr_t spec); static int open_image(const uintptr_t spec); @@ -305,7 +305,7 @@ static void print_boot_device(boot_api_context_t *boot_context) } } -#if STM32MP_EMMC || STM32MP_SDMMC +#if STM32MP_SDMMC static void print_bootrom_sd_status(boot_api_context_t *boot_context) { if (boot_context->sd_err_internal_timeout_cnt != 0U) { @@ -338,7 +338,9 @@ static void print_bootrom_sd_status(boot_api_context_t *boot_context) boot_context->sd_overall_retry_cnt); } } +#endif +#if STM32MP_EMMC static void print_bootrom_emmc_status(boot_api_context_t *boot_context) { INFO("BootROM: %d (0x%x) bytes copied from eMMC\n", @@ -399,342 +401,344 @@ static void print_bootrom_emmc_status(boot_api_context_t *boot_context) } #endif - -void stm32mp_io_setup(void) +#if STM32MP_EMMC || STM32MP_SDMMC +static void boot_mmc(enum mmc_device_type mmc_dev_type, + uint16_t boot_interface_instance) { int io_result __unused; uint8_t idx; struct stm32image_part_info *part; -#if STM32MP_UART_PROGRAMMER - uintptr_t uart_addr; -#endif -#if STM32MP_SDMMC || STM32MP_EMMC struct stm32_sdmmc2_params params; struct mmc_device_info device_info; - uintptr_t mmc_default_instance; const partition_entry_t *entry; -#endif -#ifdef STM32MP_USB - struct usb_ctx *usb_context; -#endif - boot_api_context_t *boot_context = - (boot_api_context_t *)stm32mp_get_boot_ctx_address(); - print_boot_device(boot_context); + zeromem(&device_info, sizeof(struct mmc_device_info)); + zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); - if ((boot_context->boot_partition_used_toboot == 1U) || - (boot_context->boot_partition_used_toboot == 2U)) { - INFO("Boot used partition fsbl%d\n", - boot_context->boot_partition_used_toboot); - } + device_info.mmc_dev_type = mmc_dev_type; - io_result = register_io_dev_dummy(&dummy_dev_con); - assert(io_result == 0); + switch (boot_interface_instance) { + case 1: + params.reg_base = STM32MP_SDMMC1_BASE; + break; + case 2: + params.reg_base = STM32MP_SDMMC2_BASE; + break; + case 3: + params.reg_base = STM32MP_SDMMC3_BASE; + break; + default: + WARN("SDMMC instance not found, using default\n"); + if (mmc_dev_type == MMC_IS_SD) { + params.reg_base = STM32MP_SDMMC1_BASE; + } else { + params.reg_base = STM32MP_SDMMC2_BASE; + } + break; + } - io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, - &dummy_dev_handle); - assert(io_result == 0); + params.device_info = &device_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); + panic(); + } - switch (boot_context->boot_interface_selected) { - case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: - case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: - dmbsy(); + /* Open MMC as a block device to read GPT table */ + io_result = register_io_dev_block(&mmc_dev_con); + if (io_result != 0) { + panic(); + } -#if STM32MP_EMMC || STM32MP_SDMMC - memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params)); + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec, + &storage_dev_handle); + assert(io_result == 0); - if (boot_context->boot_interface_selected == - BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) { - device_info.mmc_dev_type = MMC_IS_EMMC; - print_bootrom_emmc_status(boot_context); -#if STM32MP_EMMC - mmc_default_instance = STM32MP_SDMMC2_BASE; -#else - ERROR("MMC driver is not enabled\n"); - panic(); -#endif - } else { - device_info.mmc_dev_type = MMC_IS_SD; - print_bootrom_sd_status(boot_context); -#if STM32MP_SDMMC - mmc_default_instance = STM32MP_SDMMC1_BASE; -#else - ERROR("MMC driver is not enabled\n"); - panic(); -#endif - } + partition_init(GPT_IMAGE_ID); - switch (boot_context->boot_interface_instance) { - case 1: - params.reg_base = STM32MP_SDMMC1_BASE; - break; - case 2: - params.reg_base = STM32MP_SDMMC2_BASE; - break; - case 3: - params.reg_base = STM32MP_SDMMC3_BASE; - break; - default: - WARN("SDMMC instance not found, using default\n"); - params.reg_base = mmc_default_instance; - break; - } + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); - params.device_info = &device_info; - if (stm32_sdmmc2_mmc_init(¶ms) != 0) { - ERROR("SDMMC%u init failed\n", - boot_context->boot_interface_instance); - panic(); - } + stm32image_dev_info_spec.device_size = + stm32_sdmmc2_mmc_get_device_size(); - /* Open MMC as a block device to read GPT table */ - io_result = register_io_dev_block(&mmc_dev_con); - if (io_result != 0) { + for (idx = 0U; idx < IMG_IDX_NUM; idx++) { + part = &stm32image_dev_info_spec.part_info[idx]; + entry = get_partition_entry(part->name); + if (entry == NULL) { + ERROR("Partition %s not found\n", part->name); panic(); } - io_result = io_dev_open(mmc_dev_con, - (uintptr_t)&mmc_block_dev_spec, - &storage_dev_handle); - assert(io_result == 0); - - partition_init(GPT_IMAGE_ID); - - io_result = io_dev_close(storage_dev_handle); - assert(io_result == 0); + part->part_offset = entry->start; + part->bkp_offset = 0U; + } - stm32image_dev_info_spec.device_size = - stm32_sdmmc2_mmc_get_device_size(); + /* + * Re-open MMC with io_mmc, for better perfs compared to + * io_block. + */ + io_result = register_io_dev_mmc(&mmc_dev_con); + assert(io_result == 0); - for (idx = 0U; idx < IMG_IDX_NUM; idx++) { - part = &stm32image_dev_info_spec.part_info[idx]; - entry = get_partition_entry(part->name); - if (entry == NULL) { - ERROR("Partition %s not found\n", - part->name); - panic(); - } + io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle); + assert(io_result == 0); - part->part_offset = entry->start; - part->bkp_offset = 0U; - } + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); - /* - * Re-open MMC with io_mmc, for better perfs compared to - * io_block. - */ - io_result = register_io_dev_mmc(&mmc_dev_con); - assert(io_result == 0); - - io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle); - assert(io_result == 0); - - io_result = register_io_dev_stm32image(&stm32image_dev_con); - assert(io_result == 0); - - io_result = io_dev_open(stm32image_dev_con, - (uintptr_t)&stm32image_dev_info_spec, - &image_dev_handle); - assert(io_result == 0); -#else /* STM32MP_EMMC || STM32MP_SDMMC */ - ERROR("EMMC or SDMMC driver not enabled\n"); - panic(); -#endif /* STM32MP_EMMC || STM32MP_SDMMC */ - break; + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} +#endif #if STM32MP1_QSPI_NOR - case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: - dmbsy(); +static void boot_qspi_nor(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; - io_result = register_io_dev_qspi(&qspi_dev_con); + io_result = register_io_dev_qspi(&qspi_dev_con); + assert(io_result == 0); - assert(io_result == 0); - switch (boot_context->boot_interface_instance) { - case 1: - qspi_dev_spec.instance = - (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; - break; - default: - WARN("NOR instance not found, using default\n"); - qspi_dev_spec.instance = - (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; - break; - } - qspi_dev_spec.is_dual = boot_context->nor_isdual; + if (boot_context->boot_interface_instance != 1U) { + WARN("NOR instance not found, using default\n"); + } - /* Open connections to devices and cache the handles */ - io_result = io_dev_open(qspi_dev_con, - (uintptr_t)&qspi_dev_spec, - &storage_dev_handle); - assert(io_result == 0); + qspi_dev_spec.instance = (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE; + qspi_dev_spec.is_dual = boot_context->nor_isdual; - stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE; - stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE; + /* Open connections to devices */ + io_result = io_dev_open(qspi_dev_con, + (uintptr_t)&qspi_dev_spec, + &storage_dev_handle); + assert(io_result == 0); - idx = IMG_IDX_BL33; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NOR_BL33_OFFSET; - part->bkp_offset = QSPI_NOR_BLK_SIZE; + stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE; + stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_SIZE; -#ifdef AARCH32_SP_OPTEE - idx = IMG_IDX_OPTEE_HEADER; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NOR_TEEH_OFFSET; - part->bkp_offset = QSPI_NOR_BLK_SIZE; - - idx = IMG_IDX_OPTEE_PAGED; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NOR_TEED_OFFSET; - part->bkp_offset = QSPI_NOR_BLK_SIZE; + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_BL33_OFFSET; + part->bkp_offset = QSPI_NOR_BLK_SIZE; - idx = IMG_IDX_OPTEE_PAGER; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NOR_TEEX_OFFSET; - part->bkp_offset = QSPI_NOR_BLK_SIZE; +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEH_OFFSET; + part->bkp_offset = QSPI_NOR_BLK_SIZE; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEED_OFFSET; + part->bkp_offset = QSPI_NOR_BLK_SIZE; + + idx = IMG_IDX_OPTEE_PAGER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEX_OFFSET; + part->bkp_offset = QSPI_NOR_BLK_SIZE; #endif - io_result = register_io_dev_stm32image(&stm32image_dev_con); - assert(io_result == 0); + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); - io_result = io_dev_open(stm32image_dev_con, - (uintptr_t)&stm32image_dev_info_spec, - &image_dev_handle); - assert(io_result == 0); - break; + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} #endif - case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: - #if STM32MP_FMC_NAND - dmbsy(); - - /* Register the IO devices on this platform */ - io_result = register_io_dev_nand(&nand_dev_con); - assert(io_result == 0); - - nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE; - nand_dev_spec.Info.PageSize = boot_context->nand_page_size; - nand_dev_spec.Info.BlockSize = boot_context->nand_block_size; - nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb; - nand_dev_spec.Info.BusWidth = boot_context->nand_data_width; - nand_dev_spec.Info.ECCcorrectability = - boot_context->nand_ecc_bits; - - /* Open connections to devices and cache the handles */ - io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, - &storage_dev_handle); - assert(io_result == 0); - - stm32image_dev_info_spec.device_size = - nand_dev_spec.Info.PageSize * - nand_dev_spec.Info.BlockSize * - nand_dev_spec.Info.BlockNb; - stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR; - - idx = IMG_IDX_BL33; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NAND_BL33_OFFSET; - part->bkp_offset = nand_dev_spec.Info.PageSize * - nand_dev_spec.Info.BlockSize; +static void boot_fmc_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; -#ifdef AARCH32_SP_OPTEE - idx = IMG_IDX_OPTEE_HEADER; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NAND_TEEH_OFFSET; - part->bkp_offset = nand_dev_spec.Info.PageSize * - nand_dev_spec.Info.BlockSize; + /* Register the IO devices on this platform */ + io_result = register_io_dev_nand(&nand_dev_con); + assert(io_result == 0); - idx = IMG_IDX_OPTEE_PAGED; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NAND_TEED_OFFSET; - part->bkp_offset = nand_dev_spec.Info.PageSize * - nand_dev_spec.Info.BlockSize; + nand_dev_spec.Instance = (FMC_TypeDef *)STM32MP_FMC_BASE; + nand_dev_spec.Info.PageSize = boot_context->nand_page_size; + nand_dev_spec.Info.BlockSize = boot_context->nand_block_size; + nand_dev_spec.Info.BlockNb = boot_context->nand_block_nb; + nand_dev_spec.Info.BusWidth = boot_context->nand_data_width; + nand_dev_spec.Info.ECCcorrectability = + boot_context->nand_ecc_bits; + + /* Open connections to devices */ + io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); - idx = IMG_IDX_OPTEE_PAGER; - part = &stm32image_dev_info_spec.part_info[idx]; - part->part_offset = STM32MP_NAND_TEEX_OFFSET; - part->bkp_offset = nand_dev_spec.Info.PageSize * - nand_dev_spec.Info.BlockSize; + stm32image_dev_info_spec.device_size = + nand_dev_spec.Info.PageSize * + nand_dev_spec.Info.BlockSize * + nand_dev_spec.Info.BlockNb; + stm32image_dev_info_spec.lba_size = BCH_PAGE_SECTOR; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = nand_dev_spec.Info.PageSize * + nand_dev_spec.Info.BlockSize; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = nand_dev_spec.Info.PageSize * + nand_dev_spec.Info.BlockSize; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = nand_dev_spec.Info.PageSize * + nand_dev_spec.Info.BlockSize; + + idx = IMG_IDX_OPTEE_PAGER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = nand_dev_spec.Info.PageSize * + nand_dev_spec.Info.BlockSize; #endif - io_result = register_io_dev_stm32image(&stm32image_dev_con); - assert(io_result == 0); + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); - io_result = io_dev_open(stm32image_dev_con, - (uintptr_t)&stm32image_dev_info_spec, - &image_dev_handle); - assert(io_result == 0); -#else - ERROR("FMC NAND driver is not enabled\n"); - panic(); + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} #endif - break; #if STM32MP_UART_PROGRAMMER - case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: +static void flash_uart(uint16_t boot_interface_instance) +{ + int io_result __unused; + uintptr_t uart_addr; - /* Register the IO devices on this platform */ - io_result = register_io_dev_uart(&uart_dev_con); - assert(io_result == 0); + /* Register the IO devices on this platform */ + io_result = register_io_dev_uart(&uart_dev_con); + assert(io_result == 0); - uart_programmer.Init.WordLength = UART_WORDLENGTH_9B; - uart_programmer.Init.Parity = UART_PARITY_EVEN; - uart_addr = - get_uart_address(boot_context->boot_interface_instance); + uart_programmer.Init.WordLength = UART_WORDLENGTH_9B; + uart_programmer.Init.Parity = UART_PARITY_EVEN; + uart_addr = get_uart_address(boot_interface_instance); - if (uart_addr) { - uart_programmer.Instance = (USART_TypeDef *)uart_addr; - } else { - WARN("UART instance not found, using default\n"); - uart_programmer.Instance = (USART_TypeDef *)USART2_BASE; - } + if (uart_addr != 0U) { + uart_programmer.Instance = (USART_TypeDef *)uart_addr; + } else { + WARN("UART instance not found, using default\n"); + uart_programmer.Instance = (USART_TypeDef *)USART2_BASE; + } - /* Open connections to devices and cache the handles */ - io_result = io_dev_open(uart_dev_con, - (uintptr_t)&uart_programmer, - &image_dev_handle); - assert(!io_result); - break; + /* Open connections to devices */ + io_result = io_dev_open(uart_dev_con, (uintptr_t)&uart_programmer, + &image_dev_handle); + assert(!io_result); +} #endif #ifdef STM32MP_USB - case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: - usb_context = (struct usb_ctx *)boot_context->usb_context; +static void flash_usb(struct usb_ctx *usb_context) +{ + int io_result __unused; - pcd_handle.in_ep[0].maxpacket = 0x40; - pcd_handle.out_ep[0].maxpacket = 0x40; + pcd_handle.in_ep[0].maxpacket = 0x40; + pcd_handle.out_ep[0].maxpacket = 0x40; - pcd_handle.state = HAL_PCD_STATE_READY; + pcd_handle.state = HAL_PCD_STATE_READY; - usb_core_handle.data = &pcd_handle; + usb_core_handle.data = &pcd_handle; - usb_dwc2_init_driver(&usb_core_handle, - (uint32_t *)USB_OTG_BASE); + usb_dwc2_init_driver(&usb_core_handle, + (uint32_t *)USB_OTG_BASE); - usb_dfu_register_callback(&usb_core_handle); + usb_dfu_register_callback(&usb_core_handle); - stm32mp_usb_init_desc(&usb_core_handle); + stm32mp_usb_init_desc(&usb_core_handle); - usb_core_handle.ep_in[0].maxpacket = 0x40; - usb_core_handle.ep_out[0].maxpacket = 0x40; + usb_core_handle.ep_in[0].maxpacket = 0x40; + usb_core_handle.ep_out[0].maxpacket = 0x40; - usb_core_handle.ep0_state = - usb_context->pusbd_device_ctx->ep0_state; - usb_core_handle.dev_state = USBD_STATE_CONFIGURED; + usb_core_handle.ep0_state = + usb_context->pusbd_device_ctx->ep0_state; + usb_core_handle.dev_state = USBD_STATE_CONFIGURED; - usb_core_handle.class_data = &usb_dfu_handle; - usb_dfu_handle.dev_state = DFU_STATE_IDLE; + usb_core_handle.class_data = &usb_dfu_handle; + usb_dfu_handle.dev_state = DFU_STATE_IDLE; - /* Register the IO devices on this platform */ - io_result = register_io_dev_usb(&usb_dev_con); - assert(io_result == 0); + /* Register the IO devices on this platform */ + io_result = register_io_dev_usb(&usb_dev_con); + assert(io_result == 0); - /* Open connections to devices and cache the handles */ - io_result = io_dev_open(usb_dev_con, - (uintptr_t)&usb_core_handle, - &image_dev_handle); + /* Open connections to devices */ + io_result = io_dev_open(usb_dev_con, + (uintptr_t)&usb_core_handle, + &image_dev_handle); - assert(io_result == 0); + assert(io_result == 0); +} +#endif + +void stm32mp_io_setup(void) +{ + int io_result __unused; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + + print_boot_device(boot_context); + + if ((boot_context->boot_partition_used_toboot == 1U) || + (boot_context->boot_partition_used_toboot == 2U)) { + INFO("Boot used partition fsbl%d\n", + boot_context->boot_partition_used_toboot); + } + + io_result = register_io_dev_dummy(&dummy_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, + &dummy_dev_handle); + assert(io_result == 0); + + switch (boot_context->boot_interface_selected) { +#if STM32MP_SDMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + print_bootrom_sd_status(boot_context); + boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); + break; +#endif +#if STM32MP_EMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + print_bootrom_emmc_status(boot_context); + boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); + break; +#endif +#if STM32MP1_QSPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + boot_qspi_nor(boot_context); + break; +#endif +#if STM32MP_FMC_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + boot_fmc_nand(boot_context); + break; +#endif +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + flash_uart(boot_context->boot_interface_instance); + break; +#endif +#ifdef STM32MP_USB + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + flash_usb((struct usb_ctx *)boot_context->usb_context); break; #endif #ifdef STM32MP1_QSPI_NAND diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h index 70f8202..b5a2bf9 100644 --- a/plat/st/common/include/stm32mp_auth.h +++ b/plat/st/common/include/stm32mp_auth.h @@ -9,6 +9,14 @@ #include +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 #include +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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -203,9 +204,9 @@ enum ddr_type { #define STM32MP_NAND_BL33_OFFSET U(0x00200000) #ifdef AARCH32_SP_OPTEE -#define STM32MP_NAND_TEEH_OFFSET U(0x00400000) -#define STM32MP_NAND_TEED_OFFSET U(0x00480000) -#define STM32MP_NAND_TEEX_OFFSET U(0x00500000) +#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) +#define STM32MP_NAND_TEED_OFFSET U(0x00680000) +#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) #endif /******************************************************************************* @@ -374,7 +375,6 @@ enum ddr_type { #define UID2_OTP U(15) #define PACKAGE_OTP U(16) #define HW2_OTP U(18) /* HW watchdog OTP */ -#define BOARD_OTP U(59) /* OTP mask */ /* DATA0 */ @@ -393,6 +393,9 @@ enum ddr_type { #define IWDG_FZ_STOP_POS 5 #define IWDG_FZ_STANDBY_POS 7 +/* HW2 OTP */ +#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + /* NAND OTP */ /* NAND parameter storage flag */ #define NAND_PARAM_STORED_IN_OTP U(0x80000000) @@ -447,7 +450,12 @@ enum ddr_type { #define PLAT_MAX_TAMP_INT U(5) #define PLAT_MAX_TAMP_EXT U(3) #define TAMP_BASE U(0x5C00A000) +#define TAMP_SMCR (TAMP_BASE + U(0x20)) #define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) +#define TAMP_BKP_SEC_NUMBER U(10) +#define TAMP_BKP_SEC_WDPROT_SHIFT U(16) +#define TAMP_BKP_SEC_RWDPROT_SHIFT U(0) + #if !(defined(__LINKER__) || defined(__ASSEMBLY__)) static inline uint32_t tamp_bkpr(uint32_t idx) @@ -523,6 +531,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx) /******************************************************************************* * Device Tree defines ******************************************************************************/ +#define DT_BSEC_COMPAT "st,stm32mp15-bsec" #define DT_PWR_COMPAT "st,stm32mp1-pwr" #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" #define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 1adaaee..afaa1f4 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -311,15 +311,20 @@ func plat_crash_console_putc b console_stm32_core_putc endfunc plat_crash_console_putc - /* ----------------------------------------------------- + /* ---------------------------------------------------------- * void plat_panic_handler(void) __dead2; * Report exception + endless loop. - * ----------------------------------------------------- + * + * r6 holds the address where the fault occurred. + * Filling lr with this value allows debuggers to reconstruct + * the backtrace. + * ---------------------------------------------------------- */ func plat_panic_handler mrs r0, cpsr and r0, #MODE32_MASK bl plat_report_exception + mov lr, r6 b . endfunc plat_panic_handler @@ -363,8 +368,8 @@ func wfi_svc_int_enable str r4, [sp, #SMC_CTX_SCR] cps #MODE32_svc cpsie af - isb dsb + isb wfi cpsid af cps #MODE32_mon diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c index de9035c..f8b35dd 100644 --- a/plat/st/stm32mp1/stm32mp1_low_power.c +++ b/plat/st/stm32mp1/stm32mp1_low_power.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -129,6 +129,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) uintptr_t pwr_base = stm32mp_pwr_base(); uintptr_t rcc_base = stm32mp_rcc_base(); + stm32mp1_syscfg_disable_io_compensation(); + dcsw_op_all(DC_OP_CISW); stm32_clean_context(); @@ -141,6 +143,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) stm32_save_ddr_training_area(); } + stm32mp1_clk_mpu_suspend(); + if (dt_pmic_status() > 0) { stm32_apply_pmic_suspend_config(mode); @@ -186,7 +190,6 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) mmio_write_32(bkpr_core1_magic, 0); if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) { - /* * Save non-secure world entrypoint after standby in Backup * register @@ -198,6 +201,14 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) if (stm32_save_context(zq0cr0_zdata) != 0) { panic(); } + + /* Keep retention and backup RAM content in standby */ + mmio_setbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | + PWR_CR2_RREN); + while ((mmio_read_32(pwr_base + PWR_CR2) & + (PWR_CR2_BRRDY | PWR_CR2_RRRDY)) == 0U) { + ; + } } stm32mp_clk_disable(RTCAPB); @@ -212,6 +223,7 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) */ void stm32_exit_cstop(void) { + uintptr_t pwr_base = stm32mp_pwr_base(); uintptr_t rcc_base = stm32mp_rcc_base(); if (!enter_cstop_done) { @@ -220,6 +232,8 @@ void stm32_exit_cstop(void) enter_cstop_done = false; + stm32mp1_clk_mpu_resume(); + if (ddr_sw_self_refresh_exit() != 0) { panic(); } @@ -236,6 +250,9 @@ void stm32_exit_cstop(void) dsb(); isb(); + /* Disable retention and backup RAM content after stop */ + mmio_clrbits_32(pwr_base + PWR_CR2, PWR_CR2_BREN | PWR_CR2_RREN); + /* Update STGEN counter with low power mode duration */ stm32_rtc_get_calendar(¤t_calendar); @@ -243,10 +260,17 @@ void stm32_exit_cstop(void) &sleep_time); stm32mp1_stgen_increment(stdby_time_in_ms); + + stm32mp1_syscfg_enable_io_compensation(); } static void enter_shutdown(void) { + /* Set DDR in Self-refresh before shutting down the platform */ + if (ddr_standby_sr_entry(NULL) != 0) { + WARN("DDR can't be set in Self-refresh mode\n"); + } + if (dt_pmic_status() > 0) { if (!initialize_pmic_i2c()) { panic(); @@ -294,10 +318,10 @@ void stm32_pwr_down_wfi(void) { uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; - stm32mp1_rcc_set_wakeup(false); + stm32mp1_calib_set_wakeup(false); while (interrupt == GIC_SPURIOUS_INTERRUPT && - !stm32mp1_rcc_get_wakeup()) { + !stm32mp1_calib_get_wakeup()) { wfi_svc_int_enable((uintptr_t)&int_stack[0]); interrupt = gicv2_acknowledge_interrupt(); diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 20a2f5c..b95bc3d 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -40,11 +40,12 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) assert(cpu_state == ARM_LOCAL_STATE_RET); /* - * Enter standby state - * dsb is good practice before using wfi to enter low power states + * Enter standby state. + * Synchronize on memory accesses and instruction flow before the WFI + * instruction. */ - isb(); dsb(); + isb(); while (interrupt == GIC_SPURIOUS_INTERRUPT) { wfi(); @@ -85,6 +86,9 @@ static int stm32_pwr_domain_on(u_register_t mpidr) return PSCI_E_INVALID_PARAMS; } + /* Reset backup register content */ + mmio_write_32(bkpr_core1_magic, 0); + /* Need to send additional IT 0 after individual core 1 reset */ gicv2_raise_sgi(ARM_IRQ_NON_SEC_SGI_0, STM32MP_SECONDARY_CPU); @@ -183,9 +187,12 @@ static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPUP1RST); - /* wfi is required for an auto-reset */ - isb(); + /* + * Synchronize on memory accesses and instruction flow before + * auto-reset from the WFI instruction. + */ dsb(); + isb(); wfi(); /* This shouldn't be reached */ diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index c1f4c82..aae537f 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,8 +15,26 @@ #include #include #include +#include #include +/* 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 @@ -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 #include +#include #include #include #include +#include #include #include @@ -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