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

45591 lines
1.3 MiB

From b378eb77ad6177d7bd5cb1a5befc4b0c52f70e2c Mon Sep 17 00:00:00 2001
From: christophe montaud <christophe.montaud@st.com>
Date: Tue, 29 Jan 2019 18:16:44 +0100
Subject: [PATCH] st update r1
---
.checkpatch.conf | 18 +
Makefile | 56 +-
bl2/aarch32/bl2_arch_setup.c | 1 +
bl2/aarch32/bl2_el3_entrypoint.S | 4 +
bl2/aarch32/bl2_el3_exceptions.S | 9 +
bl2/aarch32/bl2_entrypoint.S | 9 +
bl2/bl2_image_load_v2.c | 14 +-
bl2/bl2_private.h | 3 +
bl2u/aarch32/bl2u_entrypoint.S | 9 +
bl32/sp_min/aarch32/entrypoint.S | 9 +
common/aarch32/debug.S | 54 +-
docs/devicetree/bindings/arm/secure.txt | 53 +
docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt | 324 +++
docs/devicetree/bindings/i2c/i2c-stm32.txt | 54 +
docs/devicetree/bindings/mmc/mmci.txt | 72 +
docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt | 22 +
docs/devicetree/bindings/power/st,stm32mp1-pwr.txt | 42 +
docs/devicetree/bindings/power/st,stpmic1.txt | 132 ++
docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt | 6 +
docs/devicetree/bindings/rng/st,stm32-rng.txt | 23 +
docs/devicetree/bindings/serial/st,stm32-usart.txt | 88 +
docs/devicetree/bindings/soc/st,stm32-etzpc.txt | 56 +
docs/devicetree/bindings/soc/st,stm32-romem.txt | 31 +
docs/devicetree/bindings/soc/st,stm32-stgen.txt | 18 +
docs/devicetree/bindings/soc/st,stm32-tamp.txt | 22 +
.../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 28 +
docs/plat/stm32mp1.rst | 16 +
docs/porting-guide.rst | 44 +-
drivers/arm/pl011/aarch32/pl011_console.S | 139 +-
drivers/arm/pl011/aarch64/pl011_console.S | 3 +-
drivers/arm/tzc/tzc400.c | 129 ++
drivers/cadence/uart/aarch64/cdns_console.S | 4 +-
drivers/console/aarch32/console.S | 105 +-
drivers/console/aarch32/deprecated_console.S | 112 +
drivers/console/aarch32/multi_console.S | 318 +++
drivers/console/aarch64/skeleton_console.S | 9 +-
.../coreboot/cbmem_console/aarch64/cbmem_console.S | 3 +-
drivers/io/io_block.c | 8 +-
drivers/io/io_memmap.c | 5 +-
drivers/io/io_semihosting.c | 4 +-
drivers/io/io_storage.c | 2 +-
drivers/mmc/mmc.c | 23 +-
drivers/partition/gpt.c | 10 +-
drivers/partition/partition.c | 2 +-
drivers/st/bsec/bsec.c | 911 ++++++++
drivers/st/clk/stm32mp1_clk.c | 2247 +++++++++++++++-----
drivers/st/clk/stm32mp1_clkfunc.c | 211 +-
drivers/st/clk/stm32mp_clkfunc.c | 307 +++
drivers/st/ddr/stm32mp1_ddr.c | 484 +++--
drivers/st/ddr/stm32mp1_ddr_helpers.c | 510 ++++-
drivers/st/ddr/stm32mp1_ram.c | 194 +-
drivers/st/etzpc/etzpc.c | 310 +++
drivers/st/gpio/stm32_gpio.c | 267 ++-
drivers/st/hash/hash_sec.c | 369 ++++
drivers/st/i2c/stm32_i2c.c | 1371 ++++++++++++
drivers/st/io/io_mmc.c | 134 ++
drivers/st/io/io_programmer_st_usb.c | 379 ++++
drivers/st/io/io_stm32image.c | 381 ++++
drivers/st/iwdg/stm32_iwdg.c | 289 +++
drivers/st/mmc/stm32_sdmmc2.c | 752 +++++++
drivers/st/nand/io_nand.c | 228 ++
drivers/st/nand/nand.c | 1548 ++++++++++++++
drivers/st/pmic/stm32_i2c.c | 851 --------
drivers/st/pmic/stm32mp1_pmic.c | 346 ---
drivers/st/pmic/stm32mp_pmic.c | 522 +++++
drivers/st/pmic/stpmic1.c | 817 +++++++
drivers/st/pmic/stpmu1.c | 600 ------
drivers/st/qspi/io_qspi.c | 349 +++
drivers/st/reset/stm32mp1_reset.c | 64 +-
drivers/st/rng/stm32_rng.c | 191 ++
drivers/st/rtc/stm32_rtc.c | 499 +++++
drivers/st/tamper/stm32_tamp.c | 375 ++++
drivers/st/timer/stm32_timer.c | 297 +++
drivers/st/uart/aarch32/stm32_console.S | 151 +-
drivers/st/uart/io_programmer_uart.c | 597 ++++++
drivers/st/uart/stm32mp1xx_hal_uart.c | 799 +++++++
drivers/st/usb_dwc2/usb_dwc2.c | 858 ++++++++
drivers/ti/uart/aarch64/16550_console.S | 3 +-
fdts/stm32mp15-ddr.dtsi | 2 +-
fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 121 ++
fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 19 +-
fdts/stm32mp157-pinctrl.dtsi | 154 +-
fdts/stm32mp157a-dk1.dts | 464 ++++
fdts/stm32mp157c-dk2.dts | 16 +
fdts/stm32mp157c-ed1.dts | 342 ++-
fdts/stm32mp157c-ev1.dts | 52 +-
fdts/stm32mp157c-security.dtsi | 71 +
fdts/stm32mp157c.dtsi | 215 +-
fdts/stm32mp157caa-pinctrl.dtsi | 8 +-
fdts/stm32mp157cab-pinctrl.dtsi | 62 +
fdts/stm32mp157cac-pinctrl.dtsi | 78 +
fdts/stm32mp157cad-pinctrl.dtsi | 62 +
include/common/aarch32/console_macros.S | 84 +
include/common/aarch64/console_macros.S | 46 +-
include/common/tbbr/tbbr_img_def.h | 8 +-
include/drivers/arm/tzc400.h | 4 +
include/drivers/io/io_driver.h | 2 +-
include/drivers/io/io_storage.h | 8 +-
include/drivers/st/bsec.h | 205 ++
include/drivers/st/etzpc.h | 32 +
include/drivers/st/hash_sec.h | 113 +
include/drivers/st/io_mmc.h | 14 +
include/drivers/st/io_nand.h | 19 +
include/drivers/st/io_programmer.h | 51 +
include/drivers/st/io_programmer_st_usb.h | 20 +
include/drivers/st/io_qspi.h | 92 +
include/drivers/st/io_stm32image.h | 32 +
include/drivers/st/io_uart.h | 12 +
include/drivers/st/nand.h | 252 +++
include/drivers/st/stm32_console.h | 34 +
include/drivers/st/stm32_gpio.h | 68 +-
include/drivers/st/stm32_hal_hash_reg.h | 136 ++
include/drivers/st/stm32_i2c.h | 303 +--
include/drivers/st/stm32_iwdg.h | 20 +
include/drivers/st/stm32_rng.h | 13 +
include/drivers/st/stm32_rtc.h | 79 +
include/drivers/st/stm32_sdmmc2.h | 31 +
include/drivers/st/stm32_tamp.h | 163 ++
include/drivers/st/stm32_timer.h | 21 +
include/drivers/st/stm32_uart_regs.h | 199 ++
include/drivers/st/stm32mp1_clk.h | 71 +-
include/drivers/st/stm32mp1_clkfunc.h | 18 +-
include/drivers/st/stm32mp1_ddr.h | 13 +-
include/drivers/st/stm32mp1_ddr_helpers.h | 14 +-
include/drivers/st/stm32mp1_ddr_regs.h | 15 +-
include/drivers/st/stm32mp1_pmic.h | 18 -
include/drivers/st/stm32mp1_pwr.h | 31 +-
include/drivers/st/stm32mp1_ram.h | 6 +-
include/drivers/st/stm32mp1_rcc.h | 138 +-
include/drivers/st/stm32mp1_reset.h | 15 -
include/drivers/st/stm32mp1xx_hal.h | 203 ++
include/drivers/st/stm32mp1xx_hal_uart.h | 1586 ++++++++++++++
include/drivers/st/stm32mp1xx_hal_uart_ex.h | 87 +
include/drivers/st/stm32mp_clkfunc.h | 28 +
include/drivers/st/stm32mp_pmic.h | 24 +
include/drivers/st/stm32mp_reset.h | 15 +
include/drivers/st/stpmic1.h | 173 ++
include/drivers/st/stpmu1.h | 141 --
include/drivers/st/usb_dwc2.h | 443 ++++
include/dt-bindings/interrupt-controller/arm-gic.h | 21 +
include/dt-bindings/pinctrl/stm32-pinfunc.h | 6 +
include/dt-bindings/power/stm32mp1-power.h | 19 +
include/dt-bindings/soc/st,stm32-etzpc.h | 107 +
include/lib/aarch32/arch.h | 14 +
include/lib/aarch32/arch_helpers.h | 3 +
include/lib/cpus/aarch32/cortex_a9.h | 5 +
include/lib/optee_utils.h | 1 +
include/lib/psci/psci.h | 8 +-
include/lib/usb/usb_core.h | 352 +++
include/lib/usb/usb_st_dfu.h | 115 +
include/lib/utils.h | 29 +-
include/lib/utils_def.h | 20 +-
include/lib/xlat_tables/xlat_tables_v2_helpers.h | 41 +-
include/plat/common/platform.h | 5 +
lib/compiler-rt/builtins/int_lib.h | 13 +-
lib/compiler-rt/builtins/lshrdi3.c | 45 +
lib/compiler-rt/compiler-rt.mk | 3 +-
lib/libfdt/fdt_ro.c | 2 +-
lib/optee/optee_utils.c | 30 +
lib/usb/usb_core.c | 732 +++++++
lib/usb/usb_st_dfu.c | 865 ++++++++
lib/xlat_tables/aarch32/xlat_tables.c | 9 +
lib/xlat_tables/aarch64/xlat_tables.c | 4 +
lib/xlat_tables/xlat_tables_common.c | 18 +
lib/xlat_tables_v2/xlat_tables_core.c | 7 +-
make_helpers/build_macros.mk | 15 +-
make_helpers/defaults.mk | 3 +
plat/arm/common/aarch32/arm_helpers.S | 6 +-
plat/arm/common/arm_common.mk | 4 +-
plat/arm/common/sp_min/arm_sp_min_setup.c | 7 +-
plat/common/aarch32/crash_console_helpers.S | 92 +
plat/common/aarch32/plat_sp_min_common.c | 4 +
plat/common/aarch32/platform_helpers.S | 38 +
plat/common/aarch64/crash_console_helpers.S | 92 +
plat/common/aarch64/platform_helpers.S | 4 +
plat/common/plat_log_common.c | 1 +
plat/imx/common/lpuart_console.S | 3 +-
plat/layerscape/common/aarch64/ls_console.S | 3 +-
plat/st/common/bl2_io_storage.c | 773 +++++++
plat/st/common/include/stm32mp_auth.h | 15 +
plat/st/common/include/stm32mp_common.h | 49 +
plat/st/common/include/stm32mp_dt.h | 54 +
plat/st/common/include/stm32mp_shres_helpers.h | 86 +
plat/st/common/stm32mp_auth.c | 121 ++
plat/st/common/stm32mp_common.c | 168 ++
plat/st/common/stm32mp_dt.c | 559 +++++
plat/st/common/stm32mp_shres_helpers.c | 71 +
plat/st/stm32mp1/bl2_io_storage.c | 193 --
plat/st/stm32mp1/bl2_plat_setup.c | 447 +++-
plat/st/stm32mp1/include/boot_api.h | 411 +++-
plat/st/stm32mp1/include/platform_def.h | 64 +-
plat/st/stm32mp1/include/stm32mp1_context.h | 18 +-
plat/st/stm32mp1/include/stm32mp1_dbgmcu.h | 26 +
plat/st/stm32mp1/include/stm32mp1_dt.h | 41 -
plat/st/stm32mp1/include/stm32mp1_low_power.h | 19 +
plat/st/stm32mp1/include/stm32mp1_power_config.h | 28 +
plat/st/stm32mp1/include/stm32mp1_private.h | 30 +-
.../stm32mp1/include/stm32mp1_shared_resources.h | 83 +
plat/st/stm32mp1/include/stm32mp1_smc.h | 68 +
plat/st/stm32mp1/include/stm32mp1_usb_desc.h | 55 +
plat/st/stm32mp1/include/usb_ctx.h | 17 +
plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 49 +-
plat/st/stm32mp1/plat_image_load.c | 103 +
plat/st/stm32mp1/platform.mk | 144 +-
plat/st/stm32mp1/services/bsec_svc.c | 460 ++++
plat/st/stm32mp1/services/bsec_svc.h | 21 +
plat/st/stm32mp1/services/low_power_svc.c | 46 +
plat/st/stm32mp1/services/low_power_svc.h | 15 +
plat/st/stm32mp1/services/pwr_svc.c | 124 ++
plat/st/stm32mp1/services/pwr_svc.h | 13 +
plat/st/stm32mp1/services/rcc_svc.c | 477 +++++
plat/st/stm32mp1/services/rcc_svc.h | 14 +
plat/st/stm32mp1/services/stm32mp1_svc_setup.c | 113 +
plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 14 +
plat/st/stm32mp1/sp_min/sp_min_setup.c | 243 ++-
plat/st/stm32mp1/stm32mp1.ld.S | 19 +-
plat/st/stm32mp1/stm32mp1_common.c | 101 -
plat/st/stm32mp1/stm32mp1_context.c | 220 +-
plat/st/stm32mp1/stm32mp1_dbgmcu.c | 153 ++
plat/st/stm32mp1/stm32mp1_def.h | 441 +++-
plat/st/stm32mp1/stm32mp1_dt.c | 476 -----
plat/st/stm32mp1/stm32mp1_gic.c | 173 +-
plat/st/stm32mp1/stm32mp1_helper.S | 248 ++-
plat/st/stm32mp1/stm32mp1_helper_dbg.S | 227 ++
plat/st/stm32mp1/stm32mp1_low_power.c | 311 +++
plat/st/stm32mp1/stm32mp1_pm.c | 118 +-
plat/st/stm32mp1/stm32mp1_power_config.c | 193 ++
plat/st/stm32mp1/stm32mp1_private.c | 379 ++++
plat/st/stm32mp1/stm32mp1_security.c | 91 +-
plat/st/stm32mp1/stm32mp1_shared_resources.c | 833 ++++++++
plat/st/stm32mp1/stm32mp1_syscfg.c | 144 ++
plat/st/stm32mp1/stm32mp1_usb_desc.c | 401 ++++
tools/cert_create/Makefile | 18 +-
tools/doimage/Makefile | 20 +-
tools/fiptool/Makefile | 14 +-
tools/stm32image/Makefile | 20 +-
tools/stm32image/stm32image.c | 2 +-
237 files changed, 34905 insertions(+), 4745 deletions(-)
create mode 100644 docs/devicetree/bindings/arm/secure.txt
create mode 100644 docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
create mode 100644 docs/devicetree/bindings/i2c/i2c-stm32.txt
create mode 100644 docs/devicetree/bindings/mmc/mmci.txt
create mode 100644 docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt
create mode 100644 docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
create mode 100644 docs/devicetree/bindings/power/st,stpmic1.txt
create mode 100644 docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt
create mode 100644 docs/devicetree/bindings/rng/st,stm32-rng.txt
create mode 100644 docs/devicetree/bindings/serial/st,stm32-usart.txt
create mode 100644 docs/devicetree/bindings/soc/st,stm32-etzpc.txt
create mode 100644 docs/devicetree/bindings/soc/st,stm32-romem.txt
create mode 100644 docs/devicetree/bindings/soc/st,stm32-stgen.txt
create mode 100644 docs/devicetree/bindings/soc/st,stm32-tamp.txt
create mode 100644 docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt
create mode 100644 drivers/console/aarch32/deprecated_console.S
create mode 100644 drivers/console/aarch32/multi_console.S
create mode 100644 drivers/st/bsec/bsec.c
create mode 100644 drivers/st/clk/stm32mp_clkfunc.c
create mode 100644 drivers/st/etzpc/etzpc.c
create mode 100644 drivers/st/hash/hash_sec.c
create mode 100644 drivers/st/i2c/stm32_i2c.c
create mode 100644 drivers/st/io/io_mmc.c
create mode 100644 drivers/st/io/io_programmer_st_usb.c
create mode 100644 drivers/st/io/io_stm32image.c
create mode 100644 drivers/st/iwdg/stm32_iwdg.c
create mode 100644 drivers/st/mmc/stm32_sdmmc2.c
create mode 100644 drivers/st/nand/io_nand.c
create mode 100644 drivers/st/nand/nand.c
delete mode 100644 drivers/st/pmic/stm32_i2c.c
delete mode 100644 drivers/st/pmic/stm32mp1_pmic.c
create mode 100644 drivers/st/pmic/stm32mp_pmic.c
create mode 100644 drivers/st/pmic/stpmic1.c
delete mode 100644 drivers/st/pmic/stpmu1.c
create mode 100644 drivers/st/qspi/io_qspi.c
create mode 100644 drivers/st/rng/stm32_rng.c
create mode 100644 drivers/st/rtc/stm32_rtc.c
create mode 100644 drivers/st/tamper/stm32_tamp.c
create mode 100644 drivers/st/timer/stm32_timer.c
create mode 100644 drivers/st/uart/io_programmer_uart.c
create mode 100644 drivers/st/uart/stm32mp1xx_hal_uart.c
create mode 100644 drivers/st/usb_dwc2/usb_dwc2.c
create mode 100644 fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
create mode 100644 fdts/stm32mp157a-dk1.dts
create mode 100644 fdts/stm32mp157c-dk2.dts
create mode 100644 fdts/stm32mp157c-security.dtsi
create mode 100644 fdts/stm32mp157cab-pinctrl.dtsi
create mode 100644 fdts/stm32mp157cac-pinctrl.dtsi
create mode 100644 fdts/stm32mp157cad-pinctrl.dtsi
create mode 100644 include/common/aarch32/console_macros.S
create mode 100644 include/drivers/st/bsec.h
create mode 100644 include/drivers/st/etzpc.h
create mode 100644 include/drivers/st/hash_sec.h
create mode 100644 include/drivers/st/io_mmc.h
create mode 100644 include/drivers/st/io_nand.h
create mode 100644 include/drivers/st/io_programmer.h
create mode 100644 include/drivers/st/io_programmer_st_usb.h
create mode 100644 include/drivers/st/io_qspi.h
create mode 100644 include/drivers/st/io_stm32image.h
create mode 100644 include/drivers/st/io_uart.h
create mode 100644 include/drivers/st/nand.h
create mode 100644 include/drivers/st/stm32_console.h
create mode 100644 include/drivers/st/stm32_hal_hash_reg.h
create mode 100644 include/drivers/st/stm32_iwdg.h
create mode 100644 include/drivers/st/stm32_rng.h
create mode 100644 include/drivers/st/stm32_rtc.h
create mode 100644 include/drivers/st/stm32_sdmmc2.h
create mode 100644 include/drivers/st/stm32_tamp.h
create mode 100644 include/drivers/st/stm32_timer.h
create mode 100644 include/drivers/st/stm32_uart_regs.h
delete mode 100644 include/drivers/st/stm32mp1_pmic.h
delete mode 100644 include/drivers/st/stm32mp1_reset.h
create mode 100644 include/drivers/st/stm32mp1xx_hal.h
create mode 100644 include/drivers/st/stm32mp1xx_hal_uart.h
create mode 100644 include/drivers/st/stm32mp1xx_hal_uart_ex.h
create mode 100644 include/drivers/st/stm32mp_clkfunc.h
create mode 100644 include/drivers/st/stm32mp_pmic.h
create mode 100644 include/drivers/st/stm32mp_reset.h
create mode 100644 include/drivers/st/stpmic1.h
delete mode 100644 include/drivers/st/stpmu1.h
create mode 100644 include/drivers/st/usb_dwc2.h
create mode 100644 include/dt-bindings/interrupt-controller/arm-gic.h
create mode 100644 include/dt-bindings/power/stm32mp1-power.h
create mode 100644 include/dt-bindings/soc/st,stm32-etzpc.h
create mode 100644 include/lib/usb/usb_core.h
create mode 100644 include/lib/usb/usb_st_dfu.h
create mode 100644 lib/compiler-rt/builtins/lshrdi3.c
create mode 100644 lib/usb/usb_core.c
create mode 100644 lib/usb/usb_st_dfu.c
create mode 100644 plat/common/aarch32/crash_console_helpers.S
create mode 100644 plat/common/aarch64/crash_console_helpers.S
create mode 100644 plat/st/common/bl2_io_storage.c
create mode 100644 plat/st/common/include/stm32mp_auth.h
create mode 100644 plat/st/common/include/stm32mp_common.h
create mode 100644 plat/st/common/include/stm32mp_dt.h
create mode 100644 plat/st/common/include/stm32mp_shres_helpers.h
create mode 100644 plat/st/common/stm32mp_auth.c
create mode 100644 plat/st/common/stm32mp_common.c
create mode 100644 plat/st/common/stm32mp_dt.c
create mode 100644 plat/st/common/stm32mp_shres_helpers.c
delete mode 100644 plat/st/stm32mp1/bl2_io_storage.c
create mode 100644 plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
delete mode 100644 plat/st/stm32mp1/include/stm32mp1_dt.h
create mode 100644 plat/st/stm32mp1/include/stm32mp1_low_power.h
create mode 100644 plat/st/stm32mp1/include/stm32mp1_power_config.h
create mode 100644 plat/st/stm32mp1/include/stm32mp1_shared_resources.h
create mode 100644 plat/st/stm32mp1/include/stm32mp1_smc.h
create mode 100644 plat/st/stm32mp1/include/stm32mp1_usb_desc.h
create mode 100644 plat/st/stm32mp1/include/usb_ctx.h
create mode 100644 plat/st/stm32mp1/services/bsec_svc.c
create mode 100644 plat/st/stm32mp1/services/bsec_svc.h
create mode 100644 plat/st/stm32mp1/services/low_power_svc.c
create mode 100644 plat/st/stm32mp1/services/low_power_svc.h
create mode 100644 plat/st/stm32mp1/services/pwr_svc.c
create mode 100644 plat/st/stm32mp1/services/pwr_svc.h
create mode 100644 plat/st/stm32mp1/services/rcc_svc.c
create mode 100644 plat/st/stm32mp1/services/rcc_svc.h
create mode 100644 plat/st/stm32mp1/services/stm32mp1_svc_setup.c
delete mode 100644 plat/st/stm32mp1/stm32mp1_common.c
create mode 100644 plat/st/stm32mp1/stm32mp1_dbgmcu.c
delete mode 100644 plat/st/stm32mp1/stm32mp1_dt.c
create mode 100644 plat/st/stm32mp1/stm32mp1_helper_dbg.S
create mode 100644 plat/st/stm32mp1/stm32mp1_low_power.c
create mode 100644 plat/st/stm32mp1/stm32mp1_power_config.c
create mode 100644 plat/st/stm32mp1/stm32mp1_private.c
create mode 100644 plat/st/stm32mp1/stm32mp1_shared_resources.c
create mode 100644 plat/st/stm32mp1/stm32mp1_syscfg.c
create mode 100644 plat/st/stm32mp1/stm32mp1_usb_desc.c
diff --git a/.checkpatch.conf b/.checkpatch.conf
index 63bdf7b..066207b 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -93,3 +93,21 @@
# "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt"
# We allow the usage of the volatile keyword in TF.
--ignore VOLATILE
+
+# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict):
+# "Prefer kernel type 'u32' over 'uint32_t'"
+--ignore PREFER_KERNEL_TYPES
+
+# USLEEP_RANGE reports this kind of messages (when using --strict):
+# "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt"
+--ignore USLEEP_RANGE
+
+# COMPARISON_TO_NULL reports this kind of messages (when using --strict):
+# Comparison to NULL could be written ""
+--ignore COMPARISON_TO_NULL
+
+# UNNECESSARY_PARENTHESES reports this kind of messages (when using --strict):
+# Unnecessary parentheses around ""
+--ignore UNNECESSARY_PARENTHESES
+
+--ignore BRACES
diff --git a/Makefile b/Makefile
index 23a1b0a..cda7e7d 100644
--- a/Makefile
+++ b/Makefile
@@ -187,8 +187,48 @@ TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
ASFLAGS_aarch32 = $(march32-directive)
ASFLAGS_aarch64 = -march=armv8-a
+WARNING1 := -Wextra
+WARNING1 += -Wunused -Wno-unused-parameter
+WARNING1 += -Wmissing-declarations
+WARNING1 += -Wmissing-format-attribute
+WARNING1 += -Wmissing-prototypes
+WARNING1 += -Wold-style-definition
+WARNING1 += -Wunused-but-set-variable
+WARNING1 += -Wunused-const-variable
+
+WARNING2 := -Waggregate-return
+WARNING2 += -Wcast-align
+WARNING2 += -Wdisabled-optimization
+WARNING2 += -Wnested-externs
+WARNING2 += -Wshadow
+WARNING2 += -Wlogical-op
+WARNING2 += -Wmissing-field-initializers
+WARNING2 += -Wsign-compare
+WARNING2 += -Wmaybe-uninitialized
+
+WARNING3 := -Wbad-function-cast
+WARNING3 += -Wcast-qual
+WARNING3 += -Wconversion
+WARNING3 += -Wpacked
+WARNING3 += -Wpadded
+WARNING3 += -Wpointer-arith
+WARNING3 += -Wredundant-decls
+WARNING3 += -Wswitch-default
+WARNING3 += -Wpacked-bitfield-compat
+WARNING3 += -Wvla
+
+ifeq (${W},1)
+WARN_OR_ERROR := $(WARNING1)
+else ifeq (${W},2)
+WARN_OR_ERROR := $(WARNING1) $(WARNING2)
+else ifeq (${W},3)
+WARN_OR_ERROR := $(WARNING1) $(WARNING2) $(WARNING3)
+else
+WARN_OR_ERROR := -Werror
+endif
+
CPPFLAGS = ${DEFINES} ${INCLUDES} ${MBEDTLS_INC} -nostdinc \
- -Wmissing-include-dirs -Werror
+ -Wmissing-include-dirs $(WARN_OR_ERROR)
ASFLAGS += $(CPPFLAGS) $(ASFLAGS_$(ARCH)) \
-D__ASSEMBLY__ -ffreestanding \
-Wa,--fatal-warnings
@@ -396,12 +436,6 @@ ifeq ($(HW_ASSISTED_COHERENCY)-$(USE_COHERENT_MEM),1-1)
$(error USE_COHERENT_MEM cannot be enabled with HW_ASSISTED_COHERENCY)
endif
-ifneq ($(MULTI_CONSOLE_API), 0)
- ifeq (${ARCH},aarch32)
- $(error "Error: MULTI_CONSOLE_API is not supported for AArch32")
- endif
-endif
-
#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1.
ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1)
$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled")
@@ -592,6 +626,7 @@ $(eval $(call assert_boolean,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call assert_boolean,BL2_AT_EL3))
$(eval $(call assert_boolean,BL2_IN_XIP_MEM))
+$(eval $(call assert_boolean,AARCH32_EXCEPTION_DEBUG))
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -644,6 +679,7 @@ $(eval $(call add_define,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call add_define,BL2_AT_EL3))
$(eval $(call add_define,BL2_IN_XIP_MEM))
+$(eval $(call add_define,AARCH32_EXCEPTION_DEBUG))
# Define the EL3_PAYLOAD_BASE flag only if it is provided.
ifdef EL3_PAYLOAD_BASE
@@ -784,9 +820,11 @@ checkpatch: locate-checkpatch
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
printf "\n[*] Checking style of '$$commit'\n\n"; \
git log --format=email "$$commit~..$$commit" \
- -- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \
+ -- ${CHECK_PATHS} | ${CHECKPATCH} --strict - || \
+ true; \
git diff --format=email "$$commit~..$$commit" \
- -- ${CHECK_PATHS} | ${CHECKPATCH} - || true; \
+ -- ${CHECK_PATHS} | ${CHECKPATCH} --strict - || \
+ true; \
done
certtool: ${CRTTOOL}
diff --git a/bl2/aarch32/bl2_arch_setup.c b/bl2/aarch32/bl2_arch_setup.c
index db8a068..4fd8d07 100644
--- a/bl2/aarch32/bl2_arch_setup.c
+++ b/bl2/aarch32/bl2_arch_setup.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include "../bl2_private.h"
/*******************************************************************************
* Place holder function to perform any Secure SVC specific architectural
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 0c7b064..437188e 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -15,6 +15,10 @@
func bl2_entrypoint
+#if STM32MP1_RESET_HALT_WORKAROUND
+ bl plat_dbg_attach_loop
+#endif
+
/* Save arguments x0-x3 from previous Boot loader */
mov r9, r0
mov r10, r1
diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S
index 11ddf37..7058b07 100644
--- a/bl2/aarch32/bl2_el3_exceptions.S
+++ b/bl2/aarch32/bl2_el3_exceptions.S
@@ -12,10 +12,19 @@
vector_base bl2_vector_table
b bl2_entrypoint
+#if AARCH32_EXCEPTION_DEBUG
+ b report_undef_inst /* Undef */
+#else
b report_exception /* Undef */
+#endif
b report_exception /* SVC call */
+#if AARCH32_EXCEPTION_DEBUG
+ b report_prefetch_abort /* Prefetch abort */
+ b report_data_abort /* Data abort */
+#else
b report_exception /* Prefetch abort */
b report_exception /* Data abort */
+#endif
b report_exception /* Reserved */
b report_exception /* IRQ */
b report_exception /* FIQ */
diff --git a/bl2/aarch32/bl2_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S
index d215f48..f76c1c9 100644
--- a/bl2/aarch32/bl2_entrypoint.S
+++ b/bl2/aarch32/bl2_entrypoint.S
@@ -15,10 +15,19 @@
vector_base bl2_vector_table
b bl2_entrypoint
+#if AARCH32_EXCEPTION_DEBUG
+ b report_undef_inst /* Undef */
+#else
b report_exception /* Undef */
+#endif
b report_exception /* SVC call */
+#if AARCH32_EXCEPTION_DEBUG
+ b report_prefetch_abort /* Prefetch abort */
+ b report_data_abort /* Data abort */
+#else
b report_exception /* Prefetch abort */
b report_exception /* Data abort */
+#endif
b report_exception /* Reserved */
b report_exception /* IRQ */
b report_exception /* FIQ */
diff --git a/bl2/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c
index 0f40785..2e3e145 100644
--- a/bl2/bl2_image_load_v2.c
+++ b/bl2/bl2_image_load_v2.c
@@ -69,17 +69,17 @@ struct entry_point_info *bl2_load_images(void)
ERROR("BL2: Failed to load image (%i)\n", err);
plat_error_handler(err);
}
+
+ /* Allow platform to handle image information. */
+ err = bl2_plat_handle_post_image_load(bl2_node_info->image_id);
+ if (err) {
+ ERROR("BL2: Failure in post image load handling (%i)\n", err);
+ plat_error_handler(err);
+ }
} else {
INFO("BL2: Skip loading image id %d\n", bl2_node_info->image_id);
}
- /* Allow platform to handle image information. */
- err = bl2_plat_handle_post_image_load(bl2_node_info->image_id);
- if (err) {
- ERROR("BL2: Failure in post image load handling (%i)\n", err);
- plat_error_handler(err);
- }
-
/* Go to next image */
bl2_node_info = bl2_node_info->next_load_info;
}
diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h
index f93a179..8e602ff 100644
--- a/bl2/bl2_private.h
+++ b/bl2/bl2_private.h
@@ -8,6 +8,9 @@
#define __BL2_PRIVATE_H__
#if BL2_IN_XIP_MEM
+
+#include <stdint.h>
+
/*******************************************************************************
* Declarations of linker defined symbols which will tell us where BL2 lives
* in Trusted ROM and RAM
diff --git a/bl2u/aarch32/bl2u_entrypoint.S b/bl2u/aarch32/bl2u_entrypoint.S
index 7fb64f3..b511499 100644
--- a/bl2u/aarch32/bl2u_entrypoint.S
+++ b/bl2u/aarch32/bl2u_entrypoint.S
@@ -15,10 +15,19 @@
vector_base bl2u_vector_table
b bl2u_entrypoint
+#if AARCH32_EXCEPTION_DEBUG
+ b report_undef_inst /* Undef */
+#else
b report_exception /* Undef */
+#endif
b report_exception /* SVC call */
+#if AARCH32_EXCEPTION_DEBUG
+ b report_prefetch_abort /* Prefetch abort */
+ b report_data_abort /* Data abort */
+#else
b report_exception /* Prefetch abort */
b report_exception /* Data abort */
+#endif
b report_exception /* Reserved */
b report_exception /* IRQ */
b report_exception /* FIQ */
diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S
index d6853cc..2d67af3 100644
--- a/bl32/sp_min/aarch32/entrypoint.S
+++ b/bl32/sp_min/aarch32/entrypoint.S
@@ -44,10 +44,19 @@
vector_base sp_min_vector_table
b sp_min_entrypoint
+#if AARCH32_EXCEPTION_DEBUG
+ b report_undef_inst /* Undef */
+#else
b plat_panic_handler /* Undef */
+#endif
b sp_min_handle_smc /* Syscall */
+#if AARCH32_EXCEPTION_DEBUG
+ b report_prefetch_abort /* Prefetch abort */
+ b report_data_abort /* Data abort */
+#else
b plat_panic_handler /* Prefetch abort */
b plat_panic_handler /* Data abort */
+#endif
b plat_panic_handler /* Reserved */
b plat_panic_handler /* IRQ */
b sp_min_handle_fiq /* FIQ */
diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S
index f506356..a058645 100644
--- a/common/aarch32/debug.S
+++ b/common/aarch32/debug.S
@@ -7,9 +7,16 @@
#include <arch.h>
#include <asm_macros.S>
+ .globl asm_print_str
+ .globl asm_print_hex
.globl asm_assert
.globl do_panic
.globl report_exception
+#if AARCH32_EXCEPTION_DEBUG
+ .globl report_undef_inst
+ .globl report_prefetch_abort
+ .globl report_data_abort
+#endif
/* Since the max decimal input number is 65536 */
#define MAX_DEC_DIVISOR 10000
@@ -66,6 +73,41 @@ func report_exception
no_ret plat_panic_handler
endfunc report_exception
+#if AARCH32_EXCEPTION_DEBUG
+ /***********************************************************
+ * This function is called from the vector table for
+ * undefined instruction. The lr_und is given as an
+ * argument to platform handler.
+ ***********************************************************/
+func report_undef_inst
+ mrs r0, lr_und
+ bl plat_report_undef_inst
+ no_ret plat_panic_handler
+endfunc report_undef_inst
+
+ /***********************************************************
+ * This function is called from the vector table for
+ * unhandled exceptions. The lr_abt is given as an
+ * argument to platform handler.
+ ***********************************************************/
+func report_prefetch_abort
+ mrs r0, lr_abt
+ bl plat_report_prefetch_abort
+ no_ret plat_panic_handler
+endfunc report_prefetch_abort
+
+ /***********************************************************
+ * This function is called from the vector table for
+ * unhandled exceptions. The lr_abt is given as an
+ * argument to platform handler.
+ ***********************************************************/
+func report_data_abort
+ mrs r0, lr_abt
+ bl plat_report_data_abort
+ no_ret plat_panic_handler
+endfunc report_data_abort
+#endif
+
#if ENABLE_ASSERTIONS
.section .rodata.assert_str, "aS"
assert_msg1:
@@ -151,10 +193,10 @@ endfunc asm_assert
/*
* This function prints a string from address in r4
- * Clobber: lr, r0 - r4
+ * Clobber: lr, r0 - r4, r7
*/
func asm_print_str
- mov r3, lr
+ mov r7, lr
1:
ldrb r0, [r4], #0x1
cmp r0, #0
@@ -162,16 +204,16 @@ func asm_print_str
bl plat_crash_console_putc
b 1b
2:
- bx r3
+ bx r7
endfunc asm_print_str
/*
* This function prints a hexadecimal number in r4.
* In: r4 = the hexadecimal to print.
- * Clobber: lr, r0 - r3, r5
+ * Clobber: lr, r0 - r3, r5, r7
*/
func asm_print_hex
- mov r3, lr
+ mov r7, lr
mov r5, #32 /* No of bits to convert to ascii */
1:
sub r5, r5, #4
@@ -188,5 +230,5 @@ func asm_print_hex
bl plat_crash_console_putc
cmp r5, #0
bne 1b
- bx r3
+ bx r7
endfunc asm_print_hex
diff --git a/docs/devicetree/bindings/arm/secure.txt b/docs/devicetree/bindings/arm/secure.txt
new file mode 100644
index 0000000..e31303f
--- /dev/null
+++ b/docs/devicetree/bindings/arm/secure.txt
@@ -0,0 +1,53 @@
+* ARM Secure world bindings
+
+ARM CPUs with TrustZone support have two distinct address spaces,
+"Normal" and "Secure". Most devicetree consumers (including the Linux
+kernel) are not TrustZone aware and run entirely in either the Normal
+world or the Secure world. However some devicetree consumers are
+TrustZone aware and need to be able to determine whether devices are
+visible only in the Secure address space, only in the Normal address
+space, or visible in both. (One example of that situation would be a
+virtual machine which boots Secure firmware and wants to tell the
+firmware about the layout of the machine via devicetree.)
+
+The general principle of the naming scheme for Secure world bindings
+is that any property that needs a different value in the Secure world
+can be supported by prefixing the property name with "secure-". So for
+instance "secure-foo" would override "foo". For property names with
+a vendor prefix, the Secure variant of "vendor,foo" would be
+"vendor,secure-foo". If there is no "secure-" property then the Secure
+world value is the same as specified for the Normal world by the
+non-prefixed property. However, only the properties listed below may
+validly have "secure-" versions; this list will be enlarged on a
+case-by-case basis.
+
+Defining the bindings in this way means that a device tree which has
+been annotated to indicate the presence of Secure-only devices can
+still be processed unmodified by existing Non-secure software (and in
+particular by the kernel).
+
+Note that it is still valid for bindings intended for purely Secure
+world consumers (like kernels that run entirely in Secure) to simply
+describe the view of Secure world using the standard bindings. These
+secure- bindings only need to be used where both the Secure and Normal
+world views need to be described in a single device tree.
+
+Valid Secure world properties:
+
+- secure-status : specifies whether the device is present and usable
+ in the secure world. The combination of this with "status" allows
+ the various possible combinations of device visibility to be
+ specified. If "secure-status" is not specified it defaults to the
+ same value as "status"; if "status" is not specified either then
+ both default to "okay". This means the following combinations are
+ possible:
+
+ /* Neither specified: default to visible in both S and NS */
+ secure-status = "okay"; /* visible in both */
+ status = "okay"; /* visible in both */
+ status = "okay"; secure-status = "okay"; /* visible in both */
+ secure-status = "disabled"; /* NS-only */
+ status = "okay"; secure-status = "disabled"; /* NS-only */
+ status = "disabled"; secure-status = "okay"; /* S-only */
+ status = "disabled"; /* disabled in both */
+ status = "disabled"; secure-status = "disabled"; /* disabled in both */
diff --git a/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
new file mode 100644
index 0000000..7021486
--- /dev/null
+++ b/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt
@@ -0,0 +1,324 @@
+STMicroelectronics STM32 Peripheral Reset Clock Controller
+==========================================================
+
+The RCC IP is both a reset and a clock controller.
+
+RCC makes also power management (resume/supend and wakeup interrupt).
+
+Please also refer to reset.txt for common reset controller binding usage.
+
+Please also refer to clock-bindings.txt for common clock controller
+binding usage.
+
+
+Required properties:
+- compatible: "st,stm32mp1-rcc", "syscon"
+- reg: should be register base and length as documented in the datasheet
+- #clock-cells: 1, device nodes should specify the clock in their
+ "clocks" property, containing a phandle to the clock device node,
+ an index specifying the clock to use.
+- #reset-cells: Shall be 1
+- interrupts: Should contain a general interrupt line and a interrupt line
+ to the wake-up of processor (CSTOP).
+
+Example:
+ rcc: rcc@50000000 {
+ compatible = "st,stm32mp1-rcc", "syscon";
+ reg = <0x50000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>,
+ <GIC_SPI 145 IRQ_TYPE_NONE>;
+ };
+
+Other properties:
+- secure-status: Relates to RCC TZ_ENABLE configuration to restrict RCC access.
+- st,clksrc : The clock sources configuration array in a platform specific order.
+- st,clkdiv : The clock dividers configuration array in a paltform specific order.
+- st,pll : A specific PLL configuration
+- st,pkcs : The peripheral kernel clock distribution configuration array.
+
+Specifying clocks
+=================
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/stm32mp1-clks.h header and can be used in device
+tree sources.
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+The index is the bit number within the RCC registers bank, starting from RCC
+base address.
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register.
+
+For example on STM32MP1, for LTDC reset:
+ ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset
+ = 0x180 / 4 * 32 + 0 = 3072
+
+The list of valid indices for STM32MP1 is available in:
+include/dt-bindings/reset-controller/stm32mp1-resets.h
+
+This file implements defines like:
+#define LTDC_R 3072
+
+
+Defining clock source distribution with property st,clksrc
+==========================================================
+
+Property can be used to configure the clock distribution tree.
+When used, it shall describe the whole distribution tree.
+
+For the STM32MP15x family there are 9 clock sources selector which are
+configured in the following order:
+ MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2
+
+Clock source configuration values are defined by macros CLK_<NAME>_<SOURCE>
+from dt-bindings/clock/stm32mp1-clksrc.h.
+
+Example:
+ st,clksrc = <
+ CLK_MPU_PLL1P
+ CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
+ CLK_PLL12_HSE
+ CLK_PLL3_HSE
+ CLK_PLL4_HSE
+ CLK_RTC_LSE
+ CLK_MCO1_DISABLED
+ CLK_MCO2_DISABLED
+ >;
+
+
+Defining clock dividers with property st,clkdiv
+===============================================
+
+Property can be used to configure the clock main dividers value.
+When used, it shall describe the whole clock dividers tree.
+
+For the STM32MP15x family there are 11 dividers values expected.
+They shall be configured in the following order:
+ MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2
+
+The each divider value uses the DIV coding defined in RCC associated
+register RCC_xxxDIVR. In most cases, it is:
+ 0x0: not divided
+ 0x1: division by 2
+ 0x2: division by 4
+ 0x3: division by 8
+ ...
+
+Note that for RTC MCO1 MCO2, the coding is different:
+ 0x0: not divided
+ 0x1: division by 2
+ 0x2: division by 3
+ 0x3: division by 4
+ ...
+
+Example:
+ st,clkdiv = <
+ 1 /*MPU*/
+ 0 /*AXI*/
+ 0 /*MCU*/
+ 1 /*APB1*/
+ 1 /*APB2*/
+ 1 /*APB3*/
+ 1 /*APB4*/
+ 2 /*APB5*/
+ 23 /*RTC*/
+ 0 /*MCO1*/
+ 0 /*MCO2*/
+ >;
+
+Defining peripheral PLL frequencies with property st,pll
+========================================================
+
+This property can be used to configure PLL frequencies.
+
+PLL children nodes for PLL1 to PLL4 (see ref manual for details)
+are listed with associated index 0 to 3 (st,pll@0 to st,pll@3).
+PLLx is off when the associated node is absent.
+
+Here are the available properties for each PLL node:
+
+- cfg: The parameters for PLL configuration in the following order:
+ DIVM DIVN DIVP DIVQ DIVR Output.
+
+ DIVx values are defined as in RCC spec:
+ 0x0: bypass (division by 1)
+ 0x1: division by 2
+ 0x2: division by 3
+ 0x3: division by 4
+ ...
+
+ Output contains a bitfield for each output value (1:ON/0:OFF)
+ BIT(0) => output P : DIVPEN
+ BIT(1) => output Q : DIVQEN
+ BIT(2) => output R : DIVREN
+ NB: macro PQR(p,q,r) can be used to build this value
+ with p,q,r = 0 or 1.
+
+- frac: Fractional part of the multiplication factor
+ (optional, PLL is in integer mode when absent).
+
+- csg: Clock Spreading Generator (optional) with parameters in the following
+ order: MOD_PER INC_STEP SSCG_MODE.
+
+ MOD_PER: Modulation Period Adjustment
+ INC_STEP: Modulation Depth Adjustment
+ SSCG_MODE: Spread spectrum clock generator mode, with associated
+ defined from stm32mp1-clksrc.h:
+ - SSCG_MODE_CENTER_SPREAD = 0
+ - SSCG_MODE_DOWN_SPREAD = 1
+
+Example:
+ st,pll@0 {
+ cfg = < 1 53 0 0 0 1 >;
+ frac = < 0x810 >;
+ };
+ st,pll@1 {
+ cfg = < 1 43 1 0 0 PQR(0,1,1) >;
+ csg = < 10 20 1 >;
+ };
+ st,pll@2 {
+ cfg = < 2 85 3 13 3 0 >;
+ csg = < 10 20 SSCG_MODE_CENTER_SPREAD >;
+ };
+ st,pll@3 {
+ cfg = < 2 78 4 7 9 3 >;
+ };
+
+Defining peripherals kernel clock tree distribution with property st,pkcs
+=========================================================================
+
+This property can be used to configure the peripherals kernel clock selection.
+
+The property is a list of peripheral kernel clock source identifiers defined
+by macros CLK_<KERNEL-CLOCK>_<PARENT-CLOCK> as defined by header file
+dt-bindings/clock/stm32mp1-clksrc.h.
+
+st,pkcs may not list all the kernel clocks and has no ordering requirements.
+
+Example:
+ st,pkcs = <
+ CLK_STGEN_HSE
+ CLK_CKPER_HSI
+ CLK_USBPHY_PLL2P
+ CLK_DSI_PLL2Q
+ CLK_I2C46_HSI
+ CLK_UART1_HSI
+ CLK_UART24_HSI
+ >;
+
+Fixed clocks description
+========================
+
+The clock tree is also based on 5 fixed-clock in clocks node
+used to define the state of associated ST32MP1 oscillators:
+- clk-lsi
+- clk-lse
+- clk-hsi
+- clk-hse
+- clk-csi
+
+At boot the clock tree initialization will
+- enable oscillators present in device tree
+- disable HSI oscillator if the node is absent (always activated by bootrom)
+
+Optional properties :
+
+a) for external oscillator: "clk-lse", "clk-hse"
+
+ 4 optional fields are managed
+ - "st,bypass" configures the oscillator bypass mode (HSEBYP, LSEBYP)
+ - "st,digbypass" configures the bypass mode as full-swing digital
+ signal (DIGBYP)
+ - "st,css" activates the clock security system (HSECSSON, LSECSSON)
+ - "st,drive" (only for LSE) contains the value of the drive for the
+ oscillator (see LSEDRV_ defined in the file
+ dt-bindings/clock/stm32mp1-clksrc.h)
+
+ Example board file:
+
+ / {
+ clocks {
+ clk_hse: clk-hse {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <64000000>;
+ st,bypass;
+ };
+
+ clk_lse: clk-lse {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ st,css;
+ st,drive = <LSEDRV_LOWEST>;
+ };
+ };
+
+b) for internal oscillator: "clk-hsi"
+
+ Internally HSI clock is fixed to 64MHz for STM32MP157 SoC.
+ In device tree, clk-hsi is the clock after HSIDIV (clk_hsi in RCC
+ doc). So this clock frequency is used to compute the expected HSI_DIV
+ for the clock tree initialization.
+
+ Example with HSIDIV = /1:
+
+ / {
+ clocks {
+ clk_hsi: clk-hsi {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <64000000>;
+ };
+ };
+
+ Example with HSIDIV = /2
+
+ / {
+ clocks {
+ clk_hsi: clk-hsi {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32000000>;
+ };
+ };
+
+HSI & CSI calibration
+========================
+
+Calibration is an optional feature that may be enabled from device tree. It
+allows to request calibration of the HSI or the CSI clocks from several means:
+ - SiP SMC service
+ - Periodic calibration every X seconds
+ - Interrupt raised by the MCU
+
+This feature requires that a HW timer is assigned to the calibration sequence.
+
+Dedicated interrupt must be defined using "mcu_sev" name to start a calibration
+on detection of an interrupt raised by MCU.
+
+- st,hsi-cal: used to enable HSI clock calibration feature.
+
+- st,csi-cal; used to enable CSI clock calibration feature.
+
+- st,cal-sec: used to enable periodic calibration every specified seconds from
+ secure monitor. Time must be given in seconds. If not specified, calibration
+ is processed for each incoming request.
+
+Example:
+ &rcc {
+ st,hsi-cal;
+ st,csi-cal;
+ st,cal-sec = <15>;
+ secure-interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mcu_sev", "wakeup";
+ };
diff --git a/docs/devicetree/bindings/i2c/i2c-stm32.txt b/docs/devicetree/bindings/i2c/i2c-stm32.txt
new file mode 100644
index 0000000..68aefa6
--- /dev/null
+++ b/docs/devicetree/bindings/i2c/i2c-stm32.txt
@@ -0,0 +1,54 @@
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
+
+Required properties :
+- compatible : Must be one of the following
+ - "st,stm32f7-i2c"
+- reg : Offset and length of the register set for the device
+- resets: Must contain the phandle to the reset controller.
+- clocks: Must contain the input clock of the I2C instance.
+- A pinctrl state named "default" must be defined to set pins in mode of
+ operation for I2C transfer. An optional pinctrl state named "sleep" has to
+ be defined as well as to put I2C in low power mode in suspend mode.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+ the default 100 kHz frequency will be used.
+- i2c-scl-rising-time-ns : Only for STM32F7, I2C SCL Rising time for the board
+ (default: 25)
+- i2c-scl-falling-time-ns : Only for STM32F7, I2C SCL Falling time for the board
+ (default: 10)
+ I2C Timings are derived from these 2 values
+- st,syscfg-fmp: Only for STM32F7, use to set Fast Mode Plus bit within SYSCFG
+ whether Fast Mode Plus speed is selected by slave.
+ 1st cell : phandle to syscfg
+ 2nd cell : register offset within SYSCFG
+ 3rd cell : register bitmask for FMP bit
+
+Example :
+
+ i2c@40005400 {
+ compatible = "st,stm32f4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005400 0x400>;
+ resets = <&rcc 277>;
+ clocks = <&rcc 0 149>;
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+ pinctrl-names = "default";
+ };
+
+ i2c@40005400 {
+ compatible = "st,stm32f7-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005400 0x400>;
+ resets = <&rcc STM32F7_APB1_RESET(I2C1)>;
+ clocks = <&rcc 1 CLK_I2C1>;
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+ pinctrl-1 = <&i2c1_sda_pin_sleep>, <&i2c1_scl_pin_sleep>;
+ pinctrl-names = "default", "sleep";
+ st,syscfg-fmp = <&syscfg 0x4 0x1>;
+ };
+
diff --git a/docs/devicetree/bindings/mmc/mmci.txt b/docs/devicetree/bindings/mmc/mmci.txt
new file mode 100644
index 0000000..6d3c626
--- /dev/null
+++ b/docs/devicetree/bindings/mmc/mmci.txt
@@ -0,0 +1,72 @@
+* ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1
+
+The ARM PrimeCell MMCI PL180 and PL181 provides an interface for
+reading and writing to MultiMedia and SD cards alike.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the mmci driver. Using "st" as
+the prefix for a property, indicates support by the ST Micro variant.
+
+Required properties:
+- compatible : contains "arm,pl18x", "arm,primecell".
+- vmmc-supply : phandle to the regulator device tree node, mentioned
+ as the VCC/VDD supply in the eMMC/SD specs.
+
+Optional properties:
+- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides
+ the ID provided by the HW
+- resets : phandle to internal reset line.
+ Should be defined for sdmmc variant.
+- vqmmc-supply : phandle to the regulator device tree node, mentioned
+ as the VCCQ/VDD_IO supply in the eMMC/SD specs.
+specific for ux500 variant:
+- st,sig-dir-dat0 : bus signal direction pin used for DAT[0].
+- st,sig-dir-dat2 : bus signal direction pin used for DAT[2].
+- st,sig-dir-dat31 : bus signal direction pin used for DAT[3] and DAT[1].
+- st,sig-dir-dat74 : bus signal direction pin used for DAT[4] to DAT[7].
+- st,sig-dir-cmd : cmd signal direction pin used for CMD.
+- st,sig-pin-fbclk : feedback clock signal pin used.
+
+specific for sdmmc variant:
+- st,sig-dir : signal direction polarity used for cmd, dat0 dat123.
+- st,neg-edge : data & command phase relation, generated on
+ sd clock falling edge.
+- st,use-ckin : use ckin pin from an external driver to sample
+ the receive data (example: with voltage
+ switch transceiver).
+
+Deprecated properties:
+- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable.
+- mmc-cap-sd-highspeed : indicates whether SD is high speed capable.
+
+Example:
+
+sdi0_per1@80126000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ reg = <0x80126000 0x1000>;
+ interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
+
+ dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */
+ <&dma 29 0 0x0>; /* Logical - MemToDev */
+ dma-names = "rx", "tx";
+
+ clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
+ clock-names = "sdi", "apb_pclk";
+
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cd-gpios = <&gpio2 31 0x4>; // 95
+ st,sig-dir-dat0;
+ st,sig-dir-dat2;
+ st,sig-dir-cmd;
+ st,sig-pin-fbclk;
+
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+ vqmmc-supply = <&vmmci>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdi0_default_mode>;
+ pinctrl-1 = <&sdi0_sleep_mode>;
+};
diff --git a/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt
new file mode 100644
index 0000000..51576a3
--- /dev/null
+++ b/docs/devicetree/bindings/mmc/st,stm32-sdmmc2.txt
@@ -0,0 +1,22 @@
+* STMicroelectronics STM32 SDMMC2 controller
+
+The highspeed MMC host controller on STM32 soc family
+provides an interface for MMC, SD and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmci.txt and the properties used by the sdmmc2 driver.
+
+Required properties:
+ - compatible: should be one of:
+ "st,stm32-sdmmc2"
+
+Example:
+ sdmmc1: sdmmc@0x58005000 {
+ compatible = "st,stm32-sdmmc2";
+ reg = <0x58005000 0x1000>;
+ clocks = <&rcc SDMMC1_K>;
+ resets = <&rcc SDMMC1_R>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ status = "disabled";
+ };
diff --git a/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
new file mode 100644
index 0000000..bd56e19
--- /dev/null
+++ b/docs/devicetree/bindings/power/st,stm32mp1-pwr.txt
@@ -0,0 +1,42 @@
+STMicroelectronics STM32MP1 Power Management Controller
+=======================================================
+
+The PWR IP is responsible for handling the power related resources such as
+clocks, power supplies and resets. It provides 6 wake-up pins that are handled
+by an interrupt-controller. Wake-up pin can be used to wake-up from STANDBY SoC
+state.
+
+Required properties:
+- compatible should be: "st,stm32mp1-pwr", "st,stm32-pwr"
+- reg: should be register base and length as documented in the
+ datasheet
+
+Optional Properties:
+- Nodes corresponding to PSCI commands issued by kernel:
+ - system_suspend_supported_soc_modes: list of supported SoC modes in suspend
+ - system_off_soc_mode: SoC mode for shutdown
+
+The list of SoC modes is in include/dt-bindings/power/stm32mp1-power.h:
+ - modes for system_suspend
+ 1 -> STM32_PM_CSTOP_ALLOW_STOP
+ 2 -> STM32_PM_CSTOP_ALLOW_LP_STOP
+ 3 -> STM32_PM_CSTOP_ALLOW_LPLV_STOP
+ 4 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR
+ - modes for system_off
+ 6 -> STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF
+ 7 -> STM32_PM_SHUTDOWN
+
+Example:
+
+pwr: pwr@50001000 {
+ compatible = "st,stm32mp1-pwr", "st,stm32-pwr", "syscon", "simple-mfd";
+ reg = <0x50001000 0x400>;
+
+ system_suspend_supported_soc_modes = <
+ STM32_PM_CSLEEP_RUN
+ STM32_PM_CSTOP_ALLOW_LP_STOP
+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR
+ >;
+
+ system_off_soc_mode = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
+};
diff --git a/docs/devicetree/bindings/power/st,stpmic1.txt b/docs/devicetree/bindings/power/st,stpmic1.txt
new file mode 100644
index 0000000..54b64e2
--- /dev/null
+++ b/docs/devicetree/bindings/power/st,stpmic1.txt
@@ -0,0 +1,132 @@
+* STMicroelectronics STPMIC1 Power Management IC
+
+Required parent device properties:
+- compatible: "st,stpmic1"
+- reg: The I2C slave address for the STPMIC1 chip.
+- interrupts: The interrupt lines the device is connected to.
+ The second interrupt is used for wake-up.
+- #interrupt-cells: Should be 2.
+- interrupt-controller: Describes the STPMIC1 as an interrupt
+ controller (has its own domain). Interrupt number are the following:
+ /* Interrupt Register 1 (0x50 for latch) */
+ IT_SWOUT_R=0
+ IT_SWOUT_F=1
+ IT_VBUS_OTG_R=2
+ IT_VBUS_OTG_F=3
+ IT_WAKEUP_R=4
+ IT_WAKEUP_F=5
+ IT_PONKEY_R=6
+ IT_PONKEY_F=7
+ /* Interrupt Register 2 (0x51 for latch) */
+ IT_OVP_BOOST=8
+ IT_OCP_BOOST=9
+ IT_OCP_SWOUT=10
+ IT_OCP_OTG=11
+ IT_CURLIM_BUCK4=12
+ IT_CURLIM_BUCK3=13
+ IT_CURLIM_BUCK2=14
+ IT_CURLIM_BUCK1=15
+ /* Interrupt Register 3 (0x52 for latch) */
+ IT_SHORT_SWOUT=16
+ IT_SHORT_SWOTG=17
+ IT_CURLIM_LDO6=18
+ IT_CURLIM_LDO5=19
+ IT_CURLIM_LDO4=20
+ IT_CURLIM_LDO3=21
+ IT_CURLIM_LDO2=22
+ IT_CURLIM_LDO1=23
+ /* Interrupt Register 3 (0x52 for latch) */
+ IT_SWIN_R=24
+ IT_SWIN_F=25
+ IT_RESERVED_1=26
+ IT_RESERVED_2=27
+ IT_VINLOW_R=28
+ IT_VINLOW_F=29
+ IT_TWARN_R=30
+ IT_TWARN_F=31
+
+Optional parent device properties:
+- st,main-control-register:
+ -bit 1: Power cycling will be performed on turn OFF condition
+ -bit 2: PWRCTRL is functional
+ -bit 3: PWRCTRL active high
+- st,pads-pull-register:
+ -bit 1: WAKEUP pull down is not active
+ -bit 2: PWRCTRL pull up is active
+ -bit 3: PWRCTRL pull down is active
+ -bit 4: WAKEUP detector is disabled
+- st,vin-control-register:
+ -bit 0: VINLOW monitoring is enabled
+ -bit [1...3]: VINLOW rising threshold
+ 000 VINOK_f + 50mV
+ 001 VINOK_f + 100mV
+ 010 VINOK_f + 150mV
+ 011 VINOK_f + 200mV
+ 100 VINOK_f + 250mV
+ 101 VINOK_f + 300mV
+ 110 VINOK_f + 350mV
+ 111 VINOK_f + 400mV
+ -bit [4...5]: VINLOW hyst
+ 00 100mV
+ 01 200mV
+ 10 300mV
+ 11 400mV
+ -bit 6: SW_OUT detector is disabled
+ -bit 7: SW_IN detector is enabled.
+- st,usb-control-register:
+ -bit 3: SW_OUT current limit
+ 0: 600mA
+ 1: 1.1A
+ -bit 4: VBUS_OTG discharge is enabled
+ -bit 5: SW_OUT discharge is enabled
+ -bit 6: VBUS_OTG detection is enabled
+ -bit 7: BOOST_OVP is disabled
+
+STPMIC1 consists in a varied group of sub-devices.
+Each sub-device binding is be described in own documentation file.
+
+Device Description
+------ ------------
+st,stpmic1-onkey : Power on key, see ../input/st,stpmic1-onkey.txt
+st,stpmic1-regulators : Regulators, see ../regulator/st,stpmic1-regulator.txt
+st,stpmic1-wdt : Watchdog, see ../watchdog/st,stpmic1-wdt.txt
+
+Example:
+
+pmic: pmic@33 {
+ compatible = "st,stpmic1";
+ reg = <0x33>;
+ interrupt-parent = <&gpioa>;
+ interrupts = <0 2>;
+ st,main-control-register=<0x0c>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ onkey {
+ compatible = "st,stpmic1-onkey";
+ interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
+ interrupt-names = "onkey-falling", "onkey-rising";
+ power-off-time-sec = <10>;
+ };
+
+ watchdog {
+ compatible = "st,stpmic1-wdt";
+ };
+
+ regulators {
+ compatible = "st,stpmic1-regulators";
+
+ vdd_core: buck1 {
+ regulator-name = "vdd_core";
+ regulator-boot-on;
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1200000>;
+ };
+ vdd: buck3 {
+ regulator-name = "vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-pull-down;
+ };
+ };
diff --git a/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt
new file mode 100644
index 0000000..b4edaf7
--- /dev/null
+++ b/docs/devicetree/bindings/reset/st,stm32mp1-rcc.txt
@@ -0,0 +1,6 @@
+STMicroelectronics STM32MP1 Peripheral Reset Controller
+=======================================================
+
+The RCC IP is both a reset and a clock controller.
+
+Please see Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt
diff --git a/docs/devicetree/bindings/rng/st,stm32-rng.txt b/docs/devicetree/bindings/rng/st,stm32-rng.txt
new file mode 100644
index 0000000..3c613d7
--- /dev/null
+++ b/docs/devicetree/bindings/rng/st,stm32-rng.txt
@@ -0,0 +1,23 @@
+STMicroelectronics STM32 HW RNG
+===============================
+
+The STM32 hardware random number generator is a simple fixed purpose IP and
+is fully separated from other crypto functions.
+
+Required properties:
+
+- compatible : Should be "st,stm32-rng"
+- reg : Should be register base and length as documented in the datasheet
+- clocks : The clock needed to enable the RNG
+
+Optional properties:
+- resets : The reset to properly start RNG
+- clock-error-detect : Enable the clock detection management
+
+Example:
+
+ rng: rng@50060800 {
+ compatible = "st,stm32-rng";
+ reg = <0x50060800 0x400>;
+ clocks = <&rcc 0 38>;
+ };
diff --git a/docs/devicetree/bindings/serial/st,stm32-usart.txt b/docs/devicetree/bindings/serial/st,stm32-usart.txt
new file mode 100644
index 0000000..08b4990
--- /dev/null
+++ b/docs/devicetree/bindings/serial/st,stm32-usart.txt
@@ -0,0 +1,88 @@
+* STMicroelectronics STM32 USART
+
+Required properties:
+- compatible: can be either:
+ - "st,stm32-uart",
+ - "st,stm32f7-uart",
+ - "st,stm32h7-uart".
+ depending is compatible with stm32(f4), stm32f7 or stm32h7.
+- reg: The address and length of the peripheral registers space
+- interrupts:
+ - The interrupt line for the USART instance,
+ - An optional wake-up interrupt.
+- interrupt-names: Contains "event" for the USART interrupt line.
+- clocks: The input clock of the USART instance
+
+Optional properties:
+- resets: Must contain the phandle to the reset controller.
+- pinctrl-names: Set to "default". An additional "sleep" state can be defined
+ to set pins in sleep state when in low power. In case the device is used as
+ a wakeup source, "idle" state is defined in order to keep RX pin active.
+ For a console device, an optional state "no_console_suspend" can be defined
+ to enable console messages during suspend. Typically, "no_console_suspend" and
+ "default" states can refer to the same pin configuration.
+- pinctrl-n: Phandle(s) pointing to pin configuration nodes.
+ For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt
+- st,hw-flow-ctrl: bool flag to enable hardware flow control.
+- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low,
+ linux,rs485-enabled-at-boot-time: see rs485.txt.
+- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt
+- dma-names: "rx" and/or "tx"
+- wakeup-source: bool flag to indicate this device has wakeup capabilities
+- interrupt-names : Should contain "wakeup" if optional wake-up interrupt is
+ used.
+
+Note for dma using:
+- "tx" dma can be used without any constraint since it uses single
+dma transfers.
+- "rx" dma using requires some attention:
+ 1) if you cannot anticipate the length of your received packets
+ and if your usart device embeds an internal fifo, then DON'T use
+ dma mode.
+ 2) if you enable dma mode WITHOUT mdma intermediate copy (cf.
+ stm32-dma.txt), then the availability of the received data will
+ depend on the dma driver policy and it may be delayed until dma
+ internal fifo is full. The usart driver will see this checking
+ the dma residue when rx interrupt (RXNE or RTO) occurs.
+ 3) if you enable dma mode WITH mdma intermediate copy (cf.
+ stm32-dma.txt) then the usart driver will never see the dma
+ residue becoming smaller than RX_BUF_P but it will get its
+ rx dma complete callback called when the cyclic transfer period
+ (RX_BUF_P) is reached.
+The three possibilities above are ordered from the most cpu time
+consuming one to the least one. The counterpart of this optimisation
+is the reception granularity achievable by the usart driver, from
+one byte up to RX_BUF_P.
+
+Examples:
+usart4: serial@40004c00 {
+ compatible = "st,stm32-uart";
+ reg = <0x40004c00 0x400>;
+ interrupts = <52>;
+ clocks = <&clk_pclk1>;
+ pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
+ pinctrl-0 = <&pinctrl_usart4>;
+ pinctrl-1 = <&pinctrl_usart4_sleep>;
+ pinctrl-2 = <&pinctrl_usart4_idle>;
+ pinctrl-3 = <&pinctrl_usart4>;
+};
+
+usart2: serial@40004400 {
+ compatible = "st,stm32-uart";
+ reg = <0x40004400 0x400>;
+ interrupts = <38>;
+ clocks = <&clk_pclk1>;
+ st,hw-flow-ctrl;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>;
+};
+
+usart1: serial@40011000 {
+ compatible = "st,stm32-uart";
+ reg = <0x40011000 0x400>;
+ interrupts = <37>;
+ clocks = <&rcc 0 164>;
+ dmas = <&dma2 2 4 0x414 0x0>,
+ <&dma2 7 4 0x414 0x0>;
+ dma-names = "rx", "tx";
+};
diff --git a/docs/devicetree/bindings/soc/st,stm32-etzpc.txt b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt
new file mode 100644
index 0000000..a2ac263
--- /dev/null
+++ b/docs/devicetree/bindings/soc/st,stm32-etzpc.txt
@@ -0,0 +1,56 @@
+STM32 ETZPC
+---------------------------------
+
+Required properties:
+- compatible: should be "st,stm32-etzpc"
+- reg: physical base address and length of the registers set for the device
+- clocks: reference to the clock entry
+
+Optional property:
+- st,decprot: Configure option to properly set firewall for IPs.
+
+Examples:
+etzpc: etzpc@5C007000 {
+ compatible = "st,stm32-etzpc";
+ reg = <0x5C007000 0x400>;
+ clocks = <&rcc TZPC>;
+ status = "disabled";
+ secure-status = "okay";
+ };
+
+Firewall specifications
+=======================
+
+DECPROT macro must be used to properly configure IP firewalling. It must
+specify ID, domain and locking register status.
+
+The macro is defined in the binding header file [1].
+
+Example:
+ ... {
+ st,decprot = <
+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_GPIOZ_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>;
+ };
+
+Specify Peripheral IDs
+=======================
+
+Each peripheral is identified with a specific ID. Each platform defines the
+identifiers relevant to that platform. Peripheral IDs are defined in [1].
+
+Specify domain
+==============
+Firewall controls peripherals in specific domains:
+
+DECPROT_S_RW 0x0 -> Read/write Secure
+DECPROT_NS_R_S_W 0x1 -> Non secure read / Read/write Secure
+DECPROT_MCU_ISOLATION 0x2 -> MCU access only
+DECPROT_NS_RW 0x3 -> Non secure read/write
+
+
+[1] include/dt-bindings/soc/st,stm32-etzpc.h
+
diff --git a/docs/devicetree/bindings/soc/st,stm32-romem.txt b/docs/devicetree/bindings/soc/st,stm32-romem.txt
new file mode 100644
index 0000000..fbff52e
--- /dev/null
+++ b/docs/devicetree/bindings/soc/st,stm32-romem.txt
@@ -0,0 +1,31 @@
+STMicroelectronics STM32 Factory-programmed data device tree bindings
+
+This represents STM32 Factory-programmed read only non-volatile area: locked
+flash, OTP, read-only HW regs... This contains various information such as:
+analog calibration data for temperature sensor (e.g. TS_CAL1, TS_CAL2),
+internal vref (VREFIN_CAL), unique device ID...
+
+Required properties:
+- compatible: Should be one of:
+ "st,stm32-romem"
+ "st,stm32mp15-bsec"
+- reg: Offset and length of factory-programmed area.
+- #address-cells: Should be '<1>'.
+- #size-cells: Should be '<1>'.
+
+Optional Data cells:
+- Must be child nodes as described in nvmem.txt.
+
+Example on stm32f4:
+ romem: nvmem@1fff7800 {
+ compatible = "st,stm32-romem";
+ reg = <0x1fff7800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells: ts_cal1 at 0x1fff7a2c */
+ ts_cal1: calib@22c {
+ reg = <0x22c 0x2>;
+ };
+ ...
+ };
diff --git a/docs/devicetree/bindings/soc/st,stm32-stgen.txt b/docs/devicetree/bindings/soc/st,stm32-stgen.txt
new file mode 100644
index 0000000..dbd962e
--- /dev/null
+++ b/docs/devicetree/bindings/soc/st,stm32-stgen.txt
@@ -0,0 +1,18 @@
+STMicroelectronics STM32 STGEN
+===============================
+
+The STM32 System Generic Counter generate a time count value. This
+is a 64 bits wide counter.
+
+Required properties:
+
+- compatible : Should be "st,stm32-stgen"
+- reg : Should be register base and length as documented in the datasheet
+
+Example:
+
+ stgen: stgen@5C008000 {
+ compatible = "st,stm32-stgen";
+ reg = <0x5C008000 0x1000>;
+ status = "okay";
+ };
diff --git a/docs/devicetree/bindings/soc/st,stm32-tamp.txt b/docs/devicetree/bindings/soc/st,stm32-tamp.txt
new file mode 100644
index 0000000..4d21c6b
--- /dev/null
+++ b/docs/devicetree/bindings/soc/st,stm32-tamp.txt
@@ -0,0 +1,22 @@
+STM32 TAMPER
+---------------------------------
+
+Required properties:
+- compatible: should be "st,stm32-tamp"
+- reg: physical base address and length of the registers set for the device
+- clocks: reference to the clock entry
+- secure-status: Required to properly disable/enable secure IP
+
+Optional property:
+- st,out3-pc13: Configure option register to map OUT3 on PC13
+- wakeup-source : Configure tamp as wakeup-src
+
+Examples:
+tamp: tamp@5C00A000 {
+ compatible = "st,stm32-tamp";
+ reg = <0x5C00A000 0x100>;
+ clocks = <&rcc_clk RTCAPB>;
+ st,out3-pc13;
+ wakeup-source;
+ secure-status = "okay";
+};
diff --git a/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt
new file mode 100644
index 0000000..2453603
--- /dev/null
+++ b/docs/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -0,0 +1,28 @@
+STM32 Independent WatchDoG (IWDG)
+---------------------------------
+
+Required properties:
+- compatible: should be "st,stm32mp1-iwdg".
+- reg: physical base address and length of the registers set for the device.
+- clocks: reference to the clock entry lsi. Additional pclk clock entry.
+ is required only for st,stm32mp1-iwdg.
+- clock-names: name of the clocks used.
+ "pclk", "lsi" for st,stm32mp1-iwdg.
+
+Optional properties:
+- timeout-sec: Watchdog timeout value in seconds.
+- secure-timeout-sec: Watchdog early timeout management in seconds.
+- stm32,enable-on-stop: Keep watchdog enable during stop.
+- stm32,enable-on-standby: Keep watchdog enable durung standby.
+- secure-status: Required to properly enable/disable secure IP.
+
+Examples:
+
+iwdg2: iwdg@5a002000 {
+ compatible = "st,stm32mp1-iwdg";
+ reg = <0x5a002000 0x400>;
+ clocks = <&rcc IWDG2>, <&clk_lsi>;
+ clock-names = "pclk", "lsi";
+ instance = <2>;
+ timeout-sec = <30>;
+};
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index 9e731a4..10ad00e 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -76,7 +76,23 @@ To build:
.. code:: bash
make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min
+ cd <u-boot_directory>
+ make stm32mp15_trusted_defconfig
+ make DEVICE_TREE=stm32mp157c_ev1 all
+ ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32
The following build options are supported:
- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection.
+
+
+Populate SD-card
+----------------
+
+The SD-card has to be formated with GPT.
+It should contain at least those partitions:
+
+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary
+- ssbl: to copy the u-boot.stm32 binary
+
+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl.
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 1667cce..bef4af6 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2554,8 +2554,13 @@ NOTE: This section assumes that your platform is enabling the MULTI_CONSOLE_API
flag in its platform.mk. Not using this flag is deprecated for new platforms.
BL31 implements a crash reporting mechanism which prints the various registers
-of the CPU to enable quick crash analysis and debugging. By default, the
-definitions in ``plat/common/aarch64/platform\_helpers.S`` will cause the crash
+of the CPU to enable quick crash analysis and debugging. This mechanism relies
+on the platform implementating ``plat_crash_console_init``,
+``plat_crash_console_putc`` and ``plat_crash_console_flush``.
+
+The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample
+implementation of all of them. Platforms may include this file to their
+makefiles in order to benefit from them. By default, they will cause the crash
output to be routed over the normal console infrastructure and get printed on
consoles configured to output in crash state. ``console_set_scope()`` can be
used to control whether a console is used for crash output.
@@ -2565,8 +2570,12 @@ normal boot console can be set up), platforms may want to control crash output
more explicitly. For these, the following functions can be overridden by
platform code. They are executed outside of a C environment and without a stack.
-Function : plat\_crash\_console\_init
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If this behaviour is not desirable, the platform may implement functions that
+redirect the prints to the console driver (``console_xxx_core_init``, etc). Most
+platforms (including Arm platforms) do this and they can be used as an example.
+
+Function : plat\_crash\_console\_init [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -2577,9 +2586,10 @@ This API is used by the crash reporting mechanism to initialize the crash
console. It must only use the general purpose registers x0 through x7 to do the
initialization and returns 1 on success.
-If you are trying to debug crashes before the console driver would normally get
-registered, you can use this to register a driver from assembly with hardcoded
-parameters. For example, you could register the 16550 driver like this:
+When using the sample implementation, if you are trying to debug crashes before
+the console driver would normally get registered, you can use this to register a
+driver from assembly with hardcoded parameters. For example, you could register
+the 16550 driver like this:
::
@@ -2595,11 +2605,11 @@ parameters. For example, you could register the 16550 driver like this:
b console_16550_register /* tail call, returns 1 on success */
endfunc plat_crash_console_init
-If you're trying to debug crashes in BL1, you can call the console_xxx_core_init
-function exported by some console drivers from here.
+If you're trying to debug crashes in BL1, you can call the
+``console_xxx_core_init`` function exported by some console drivers from here.
-Function : plat\_crash\_console\_putc
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : plat\_crash\_console\_putc [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -2612,13 +2622,13 @@ x2 to do its work. The parameter and the return value are in general purpose
register x0.
If you have registered a normal console driver in ``plat_crash_console_init``,
-you can keep the default implementation here (which calls ``console_putc()``).
+you can keep the sample implementation here (which calls ``console_putc()``).
-If you're trying to debug crashes in BL1, you can call the console_xxx_core_putc
-function exported by some console drivers from here.
+If you're trying to debug crashes in BL1, you can call the
+``console_xxx_core_putc`` function exported by some console drivers from here.
-Function : plat\_crash\_console\_flush
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : plat\_crash\_console\_flush [mandatory]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -2631,7 +2641,7 @@ registers x0 through x5 to do its work. The return value is 0 on successful
completion; otherwise the return value is -1.
If you have registered a normal console driver in ``plat_crash_console_init``,
-you can keep the default implementation here (which calls ``console_flush()``).
+you can keep the sample implementation here (which calls ``console_flush()``).
If you're trying to debug crashes in BL1, you can call the console_xx_core_flush
function exported by some console drivers from here.
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S
index 3718fff..edadaa4 100644
--- a/drivers/arm/pl011/aarch32/pl011_console.S
+++ b/drivers/arm/pl011/aarch32/pl011_console.S
@@ -1,10 +1,13 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
+#include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
#include <pl011.h>
/*
@@ -13,10 +16,18 @@
*/
#include "../../../console/aarch32/console.S"
- .globl console_core_init
- .globl console_core_putc
- .globl console_core_getc
- .globl console_core_flush
+ /*
+ * "core" functions are low-level implementations that don't require
+ * writeable memory and are thus safe to call in BL1 crash context.
+ */
+ .globl console_pl011_core_init
+ .globl console_pl011_core_putc
+ .globl console_pl011_core_getc
+ .globl console_pl011_core_flush
+
+ .globl console_pl011_putc
+ .globl console_pl011_getc
+ .globl console_pl011_flush
/* -----------------------------------------------
@@ -33,7 +44,7 @@
* Clobber list : r1, r2, r3
* -----------------------------------------------
*/
-func console_core_init
+func console_pl011_core_init
/* Check the input base address */
cmp r0, #0
beq core_init_fail
@@ -73,7 +84,53 @@ func console_core_init
core_init_fail:
mov r0, #0
bx lr
-endfunc console_core_init
+endfunc console_pl011_core_init
+
+#if MULTI_CONSOLE_API
+ .globl console_pl011_register
+
+ /* -------------------------------------------------------
+ * init console_pl011_register(console_pl011_t *console,
+ * uintptr_t base, uint32_t clk, uint32_t baud)
+ * Function to initialize and register a new PL011
+ * console. Storage passed in for the console struct
+ * *must* be persistent (i.e. not from the stack).
+ * In: r0 - UART register base address
+ * r1 - UART clock in Hz
+ * r2 - Baud rate
+ * r3 - pointer to empty console_pl011_t struct
+ * Out: return 1 on success, 0 on error
+ * Clobber list : r0, r1, r2
+ * -------------------------------------------------------
+ */
+func console_pl011_register
+ push {r4, lr}
+ mov r4, r3
+ cmp r4, #0
+ beq register_fail
+ str r0, [r4, #CONSOLE_T_PL011_BASE]
+
+ bl console_pl011_core_init
+ cmp r0, #0
+ beq register_fail
+
+ mov r0, r4
+ pop {r4, lr}
+ finish_console_register pl011 putc=1, getc=1, flush=1
+
+register_fail:
+ pop {r4, pc}
+endfunc console_pl011_register
+#else
+ .globl console_core_init
+ .globl console_core_putc
+ .globl console_core_getc
+ .globl console_core_flush
+ .equ console_core_init, console_pl011_core_init
+ .equ console_core_putc, console_pl011_core_putc
+ .equ console_core_getc, console_pl011_core_getc
+ .equ console_core_flush, console_pl011_core_flush
+#endif
/* --------------------------------------------------------
* int console_core_putc(int c, uintptr_t base_addr)
@@ -85,7 +142,7 @@ endfunc console_core_init
* Clobber list : r2
* --------------------------------------------------------
*/
-func console_core_putc
+func console_pl011_core_putc
/* Check the input parameter */
cmp r1, #0
beq putc_error
@@ -109,7 +166,26 @@ func console_core_putc
putc_error:
mov r0, #-1
bx lr
-endfunc console_core_putc
+endfunc console_pl011_core_putc
+
+ /* --------------------------------------------------------
+ * int console_pl011_putc(int c, console_pl011_t *console)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In: r0 - character to be printed
+ * r1 - pointer to console_t structure
+ * Out : return -1 on error else return character.
+ * Clobber list: r2
+ * -------------------------------------------------------
+ */
+func console_pl011_putc
+#if ENABLE_ASSERTIONS
+ cmp r1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r1, [r1, #CONSOLE_T_PL011_BASE]
+ b console_pl011_core_putc
+endfunc console_pl011_putc
/* ---------------------------------------------
* int console_core_getc(uintptr_t base_addr)
@@ -120,7 +196,7 @@ endfunc console_core_putc
* Clobber list : r0, r1
* ---------------------------------------------
*/
-func console_core_getc
+func console_pl011_core_getc
cmp r0, #0
beq getc_error
1:
@@ -134,7 +210,26 @@ func console_core_getc
getc_error:
mov r0, #-1
bx lr
-endfunc console_core_getc
+endfunc console_pl011_core_getc
+
+ /* ------------------------------------------------
+ * int console_pl011_getc(console_pl011_t *console)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 if no character is available.
+ * In : r0 - pointer to console_t structure
+ * Out: r0 - character if available, else -1
+ * Clobber list: r0, r1
+ * ------------------------------------------------
+ */
+func console_pl011_getc
+#if ENABLE_ASSERTIONS
+ cmp r0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r0, [r0, #CONSOLE_T_PL011_BASE]
+ b console_pl011_core_getc
+endfunc console_pl011_getc
/* ---------------------------------------------
* int console_core_flush(uintptr_t base_addr)
@@ -145,7 +240,7 @@ endfunc console_core_getc
* Clobber list : r0, r1
* ---------------------------------------------
*/
-func console_core_flush
+func console_pl011_core_flush
cmp r0, #0
beq flush_error
@@ -160,4 +255,22 @@ func console_core_flush
flush_error:
mov r0, #-1
bx lr
-endfunc console_core_flush
+endfunc console_pl011_core_flush
+
+ /* ---------------------------------------------
+ * int console_pl011_flush(console_pl011_t *console)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : r0 - pointer to console_t structure
+ * Out : return -1 on error else return 0.
+ * Clobber list: r0, r1
+ * ---------------------------------------------
+ */
+func console_pl011_flush
+#if ENABLE_ASSERTIONS
+ cmp r0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r0, [r0, #CONSOLE_T_PL011_BASE]
+ b console_pl011_core_flush
+endfunc console_pl011_flush
diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S
index 448501a..c4d51c8 100644
--- a/drivers/arm/pl011/aarch64/pl011_console.S
+++ b/drivers/arm/pl011/aarch64/pl011_console.S
@@ -6,6 +6,7 @@
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
#include <pl011.h>
@@ -109,7 +110,7 @@ func console_pl011_register
mov x0, x6
mov x30, x7
- finish_console_register pl011
+ finish_console_register pl011 putc=1, getc=1, flush=1
register_fail:
ret x7
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index db4f88a..1849e5a 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -68,6 +68,59 @@ DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+static inline void tzc400_clear_it(long base, uint32_t filter)
+{
+ mmio_write_32(base + INT_CLEAR, 1 << filter);
+}
+
+static inline uint32_t tzc400_get_int_by_filter(long base, uint32_t filter)
+{
+ return (mmio_read_32(base + INT_STATUS) & (1 << filter));
+}
+
+#if DEBUG
+static long tzc400_get_fail_address(long base, uint32_t filter)
+{
+ long fail_address = 0;
+
+ if (sizeof(long) == sizeof(uint32_t)) {
+ if (filter) {
+ fail_address = mmio_read_32(base +
+ FAIL_ADDRESS_LOW_OFF +
+ FILTER_OFFSET);
+ } else {
+ fail_address = mmio_read_32(base +
+ FAIL_ADDRESS_LOW_OFF);
+ }
+ } else {
+ if (filter) {
+ fail_address = mmio_read_32(base +
+ FAIL_ADDRESS_LOW_OFF +
+ FILTER_OFFSET) +
+ mmio_read_32(base +
+ FAIL_ADDRESS_HIGH_OFF +
+ FILTER_OFFSET);
+ } else {
+ fail_address = mmio_read_32(base +
+ FAIL_ADDRESS_LOW_OFF) +
+ mmio_read_32(base +
+ FAIL_ADDRESS_HIGH_OFF);
+ }
+ }
+ return fail_address;
+}
+#endif
+
+static inline uint32_t tzc400_get_fail_control(long base, uint32_t filter)
+{
+ if (filter) {
+ return mmio_read_32(base + FAIL_CONTROL_OFF +
+ FILTER_OFFSET);
+ } else {
+ return mmio_read_32(base + FAIL_CONTROL_OFF);
+ }
+}
+
static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
unsigned int filter)
{
@@ -236,3 +289,79 @@ void tzc400_disable_filters(void)
for (filter = 0; filter < tzc400.num_filters; filter++)
_tzc400_set_gate_keeper(tzc400.base, filter, 0);
}
+
+void tzc400_clear_all_interrupts(void)
+{
+ unsigned int filter;
+
+ assert(tzc400.base);
+ for (filter = 0; filter < tzc400.num_filters; filter++) {
+ mmio_write_32(tzc400.base + INT_CLEAR, 1 << filter);
+ }
+}
+
+int tzc400_is_pending_interrupt(void)
+{
+ unsigned int filter;
+
+ assert(tzc400.base);
+ for (filter = 0; filter < tzc400.num_filters; filter++) {
+ if (mmio_read_32(tzc400.base + INT_STATUS) & (1 << filter)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void tzc400_it_handler(void)
+{
+ uint32_t filter = 0;
+ uint32_t filter_it_pending = tzc400.num_filters;
+ uint32_t control_fail = 0;
+#if DEBUG
+ long address_fail = 0;
+#endif
+
+ assert(tzc400.base);
+
+ /* first display information conerning the fault access */
+ for (filter = 0; (filter < tzc400.num_filters) &&
+ (filter_it_pending == tzc400.num_filters); filter++) {
+ if (tzc400_get_int_by_filter(tzc400.base, filter))
+ filter_it_pending = filter;
+ }
+
+ if (filter_it_pending == tzc400.num_filters) {
+ ERROR("Error no it pending!!");
+ panic();
+ }
+
+#if DEBUG
+ address_fail = tzc400_get_fail_address(tzc400.base, filter_it_pending);
+ ERROR("Illegal access to 0x%lx in :\n",address_fail);
+#endif
+
+ control_fail = tzc400_get_fail_control(tzc400.base, filter_it_pending);
+
+
+
+ if ((control_fail & FAIL_CONTROL_NS_SHIFT) == FAIL_CONTROL_NS_SECURE) {
+ ERROR("\tSecure\n");
+ } else {
+ ERROR("\tNo Secure\n");
+ }
+
+ if ((control_fail & FAIL_CONTROL_PRIV_SHIFT) == FAIL_CONTROL_PRIV_PRIV) {
+ ERROR("\tPrivilege\n");
+ } else {
+ ERROR("\tUnprivilege\n");
+ }
+
+ if ((control_fail & FAIL_CONTROL_DIR_SHIFT) == FAIL_CONTROL_DIR_READ) {
+ ERROR("\tRead\n");
+ } else {
+ ERROR("\tWrite\n");
+ }
+
+ tzc400_clear_it(tzc400.base, filter_it_pending);
+}
diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S
index 6732631..116c9d8 100644
--- a/drivers/cadence/uart/aarch64/cdns_console.S
+++ b/drivers/cadence/uart/aarch64/cdns_console.S
@@ -7,6 +7,8 @@
#include <asm_macros.S>
#include <assert_macros.S>
#include <cadence/cdns_uart.h>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
/*
* "core" functions are low-level implementations that don't require
@@ -76,7 +78,7 @@ func console_cdns_register
mov x0, x6
mov x30, v7
- finish_console_register cdns
+ finish_console_register cdns putc=1, getc=1, flush=1
register_fail:
ret x7
diff --git a/drivers/console/aarch32/console.S b/drivers/console/aarch32/console.S
index a3c6546..f909609 100644
--- a/drivers/console/aarch32/console.S
+++ b/drivers/console/aarch32/console.S
@@ -3,104 +3,9 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <asm_macros.S>
- .globl console_init
- .globl console_uninit
- .globl console_putc
- .globl console_getc
- .globl console_flush
-
- /*
- * The console base is in the data section and not in .bss
- * even though it is zero-init. In particular, this allows
- * the console functions to start using this variable before
- * the runtime memory is initialized for images which do not
- * need to copy the .data section from ROM to RAM.
- */
-.section .data.console_base ; .align 2
- console_base: .word 0x0
-
- /* -----------------------------------------------
- * int console_init(uintptr_t base_addr,
- * unsigned int uart_clk, unsigned int baud_rate)
- * Function to initialize the console without a
- * C Runtime to print debug information. It saves
- * the console base to the data section.
- * In: r0 - console base address
- * r1 - Uart clock in Hz
- * r2 - Baud rate
- * out: return 1 on success else 0 on error
- * Clobber list : r1 - r3
- * -----------------------------------------------
- */
-func console_init
- /* Check the input base address */
- cmp r0, #0
- beq init_fail
- ldr r3, =console_base
- str r0, [r3]
- b console_core_init
-init_fail:
- bx lr
-endfunc console_init
-
- /* -----------------------------------------------
- * void console_uninit(void)
- * Function to finish the use of console driver.
- * It sets the console_base as NULL so that any
- * further invocation of `console_putc` or
- * `console_getc` APIs would return error.
- * -----------------------------------------------
- */
-func console_uninit
- mov r0, #0
- ldr r3, =console_base
- str r0, [r3]
- bx lr
-endfunc console_uninit
-
- /* ---------------------------------------------
- * int console_putc(int c)
- * Function to output a character over the
- * console. It returns the character printed on
- * success or -1 on error.
- * In : r0 - character to be printed
- * Out : return -1 on error else return character.
- * Clobber list : r1, r2
- * ---------------------------------------------
- */
-func console_putc
- ldr r2, =console_base
- ldr r1, [r2]
- b console_core_putc
-endfunc console_putc
-
- /* ---------------------------------------------
- * int console_getc(void)
- * Function to get a character from the console.
- * It returns the character grabbed on success
- * or -1 on error.
- * Clobber list : r0, r1
- * ---------------------------------------------
- */
-func console_getc
- ldr r1, =console_base
- ldr r0, [r1]
- b console_core_getc
-endfunc console_getc
-
- /* ---------------------------------------------
- * int console_flush(void)
- * Function to force a write of all buffered
- * data that hasn't been output. It returns 0
- * upon successful completion, otherwise it
- * returns -1.
- * Clobber list : r0, r1
- * ---------------------------------------------
- */
-func console_flush
- ldr r1, =console_base
- ldr r0, [r1]
- b console_core_flush
-endfunc console_flush
+ #if MULTI_CONSOLE_API
+ #include "multi_console.S"
+ #else
+ #include "deprecated_console.S"
+ #endif
diff --git a/drivers/console/aarch32/deprecated_console.S b/drivers/console/aarch32/deprecated_console.S
new file mode 100644
index 0000000..f7e3c4f
--- /dev/null
+++ b/drivers/console/aarch32/deprecated_console.S
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+
+/*
+ * This is the common console core code for the deprecated single-console API.
+ * New platforms should set MULTI_CONSOLE_API=1 and not use this file.
+ */
+#warning "Using deprecated console implementation. Please migrate to MULTI_CONSOLE_API"
+
+ .globl console_init
+ .globl console_uninit
+ .globl console_putc
+ .globl console_getc
+ .globl console_flush
+
+ /*
+ * The console base is in the data section and not in .bss
+ * even though it is zero-init. In particular, this allows
+ * the console functions to start using this variable before
+ * the runtime memory is initialized for images which do not
+ * need to copy the .data section from ROM to RAM.
+ */
+.section .data.console_base ; .align 2
+ console_base: .word 0x0
+
+ /* -----------------------------------------------
+ * int console_init(uintptr_t base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. It saves
+ * the console base to the data section.
+ * In: r0 - console base address
+ * r1 - Uart clock in Hz
+ * r2 - Baud rate
+ * out: return 1 on success else 0 on error
+ * Clobber list : r1 - r3
+ * -----------------------------------------------
+ */
+func console_init
+ /* Check the input base address */
+ cmp r0, #0
+ beq init_fail
+ ldr r3, =console_base
+ str r0, [r3]
+ b console_core_init
+init_fail:
+ bx lr
+endfunc console_init
+
+ /* -----------------------------------------------
+ * void console_uninit(void)
+ * Function to finish the use of console driver.
+ * It sets the console_base as NULL so that any
+ * further invocation of `console_putc` or
+ * `console_getc` APIs would return error.
+ * -----------------------------------------------
+ */
+func console_uninit
+ mov r0, #0
+ ldr r3, =console_base
+ str r0, [r3]
+ bx lr
+endfunc console_uninit
+
+ /* ---------------------------------------------
+ * int console_putc(int c)
+ * Function to output a character over the
+ * console. It returns the character printed on
+ * success or -1 on error.
+ * In : r0 - character to be printed
+ * Out : return -1 on error else return character.
+ * Clobber list : r1, r2
+ * ---------------------------------------------
+ */
+func console_putc
+ ldr r2, =console_base
+ ldr r1, [r2]
+ b console_core_putc
+endfunc console_putc
+
+ /* ---------------------------------------------
+ * int console_getc(void)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on error.
+ * Clobber list : r0, r1
+ * ---------------------------------------------
+ */
+func console_getc
+ ldr r1, =console_base
+ ldr r0, [r1]
+ b console_core_getc
+endfunc console_getc
+
+ /* ---------------------------------------------
+ * int console_flush(void)
+ * Function to force a write of all buffered
+ * data that hasn't been output. It returns 0
+ * upon successful completion, otherwise it
+ * returns -1.
+ * Clobber list : r0, r1
+ * ---------------------------------------------
+ */
+func console_flush
+ ldr r1, =console_base
+ ldr r0, [r1]
+ b console_core_flush
+endfunc console_flush
diff --git a/drivers/console/aarch32/multi_console.S b/drivers/console/aarch32/multi_console.S
new file mode 100644
index 0000000..e23b20e
--- /dev/null
+++ b/drivers/console/aarch32/multi_console.S
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <console.h>
+
+ .globl console_register
+ .globl console_unregister
+ .globl console_is_registered
+ .globl console_set_scope
+ .globl console_switch_state
+ .globl console_putc
+ .globl console_getc
+ .globl console_flush
+
+ /*
+ * The console list pointer is in the data section and not in
+ * .bss even though it is zero-init. In particular, this allows
+ * the console functions to start using this variable before
+ * the runtime memory is initialized for images which do not
+ * need to copy the .data section from ROM to RAM.
+ */
+.section .data.console_list ; .align 2
+ console_list: .word 0x0
+.section .data.console_state ; .align 0
+ console_state: .byte CONSOLE_FLAG_BOOT
+
+ /* -----------------------------------------------
+ * int console_register(console_t *console)
+ * Function to insert a new console structure into
+ * the console list. Should usually be called by
+ * console_<driver>_register implementations. The
+ * data structure passed will be taken over by the
+ * console framework and *MUST* be allocated in
+ * persistent memory (e.g. the data section).
+ * In : r0 - address of console_t structure
+ * Out: r0 - Always 1 (for easier tail calling)
+ * Clobber list: r0, r1
+ * -----------------------------------------------
+ */
+func console_register
+ push {r6, lr}
+#if ENABLE_ASSERTIONS
+ /* Assert that r0 isn't a NULL pointer */
+ cmp r0, #0
+ ASM_ASSERT(ne)
+ /* Assert that the struct isn't in the stack */
+ ldr r1, =__STACKS_START__
+ cmp r0, r1
+ blo not_on_stack
+ ldr r1, =__STACKS_END__
+ cmp r0, r1
+ ASM_ASSERT(hs)
+not_on_stack:
+ /* Assert that this struct isn't in the list */
+ mov r1, r0 /* Preserve r0 and lr */
+ bl console_is_registered
+ cmp r0, #0
+ ASM_ASSERT(eq)
+ mov r0, r1
+#endif /* ENABLE_ASSERTIONS */
+ ldr r6, =console_list
+ ldr r1, [r6] /* R1 = first struct in list */
+ str r0, [r6] /* list head = new console */
+ str r1, [r0, #CONSOLE_T_NEXT] /* new console next ptr = R1 */
+ mov r0, #1
+ pop {r6, pc}
+endfunc console_register
+
+ /* -----------------------------------------------
+ * int console_unregister(console_t *console)
+ * Function to find a specific console in the list
+ * of currently active consoles and remove it.
+ * In: r0 - address of console_t struct to remove
+ * Out: r0 - removed address, or NULL if not found
+ * Clobber list: r0, r1
+ * -----------------------------------------------
+ */
+func console_unregister
+#if ENABLE_ASSERTIONS
+ /* Assert that r0 isn't a NULL pointer */
+ cmp r0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ push {r6}
+ ldr r6, =console_list /* R6 = ptr to first struct */
+ ldr r1, [r6] /* R1 = first struct */
+
+unregister_loop:
+ cmp r1, #0
+ beq unregister_not_found
+ cmp r0, r1
+ beq unregister_found
+ ldr r6, [r6] /* R6 = next ptr of struct */
+ ldr r1, [r6] /* R1 = next struct */
+ b unregister_loop
+
+unregister_found:
+ ldr r1, [r1] /* R1 = next struct */
+ str r1, [r6] /* prev->next = cur->next */
+ pop {r6}
+ bx lr
+
+unregister_not_found:
+ mov r0, #0 /* return NULL if not found */
+ pop {r6}
+ bx lr
+endfunc console_unregister
+
+ /* -----------------------------------------------
+ * int console_is_registered(console_t *console)
+ * Function to detect if a specific console is
+ * registered or not.
+ * In: r0 - address of console_t struct to remove
+ * Out: r0 - 1 if it is registered, 0 if not.
+ * Clobber list: r0
+ * -----------------------------------------------
+ */
+func console_is_registered
+#if ENABLE_ASSERTIONS
+ /* Assert that r0 isn't a NULL pointer */
+ cmp r0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ push {r6}
+ ldr r6, =console_list
+ ldr r6, [r6] /* R6 = first console struct */
+check_registered_loop:
+ cmp r6, #0 /* Check if end of list */
+ beq console_not_registered
+ cmp r0, r6 /* Check if the pointers are different */
+ beq console_registered
+ ldr r6, [r6, #CONSOLE_T_NEXT] /* Get pointer to next struct */
+ b check_registered_loop
+console_not_registered:
+ mov r0, #0
+ pop {r6}
+ bx lr
+console_registered:
+ mov r0, #1
+ pop {r6}
+ bx lr
+endfunc console_is_registered
+
+ /* -----------------------------------------------
+ * void console_switch_state(unsigned int new_state)
+ * Function to switch the current console state.
+ * The console state determines which of the
+ * registered consoles are actually used at a time.
+ * In : r0 - global console state to move to
+ * Clobber list: r0, r1
+ * -----------------------------------------------
+ */
+func console_switch_state
+ ldr r1, =console_state
+ strb r0, [r1]
+ bx lr
+endfunc console_switch_state
+
+ /* -----------------------------------------------
+ * void console_set_scope(console_t *console,
+ * unsigned int scope)
+ * Function to update the states that a given console
+ * may be active in.
+ * In : r0 - pointer to console_t struct
+ * : r1 - new active state mask
+ * Clobber list: r0, r1, r2
+ * -----------------------------------------------
+ */
+func console_set_scope
+#if ENABLE_ASSERTIONS
+ ands r2, r1, #~CONSOLE_FLAG_SCOPE_MASK
+ ASM_ASSERT(eq)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r2, [r0, #CONSOLE_T_FLAGS]
+ and r2, r2, #~CONSOLE_FLAG_SCOPE_MASK
+ orr r2, r2, r1
+ str r2, [r0, #CONSOLE_T_FLAGS]
+ bx lr
+endfunc console_set_scope
+
+ /* ---------------------------------------------
+ * int console_putc(int c)
+ * Function to output a character. Calls all
+ * active console's putc() handlers in succession.
+ * In : r0 - character to be printed
+ * Out: r0 - printed character on success, or < 0
+ if at least one console had an error
+ * Clobber list : r0, r1, r2
+ * ---------------------------------------------
+ */
+func console_putc
+ push {r4-r6, lr}
+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */
+ mov r4, r0 /* R4 = character to print */
+ ldr r6, =console_list
+ ldr r6, [r6] /* R6 = first console struct */
+
+putc_loop:
+ cmp r6, #0
+ beq putc_done
+ ldr r1, =console_state
+ ldrb r1, [r1]
+ ldr r2, [r6, #CONSOLE_T_FLAGS]
+ tst r1, r2
+ beq putc_continue
+ ldr r2, [r6, #CONSOLE_T_PUTC]
+ cmp r2, #0
+ beq putc_continue
+ mov r0, r4
+ mov r1, r6
+ blx r2
+ cmp r5, #ERROR_NO_VALID_CONSOLE /* update R5 if it's NOVALID */
+ cmpne r0, #0 /* else update it if R0 < 0 */
+ movlt r5, r0
+putc_continue:
+ ldr r6, [r6] /* R6 = next struct */
+ b putc_loop
+
+putc_done:
+ mov r0, r5
+ pop {r4-r6, pc}
+endfunc console_putc
+
+ /* ---------------------------------------------
+ * int console_getc(void)
+ * Function to get a character from any console.
+ * Keeps looping through all consoles' getc()
+ * handlers until one of them returns a
+ * character, then stops iterating and returns
+ * that character to the caller. Will stop looping
+ * if all active consoles report real errors
+ * (other than just not having a char available).
+ * Out : r0 - read character, or < 0 on error
+ * Clobber list : r0, r1
+ * ---------------------------------------------
+ */
+func console_getc
+ push {r5-r6, lr}
+getc_try_again:
+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */
+ ldr r6, =console_list
+ ldr r6, [r6] /* R6 = first console struct */
+ cmp r6, #0
+ bne getc_loop
+ mov r0, r5 /* If no consoles registered */
+ pop {r5-r6, pc} /* return immediately. */
+
+getc_loop:
+ ldr r0, =console_state
+ ldrb r0, [r0]
+ ldr r1, [r6, #CONSOLE_T_FLAGS]
+ tst r0, r1
+ beq getc_continue
+ ldr r1, [r6, #CONSOLE_T_GETC]
+ cmp r1, #0
+ beq getc_continue
+ mov r0, r6
+ blx r1
+ cmp r0, #0 /* if R0 >= 0: return */
+ bge getc_found
+ cmp r5, #ERROR_NO_PENDING_CHAR /* may update R5 (NOCHAR has */
+ movne r5, r0 /* precedence vs real errors) */
+getc_continue:
+ ldr r6, [r6] /* R6 = next struct */
+ cmp r6, #0
+ bne getc_loop
+ cmp r5, #ERROR_NO_PENDING_CHAR /* Keep scanning if at least */
+ beq getc_try_again /* one console returns NOCHAR */
+ mov r0, r5
+
+getc_found:
+ pop {r5-r6, pc}
+endfunc console_getc
+
+ /* ---------------------------------------------
+ * int console_flush(void)
+ * Function to force a write of all buffered
+ * data that hasn't been output. Calls all
+ * console's flush() handlers in succession.
+ * Out: r0 - 0 on success, < 0 if at least one error
+ * Clobber list : r0, r1, r2
+ * ---------------------------------------------
+ */
+func console_flush
+ push {r5-r6, lr}
+ mov r5, #ERROR_NO_VALID_CONSOLE /* R5 = current return value */
+ ldr r6, =console_list
+ ldr r6, [r6] /* R6 = first console struct */
+
+flush_loop:
+ cmp r6, #0
+ beq flush_done
+ ldr r1, =console_state
+ ldrb r1, [r1]
+ ldr r2, [r6, #CONSOLE_T_FLAGS]
+ tst r1, r2
+ beq flush_continue
+ ldr r1, [r6, #CONSOLE_T_FLUSH]
+ cmp r1, #0
+ beq flush_continue
+ mov r0, r6
+ blx r1
+ cmp r5, #ERROR_NO_VALID_CONSOLE /* update R5 if it's NOVALID */
+ cmpne r0, #0 /* else update it if R0 < 0 */
+ movlt r5, r0
+flush_continue:
+ ldr r6, [r6] /* R6 = next struct */
+ b flush_loop
+
+flush_done:
+ mov r0, r5
+ pop {r5-r6, pc}
+endfunc console_flush
diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S
index 1b5d739..3993eef 100644
--- a/drivers/console/aarch64/skeleton_console.S
+++ b/drivers/console/aarch64/skeleton_console.S
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
/*
@@ -60,8 +61,12 @@ func console_xxx_register
* Keep console_t pointer in x0 for later.
*/
- /* Macro to finish up registration and return (needs valid x0 + x30). */
- finish_console_register xxx
+ /*
+ * Macro to finish up registration and return (needs valid x0 + x30).
+ * If any of the argument is unspecified, then the corresponding
+ * entry in console_t is set to 0.
+ */
+ finish_console_register xxx putc=1, getc=1, flush=1
/* Jump here if hardware init fails or parameters are invalid. */
register_fail:
diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
index 2fc0603..ae9a25b 100644
--- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
+++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
@@ -6,6 +6,7 @@
#include <asm_macros.S>
#include <cbmem_console.h>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
/*
@@ -39,7 +40,7 @@ func console_cbmc_register
ldr w2, [x0]
str w2, [x1, #CONSOLE_T_CBMC_SIZE]
mov x0, x1
- finish_console_register cbmc
+ finish_console_register cbmc putc=1, flush=1
endfunc console_cbmc_register
/* -----------------------------------------------
diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c
index 8226554..3a2f403 100644
--- a/drivers/io/io_block.c
+++ b/drivers/io/io_block.c
@@ -27,7 +27,7 @@ io_type_t device_type_block(void);
static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity);
-static int block_seek(io_entity_t *entity, int mode, ssize_t offset);
+static int block_seek(io_entity_t *entity, int mode, signed long long offset);
static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read);
static int block_write(io_entity_t *entity, const uintptr_t buffer,
@@ -67,8 +67,10 @@ io_type_t device_type_block(void)
static int find_first_block_state(const io_block_dev_spec_t *dev_spec,
unsigned int *index_out)
{
+ unsigned int index;
int result = -ENOENT;
- for (int index = 0; index < MAX_IO_BLOCK_DEVICES; ++index) {
+
+ for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) {
/* dev_spec is used as identifier since it's unique */
if (state_pool[index].dev_spec == dev_spec) {
result = 0;
@@ -144,7 +146,7 @@ static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
}
/* parameter offset is relative address at here */
-static int block_seek(io_entity_t *entity, int mode, ssize_t offset)
+static int block_seek(io_entity_t *entity, int mode, signed long long offset)
{
block_dev_state_t *cur;
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index 5595e60..8add0b8 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -40,7 +40,7 @@ static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity);
static int memmap_block_seek(io_entity_t *entity, int mode,
- ssize_t offset);
+ signed long long offset);
static int memmap_block_len(io_entity_t *entity, size_t *length);
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read);
@@ -127,7 +127,8 @@ static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
/* Seek to a particular file offset on the memmap device */
-static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset)
+static int memmap_block_seek(io_entity_t *entity, int mode,
+ signed long long offset)
{
int result = -ENOENT;
file_state_t *fp;
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 9ca0a9d..125fea9 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.c
@@ -25,7 +25,7 @@ static io_type_t device_type_sh(void)
static int sh_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
static int sh_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity);
-static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset);
+static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset);
static int sh_file_len(io_entity_t *entity, size_t *length);
static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read);
@@ -90,7 +90,7 @@ static int sh_file_open(io_dev_info_t *dev_info __unused,
/* Seek to a particular file offset on the semi-hosting device */
-static int sh_file_seek(io_entity_t *entity, int mode, ssize_t offset)
+static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset)
{
long file_handle, sh_result;
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index 948f848..90282a2 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -239,7 +239,7 @@ int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle)
/* Seek to a specific position in an IO entity */
-int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset)
+int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset)
{
int result = -ENODEV;
assert(is_valid_entity(handle) && is_valid_seek_mode(mode));
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 418ab11..4f9cecf 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -246,6 +246,13 @@ static int mmc_fill_device_info(void)
return ret;
}
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return ret;
+ }
+ } while (ret != MMC_STATE_TRAN);
+
nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
(mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
(mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
@@ -292,7 +299,7 @@ static int mmc_fill_device_info(void)
break;
}
- if (ret != 0) {
+ if (ret < 0) {
return ret;
}
@@ -379,7 +386,10 @@ static int mmc_send_op_cond(void)
int ret, n;
unsigned int resp_data[4];
- mmc_reset_to_idle();
+ ret = mmc_reset_to_idle();
+ if (ret != 0) {
+ return ret;
+ };
for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
@@ -394,7 +404,7 @@ static int mmc_send_op_cond(void)
return 0;
}
- mdelay(1);
+ mdelay(10);
}
ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
@@ -409,7 +419,10 @@ static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
ops->init();
- mmc_reset_to_idle();
+ ret = mmc_reset_to_idle();
+ if (ret != 0) {
+ return ret;
+ };
if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
ret = mmc_send_op_cond();
diff --git a/drivers/partition/gpt.c b/drivers/partition/gpt.c
index 9cc917d..0c51e62 100644
--- a/drivers/partition/gpt.c
+++ b/drivers/partition/gpt.c
@@ -13,10 +13,14 @@
static int unicode_to_ascii(unsigned short *str_in, unsigned char *str_out)
{
- uint8_t *name = (uint8_t *)str_in;
+ uint8_t *name;
int i;
- assert((str_in != NULL) && (str_out != NULL) && (name[0] != '\0'));
+ assert((str_in != NULL) && (str_out != NULL));
+
+ name = (uint8_t *)str_in;
+
+ assert(name[0] != '\0');
/* check whether the unicode string is valid */
for (i = 1; i < (EFI_NAMELEN << 1); i += 2) {
@@ -36,7 +40,7 @@ int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry)
{
int result;
- assert((gpt_entry != 0) && (entry != 0));
+ assert((gpt_entry != NULL) && (entry != NULL));
if ((gpt_entry->first_lba == 0) && (gpt_entry->last_lba == 0)) {
return -EINVAL;
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c
index d6fb4b8..6085b86 100644
--- a/drivers/partition/partition.c
+++ b/drivers/partition/partition.c
@@ -30,7 +30,7 @@ static void dump_entries(int num)
name[len + j] = ' ';
}
name[EFI_NAMELEN - 1] = '\0';
- VERBOSE("%d: %s %lx-%lx\n", i + 1, name, list.list[i].start,
+ VERBOSE("%d: %s %llx-%llx\n", i + 1, name, list.list[i].start,
list.list[i].start + list.list[i].length - 4);
}
}
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
new file mode 100644
index 0000000..c579c41
--- /dev/null
+++ b/drivers/st/bsec/bsec.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bsec.h>
+#include <debug.h>
+#include <limits.h>
+#include <mmio.h>
+#include <spinlock.h>
+#include <stdint.h>
+#include <stm32mp_dt.h>
+
+#define BSEC_IP_VERSION_1_0 0x10
+#define BSEC_COMPAT "st,stm32mp15-bsec"
+
+#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT)
+
+static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused;
+
+static uint32_t bsec_power_safmem(bool power);
+
+/* BSEC access protection */
+static spinlock_t bsec_spinlock;
+static uintptr_t bsec_base;
+
+static void bsec_lock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Lock is currently required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_lock(&bsec_spinlock);
+ }
+}
+
+static void bsec_unlock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Unlock is required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_unlock(&bsec_spinlock);
+ }
+}
+
+static int bsec_get_dt_node(struct dt_node_info *info)
+{
+ int node;
+
+ node = dt_get_node(info, -1, BSEC_COMPAT);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return node;
+}
+
+#if defined(IMAGE_BL32)
+static void enable_non_secure_access(uint32_t otp)
+{
+ otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT);
+
+ if (bsec_shadow_register(otp) != BSEC_OK) {
+ panic();
+ }
+}
+
+static bool non_secure_can_access(uint32_t otp)
+{
+ return (otp_nsec_access[otp / __WORD_BIT] &
+ BIT(otp % __WORD_BIT)) != 0;
+}
+
+static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
+{
+ int bsec_subnode;
+
+ fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
+ const fdt32_t *cuint;
+ uint32_t reg;
+ uint32_t i;
+ uint32_t size;
+ uint8_t status;
+
+ cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
+ if (reg < STM32MP1_UPPER_OTP_START) {
+ continue;
+ }
+
+ status = fdt_get_status(bsec_subnode);
+ if ((status & DT_NON_SECURE) == 0U) {
+ continue;
+ }
+
+ size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t);
+
+ if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) {
+ size++;
+ }
+
+ for (i = reg; i < (reg + size); i++) {
+ enable_non_secure_access(i);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static uint32_t otp_bank_offset(uint32_t otp)
+{
+ assert(otp <= STM32MP1_OTP_MAX_ID);
+
+ return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) *
+ sizeof(uint32_t);
+}
+
+static uint32_t bsec_check_error(uint32_t otp)
+{
+ 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;
+ }
+
+ return BSEC_OK;
+}
+
+/*
+ * bsec_probe: initialize BSEC driver.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_probe(void)
+{
+ void *fdt;
+ int node;
+ struct dt_node_info bsec_info;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = bsec_get_dt_node(&bsec_info);
+ if (node < 0) {
+ panic();
+ }
+
+ bsec_base = bsec_info.base;
+
+#if defined(IMAGE_BL32)
+ bsec_dt_otp_nsec_access(fdt, node);
+#endif
+ return BSEC_OK;
+}
+
+/*
+ * bsec_get_base: return BSEC base address.
+ */
+uint32_t bsec_get_base(void)
+{
+ return bsec_base;
+}
+
+/*
+ * bsec_set_config: enable and configure BSEC.
+ * cfg: pointer to param structure used to set register.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_set_config(struct bsec_config *cfg)
+{
+ uint32_t value;
+ int32_t result;
+
+ value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) &
+ BSEC_CONF_FRQ_MASK) |
+ (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) &
+ BSEC_CONF_PRG_WIDTH_MASK) |
+ (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) &
+ BSEC_CONF_TREAD_MASK));
+
+ bsec_lock();
+
+ mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value);
+
+ bsec_unlock();
+
+ result = bsec_power_safmem((bool)cfg->power &
+ BSEC_CONF_POWER_UP_MASK);
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) &
+ UPPER_OTP_LOCK_MASK) |
+ (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) &
+ DENREG_LOCK_MASK) |
+ (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) &
+ GPLOCK_LOCK_MASK));
+
+ bsec_lock();
+
+ mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value);
+
+ bsec_unlock();
+
+ return BSEC_OK;
+}
+
+/*
+ * bsec_get_config: return config parameters set in BSEC registers.
+ * cfg: config param return.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_get_config(struct bsec_config *cfg)
+{
+ uint32_t value;
+
+ if (cfg == NULL) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
+ cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >>
+ BSEC_CONF_POWER_UP_SHIFT);
+ cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >>
+ BSEC_CONF_FRQ_SHIFT);
+ cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >>
+ BSEC_CONF_PRG_WIDTH_SHIFT);
+ cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >>
+ BSEC_CONF_TREAD_SHIFT);
+
+ value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF);
+ cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >>
+ UPPER_OTP_LOCK_SHIFT);
+ cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >>
+ DENREG_LOCK_SHIFT);
+ cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >>
+ GPLOCK_LOCK_SHIFT);
+
+ return BSEC_OK;
+}
+
+/*
+ * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_shadow_register(uint32_t otp)
+{
+ uint32_t result;
+ bool power_up = false;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if shadowing of OTP is locked */
+ if (bsec_read_sr_lock(otp)) {
+ VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n",
+ otp);
+ }
+
+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
+ result = bsec_power_safmem(true);
+
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ power_up = true;
+ }
+
+ 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);
+
+ bsec_unlock();
+
+ if (power_up) {
+ if (bsec_power_safmem(false) != BSEC_OK) {
+ panic();
+ }
+ }
+
+ return result;
+}
+
+/*
+ * bsec_read_otp: read an OTP data value.
+ * val: read value.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+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;
+}
+
+/*
+ * bsec_write_otp: write value in BSEC data register.
+ * val: value to write.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
+{
+ uint32_t result;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if programming of OTP is locked */
+ if (bsec_read_sw_lock(otp)) {
+ VERBOSE("BSEC: OTP %i is locked and write will be ignored\n",
+ otp);
+ }
+
+ 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;
+}
+
+/*
+ * bsec_program_otp: program a bit in SAFMEM after the prog.
+ * The OTP data is not refreshed.
+ * val: value to program.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
+{
+ uint32_t result;
+ bool power_up = false;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if programming of OTP is locked */
+ if (bsec_read_sp_lock(otp)) {
+ WARN("BSEC: OTP locked, prog will be ignored\n");
+ }
+
+ if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) &
+ BIT(BSEC_LOCK_PROGRAM)) != 0U) {
+ WARN("BSEC: GPLOCK activated, prog will be ignored\n");
+ }
+
+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
+ result = bsec_power_safmem(true);
+
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ power_up = true;
+ }
+
+ 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) {
+ ;
+ }
+
+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
+ result = BSEC_PROG_FAIL;
+ } else {
+ result = bsec_check_error(otp);
+ }
+
+ bsec_unlock();
+
+ if (power_up) {
+ if (bsec_power_safmem(false) != BSEC_OK) {
+ panic();
+ }
+ }
+
+ return result;
+}
+
+/*
+ * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM.
+ * otp: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_permanent_lock_otp(uint32_t otp)
+{
+ uint32_t result;
+ bool power_up = false;
+ uint32_t data;
+ uint32_t addr;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
+ result = bsec_power_safmem(true);
+
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ power_up = true;
+ }
+
+ if (otp < STM32MP1_UPPER_OTP_START) {
+ addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT;
+ data = DATA_LOWER_OTP_PERLOCK_BIT <<
+ ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U);
+ } else {
+ addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U;
+ data = DATA_UPPER_OTP_PERLOCK_BIT <<
+ (otp & DATA_UPPER_OTP_PERLOCK_MASK);
+ }
+
+ 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);
+
+ while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
+ ;
+ }
+
+ if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
+ result = BSEC_PROG_FAIL;
+ } else {
+ result = bsec_check_error(otp);
+ }
+
+ bsec_unlock();
+
+ if (power_up) {
+ if (bsec_power_safmem(false) != BSEC_OK) {
+ panic();
+ }
+ }
+
+ return result;
+}
+
+/*
+ * 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.
+ */
+uint32_t bsec_write_debug_conf(uint32_t val)
+{
+ uint32_t result = BSEC_ERROR;
+ uint32_t masked_val = val & BSEC_DEN_ALL_MSK;
+
+ bsec_lock();
+
+ mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val);
+
+ if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) {
+ result = BSEC_OK;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_debug_conf: read debug configuration.
+ */
+uint32_t bsec_read_debug_conf(void)
+{
+ return mmio_read_32(bsec_base + BSEC_DEN_OFF);
+}
+
+/*
+ * bsec_get_status: return status register value.
+ */
+uint32_t bsec_get_status(void)
+{
+ return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF);
+}
+
+/*
+ * bsec_get_hw_conf: return hardware configuration.
+ */
+uint32_t bsec_get_hw_conf(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF);
+}
+
+/*
+ * bsec_get_version: return BSEC version.
+ */
+uint32_t bsec_get_version(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IPVR_OFF);
+}
+
+/*
+ * bsec_get_id: return BSEC ID.
+ */
+uint32_t bsec_get_id(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IP_ID_OFF);
+}
+
+/*
+ * bsec_get_magic_id: return BSEC magic number.
+ */
+uint32_t bsec_get_magic_id(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF);
+}
+
+/*
+ * bsec_write_sr_lock: write 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.
+ */
+bool bsec_write_sr_lock(uint32_t otp, uint32_t value)
+{
+ 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;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sr_lock: read shadow-read lock.
+ * otp: OTP number.
+ * return: true if otp is locked, else false.
+ */
+bool bsec_read_sr_lock(uint32_t otp)
+{
+ 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);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_write_sw_lock: write 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.
+ */
+bool bsec_write_sw_lock(uint32_t otp, uint32_t value)
+{
+ 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;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sw_lock: read shadow-write lock.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_read_sw_lock(uint32_t otp)
+{
+ 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);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_write_sp_lock: write 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.
+ */
+bool bsec_write_sp_lock(uint32_t otp, uint32_t value)
+{
+ 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;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sp_lock: read shadow-program lock.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_read_sp_lock(uint32_t otp)
+{
+ 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);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_wr_lock: Read permanent lock status.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_wr_lock(uint32_t otp)
+{
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK);
+
+ 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;
+ }
+
+ return false;
+}
+
+/*
+ * 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.
+ */
+uint32_t bsec_otp_lock(uint32_t service, uint32_t value)
+{
+ 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);
+ break;
+ case BSEC_LOCK_DEBUG:
+ mmio_write_32(reg, value << BSEC_LOCK_DEBUG);
+ break;
+ case BSEC_LOCK_PROGRAM:
+ mmio_write_32(reg, value << BSEC_LOCK_PROGRAM);
+ break;
+ default:
+ return BSEC_INVALID_PARAM;
+ }
+
+ return BSEC_OK;
+}
+
+/*
+ * bsec_power_safmem: Activate or deactivate SAFMEM power.
+ * power: true to power up, false to power down.
+ * return: BSEC_OK if succeed.
+ */
+static uint32_t bsec_power_safmem(bool power)
+{
+ uint32_t register_val;
+ uint32_t timeout = BSEC_TIMEOUT_VALUE;
+
+ bsec_lock();
+
+ register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
+
+ if (power) {
+ register_val |= BSEC_CONF_POWER_UP_MASK;
+ } else {
+ register_val &= ~BSEC_CONF_POWER_UP_MASK;
+ }
+
+ 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)) {
+ timeout--;
+ }
+ } else {
+ while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) &&
+ (timeout != 0U)) {
+ timeout--;
+ }
+ }
+
+ bsec_unlock();
+
+ if (timeout == 0U) {
+ return BSEC_TIMEOUT;
+ }
+
+ return BSEC_OK;
+}
+
+/*
+ * 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
+ * otp_value: read value.
+ * word: OTP number.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word)
+{
+ uint32_t result;
+
+ result = bsec_shadow_register(word);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: %u Shadowing Error %i\n", word, result);
+ return result;
+ }
+
+ result = bsec_read_otp(otp_value, word);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: %u Read Error %i\n", word, result);
+ }
+
+ return result;
+}
+
+/*
+ * bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
+ * otp: OTP number.
+ * return: BSEC_OK if authorized access.
+ */
+uint32_t bsec_check_nsec_access_rights(uint32_t otp)
+{
+#if defined(IMAGE_BL32)
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ 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;
+ }
+ }
+ }
+#endif
+
+ return BSEC_OK;
+}
+
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index f0bf363..b304315 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -9,26 +9,34 @@
#include <assert.h>
#include <debug.h>
#include <delay_timer.h>
-#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <errno.h>
#include <generic_delay_timer.h>
#include <libfdt.h>
#include <mmio.h>
#include <platform.h>
+#include <spinlock.h>
#include <stdint.h>
#include <stdio.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_shres_helpers.h>
#include <stm32mp1_clk.h>
#include <stm32mp1_clkfunc.h>
-#include <stm32mp1_dt.h>
#include <stm32mp1_private.h>
#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#if defined(IMAGE_BL32)
+#include <stm32_timer.h>
+#endif
#include <utils_def.h>
#define MAX_HSI_HZ 64000000
+#define USB_PHY_48_MHZ 48000000
-#define TIMEOUT_200MS (plat_get_syscnt_freq2() / 5U)
-#define TIMEOUT_1S plat_get_syscnt_freq2()
+#define TIMEOUT_200MS ms2tick(200)
+#define TIMEOUT_1S s2tick(1)
#define PLLRDY_TIMEOUT TIMEOUT_200MS
#define CLKSRC_TIMEOUT TIMEOUT_200MS
@@ -36,6 +44,10 @@
#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 */
@@ -66,12 +78,21 @@ enum stm32mp1_parent_id {
_HCLK2,
_CK_PER,
_CK_MPU,
+ _CK_MCU,
+ _USB_PHY_48,
_PARENT_NB,
_UNKNOWN_ID = 0xff,
};
+/* Lists only the parent clock we are interested in */
enum stm32mp1_parent_sel {
+ _I2C12_SEL,
+ _I2C35_SEL,
+ _STGEN_SEL,
_I2C46_SEL,
+ _SPI6_SEL,
+ _USART1_SEL,
+ _RNG1_SEL,
_UART6_SEL,
_UART24_SEL,
_UART35_SEL,
@@ -80,9 +101,10 @@ enum stm32mp1_parent_sel {
_SDMMC3_SEL,
_QSPI_SEL,
_FMC_SEL,
+ _ASS_SEL,
+ _MSS_SEL,
_USBPHY_SEL,
_USBO_SEL,
- _STGEN_SEL,
_PARENT_SEL_NB,
_UNKNOWN_SEL = 0xff,
};
@@ -105,6 +127,7 @@ enum stm32mp1_div_id {
enum stm32mp1_clksrc_id {
CLKSRC_MPU,
CLKSRC_AXI,
+ CLKSRC_MCU,
CLKSRC_PLL12,
CLKSRC_PLL3,
CLKSRC_PLL4,
@@ -117,6 +140,7 @@ enum stm32mp1_clksrc_id {
enum stm32mp1_clkdiv_id {
CLKDIV_MPU,
CLKDIV_AXI,
+ CLKDIV_MCU,
CLKDIV_APB1,
CLKDIV_APB2,
CLKDIV_APB3,
@@ -162,9 +186,8 @@ struct stm32mp1_clk_gate {
uint8_t bit;
uint8_t index;
uint8_t set_clr;
- enum stm32mp1_parent_sel sel;
- enum stm32mp1_parent_id fixed;
- bool secure;
+ uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
+ uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
};
struct stm32mp1_clk_sel {
@@ -187,21 +210,34 @@ struct stm32mp1_clk_pll {
enum stm32mp_osc_id refclk[REFCLK_SIZE];
};
-struct stm32mp1_clk_data {
- const struct stm32mp1_clk_gate *gate;
- const struct stm32mp1_clk_sel *sel;
- const struct stm32mp1_clk_pll *pll;
- const int nb_gate;
+#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_priv {
- uint32_t base;
- const struct stm32mp1_clk_data *data;
- unsigned long osc[NB_OSC];
- uint32_t pkcs_usb_value;
+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];
};
-#define STM32MP1_CLK(off, b, idx, s) \
+/* 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) \
{ \
.offset = (off), \
.bit = (b), \
@@ -209,10 +245,10 @@ struct stm32mp1_clk_priv {
.set_clr = 0, \
.sel = (s), \
.fixed = _UNKNOWN_ID, \
- .secure = 0, \
}
-#define STM32MP1_CLK_F(off, b, idx, f) \
+/* Clocks with fixed source and non set/clr register access */
+#define _CLK_FIXED(off, b, idx, f) \
{ \
.offset = (off), \
.bit = (b), \
@@ -220,10 +256,10 @@ struct stm32mp1_clk_priv {
.set_clr = 0, \
.sel = _UNKNOWN_SEL, \
.fixed = (f), \
- .secure = 0, \
}
-#define STM32MP1_CLK_SET_CLR(off, b, idx, s) \
+/* Clocks with selectable source and set/clr register access */
+#define _CLK_SC_SELEC(off, b, idx, s) \
{ \
.offset = (off), \
.bit = (b), \
@@ -231,10 +267,10 @@ struct stm32mp1_clk_priv {
.set_clr = 1, \
.sel = (s), \
.fixed = _UNKNOWN_ID, \
- .secure = 0, \
}
-#define STM32MP1_CLK_SET_CLR_F(off, b, idx, f) \
+/* Clocks with fixed source and set/clr register access */
+#define _CLK_SC_FIXED(off, b, idx, f) \
{ \
.offset = (off), \
.bit = (b), \
@@ -242,32 +278,20 @@ struct stm32mp1_clk_priv {
.set_clr = 1, \
.sel = _UNKNOWN_SEL, \
.fixed = (f), \
- .secure = 0, \
- }
-
-#define STM32MP1_CLK_SEC_SET_CLR(off, b, idx, s) \
- { \
- .offset = (off), \
- .bit = (b), \
- .index = (idx), \
- .set_clr = 1, \
- .sel = (s), \
- .fixed = _UNKNOWN_ID, \
- .secure = 1, \
}
-#define STM32MP1_CLK_PARENT(idx, off, s, m, p) \
+#define _CLK_PARENT(idx, off, s, m, p) \
[(idx)] = { \
.offset = (off), \
.src = (s), \
.msk = (m), \
.parent = (p), \
- .nb_parent = ARRAY_SIZE((p)) \
+ .nb_parent = ARRAY_SIZE(p) \
}
-#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, \
- off4, off5, off6, \
- p1, p2, p3, p4) \
+#define _CLK_PLL(idx, type, off1, off2, off3, \
+ off4, off5, off6, \
+ p1, p2, p3, p4) \
[(idx)] = { \
.plltype = (type), \
.rckxselr = (off1), \
@@ -283,113 +307,180 @@ struct stm32mp1_clk_priv {
}
static const uint8_t stm32mp1_clks[][2] = {
- {CK_PER, _CK_PER},
- {CK_MPU, _CK_MPU},
- {CK_AXI, _ACLK},
- {CK_HSE, _HSE},
- {CK_CSI, _CSI},
- {CK_LSI, _LSI},
- {CK_LSE, _LSE},
- {CK_HSI, _HSI},
- {CK_HSE_DIV2, _HSE_KER_DIV2},
+ { CK_PER, _CK_PER },
+ { CK_MPU, _CK_MPU },
+ { CK_AXI, _ACLK },
+ { CK_MCU, _CK_MCU },
+ { CK_HSE, _HSE },
+ { CK_CSI, _CSI },
+ { CK_LSI, _LSI },
+ { CK_LSE, _LSE },
+ { CK_HSI, _HSI },
+ { CK_HSE_DIV2, _HSE_KER_DIV2 },
};
+#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate)
+
static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
- STM32MP1_CLK(RCC_DDRITFCR, 0, DDRC1, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 1, DDRC1LP, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 2, DDRC2, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 3, DDRC2LP, _UNKNOWN_SEL),
- STM32MP1_CLK_F(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
- STM32MP1_CLK(RCC_DDRITFCR, 5, DDRPHYCLP, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 6, DDRCAPB, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 7, DDRCAPBLP, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 8, AXIDCG, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 9, DDRPHYCAPB, _UNKNOWN_SEL),
- STM32MP1_CLK(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _UNKNOWN_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
-
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 11, TZC1, _UNKNOWN_SEL),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 12, TZC2, _UNKNOWN_SEL),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
-
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 5, HASH1, _UNKNOWN_SEL),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 6, RNG1_K, _CSI_KER),
- STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _UNKNOWN_SEL),
-
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
-
- STM32MP1_CLK(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
+ _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
+ _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
+ _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
+ _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
+ _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
+ _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
+ _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
+ _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
+ _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
+ _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
+ _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
+ _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
+ _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
+ _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
+ _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_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),
+
+ _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_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),
+ _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
+ _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
+ _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, 8, USBO_K, _USBO_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
+
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
+
+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
+ _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
+ _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, 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),
+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
+ _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
+
+ _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
+};
+
+static const uint8_t i2c12_parents[] = {
+ _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
+};
+
+static const uint8_t i2c35_parents[] = {
+ _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
+};
+
+static const uint8_t stgen_parents[] = {
+ _HSI_KER, _HSE_KER
+};
+
+static const uint8_t i2c46_parents[] = {
+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
+};
+
+static const uint8_t spi6_parents[] = {
+ _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
+};
+
+static const uint8_t usart1_parents[] = {
+ _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
+};
+
+static const uint8_t rng1_parents[] = {
+ _CSI, _PLL4_R, _LSE, _LSI
+};
+
+static const uint8_t uart6_parents[] = {
+ _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
};
-static const uint8_t i2c46_parents[] = {_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER};
-static const uint8_t uart6_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER,
- _HSE_KER};
-static const uint8_t uart24_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
- _HSE_KER};
-static const uint8_t uart35_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
- _HSE_KER};
-static const uint8_t uart78_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
- _HSE_KER};
-static const uint8_t sdmmc12_parents[] = {_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER};
-static const uint8_t sdmmc3_parents[] = {_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER};
-static const uint8_t qspi_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER};
-static const uint8_t fmc_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER};
-static const uint8_t usbphy_parents[] = {_HSE_KER, _PLL4_R, _HSE_KER_DIV2};
-static const uint8_t usbo_parents[] = {_PLL4_R, _USB_PHY_48};
-static const uint8_t stgen_parents[] = {_HSI_KER, _HSE_KER};
+static const uint8_t uart234578_parents[] = {
+ _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
+};
+
+static const uint8_t sdmmc12_parents[] = {
+ _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
+};
+
+static const uint8_t sdmmc3_parents[] = {
+ _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
+};
+
+static const uint8_t qspi_parents[] = {
+ _ACLK, _PLL3_R, _PLL4_P, _CK_PER
+};
+
+static const uint8_t fmc_parents[] = {
+ _ACLK, _PLL3_R, _PLL4_P, _CK_PER
+};
+
+static const uint8_t ass_parents[] = {
+ _HSI, _HSE, _PLL2
+};
+
+static const uint8_t mss_parents[] = {
+ _HSI, _HSE, _CSI, _PLL3
+};
+
+static const uint8_t usbphy_parents[] = {
+ _HSE_KER, _PLL4_R, _HSE_KER_DIV2
+};
+
+static const uint8_t usbo_parents[] = {
+ _PLL4_R, _USB_PHY_48
+};
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
- STM32MP1_CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents),
- STM32MP1_CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents),
- STM32MP1_CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7,
- uart24_parents),
- STM32MP1_CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7,
- uart35_parents),
- STM32MP1_CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7,
- uart78_parents),
- STM32MP1_CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7,
- sdmmc12_parents),
- STM32MP1_CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7,
- sdmmc3_parents),
- STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents),
- STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents),
- STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents),
- STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents),
- STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
+ _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),
};
/* Define characteristic of PLL according type */
@@ -411,29 +502,33 @@ static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
static const uint8_t pllncfgr2[_DIV_NB] = {
[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
- [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT
+ [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
};
static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
- STM32MP1_CLK_PLL(_PLL1, PLL_1600,
- RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
- RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
- STM32MP1_CLK_PLL(_PLL2, PLL_1600,
- RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
- RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
- _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
- STM32MP1_CLK_PLL(_PLL3, PLL_800,
- RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
- RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
- _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
- STM32MP1_CLK_PLL(_PLL4, PLL_800,
- RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
- RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
- _HSI, _HSE, _CSI, _I2S_CKIN),
+ _CLK_PLL(_PLL1, PLL_1600,
+ RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
+ RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+ _CLK_PLL(_PLL2, PLL_1600,
+ RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
+ RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
+ _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+ _CLK_PLL(_PLL3, PLL_800,
+ RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
+ RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
+ _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
+ _CLK_PLL(_PLL4, PLL_800,
+ RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
+ RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
+ _HSI, _HSE, _CSI, _I2S_CKIN),
};
/* Prescaler table lookups for clock computation */
+/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
+static const uint8_t stm32mp1_mcu_div[16] = {
+ 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
+};
/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
@@ -447,33 +542,210 @@ static const uint8_t stm32mp1_axi_div[8] = {
1, 2, 3, 4, 4, 4, 4, 4
};
-static const struct stm32mp1_clk_data stm32mp1_data = {
- .gate = stm32mp1_clk_gate,
- .sel = stm32mp1_clk_sel,
- .pll = stm32mp1_clk_pll,
- .nb_gate = ARRAY_SIZE(stm32mp1_clk_gate),
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
+ [_HSI] = "HSI",
+ [_HSE] = "HSE",
+ [_CSI] = "CSI",
+ [_LSI] = "LSI",
+ [_LSE] = "LSE",
+ [_I2S_CKIN] = "I2S_CKIN",
+ [_HSI_KER] = "HSI_KER",
+ [_HSE_KER] = "HSE_KER",
+ [_HSE_KER_DIV2] = "HSE_KER_DIV2",
+ [_CSI_KER] = "CSI_KER",
+ [_PLL1_P] = "PLL1_P",
+ [_PLL1_Q] = "PLL1_Q",
+ [_PLL1_R] = "PLL1_R",
+ [_PLL2_P] = "PLL2_P",
+ [_PLL2_Q] = "PLL2_Q",
+ [_PLL2_R] = "PLL2_R",
+ [_PLL3_P] = "PLL3_P",
+ [_PLL3_Q] = "PLL3_Q",
+ [_PLL3_R] = "PLL3_R",
+ [_PLL4_P] = "PLL4_P",
+ [_PLL4_Q] = "PLL4_Q",
+ [_PLL4_R] = "PLL4_R",
+ [_ACLK] = "ACLK",
+ [_PCLK1] = "PCLK1",
+ [_PCLK2] = "PCLK2",
+ [_PCLK3] = "PCLK3",
+ [_PCLK4] = "PCLK4",
+ [_PCLK5] = "PCLK5",
+ [_HCLK6] = "KCLK6",
+ [_HCLK2] = "HCLK2",
+ [_CK_PER] = "CK_PER",
+ [_CK_MPU] = "CK_MPU",
+ [_CK_MCU] = "CK_MCU",
+ [_USB_PHY_48] = "USB_PHY_48",
+};
+
+static const char *
+const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] __unused = {
+ [_I2C12_SEL] = "I2C12",
+ [_I2C35_SEL] = "I2C35",
+ [_STGEN_SEL] = "STGEN",
+ [_I2C46_SEL] = "I2C46",
+ [_SPI6_SEL] = "SPI6",
+ [_USART1_SEL] = "USART1",
+ [_RNG1_SEL] = "RNG1",
+ [_UART6_SEL] = "UART6",
+ [_UART24_SEL] = "UART24",
+ [_UART35_SEL] = "UART35",
+ [_UART78_SEL] = "UART78",
+ [_SDMMC12_SEL] = "SDMMC12",
+ [_SDMMC3_SEL] = "SDMMC3",
+ [_QSPI_SEL] = "QSPI",
+ [_FMC_SEL] = "FMC",
+ [_ASS_SEL] = "ASS",
+ [_MSS_SEL] = "MSS",
+ [_USBPHY_SEL] = "USBPHY",
+ [_USBO_SEL] = "USBO",
+};
+#endif
+
+/* RCC clock device driver private */
+static unsigned long stm32mp1_osc[NB_OSC];
+static struct spinlock reg_lock;
+static unsigned int gate_refcounts[NB_GATES];
+static struct spinlock refcount_lock;
+
+static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
+{
+ return &stm32mp1_clk_gate[idx];
+}
+
+static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
+{
+ return &stm32mp1_clk_sel[idx];
+}
+
+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 struct stm32mp1_clk_priv stm32mp1_clk_priv_data;
+static uint32_t timer_val;
+#endif
+
+static int stm32mp1_lock_available(void)
+{
+ /* The spinlocks are used only when MMU is enabled */
+ return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT);
+}
+
+static void stm32mp1_clk_lock(struct spinlock *lock)
+{
+ if (stm32mp1_lock_available() == 0U) {
+ return;
+ }
+
+ /* Assume interrupts are masked */
+ spin_lock(lock);
+}
+
+static void stm32mp1_clk_unlock(struct spinlock *lock)
+{
+ if (stm32mp1_lock_available() == 0U) {
+ return;
+ }
+
+ spin_unlock(lock);
+}
+
+bool stm32mp1_rcc_is_secure(void)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
+}
+
+bool stm32mp1_rcc_is_mckprot(void)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0;
+}
+
+void stm32mp1_clk_rcc_regs_lock(void)
+{
+ stm32mp1_clk_lock(&reg_lock);
+}
+
+void stm32mp1_clk_rcc_regs_unlock(void)
+{
+ stm32mp1_clk_unlock(&reg_lock);
+}
+
+static unsigned int get_id_from_rcc_bit(unsigned int offset, unsigned int bit)
+{
+ unsigned int idx;
+
+ for (idx = 0U; idx < NB_GATES; idx++) {
+ const struct stm32mp1_clk_gate *gate = gate_ref(idx);
-static unsigned long stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv,
- enum stm32mp_osc_id idx)
+ if ((offset == gate->offset) && (bit == gate->bit)) {
+ return gate->index;
+ }
+
+ if ((gate->set_clr != 0U) &&
+ (offset == (gate->offset + RCC_MP_ENCLRR_OFFSET)) &&
+ (bit == gate->bit)) {
+ return gate->index;
+ }
+ }
+
+ /* Currently only supported gated clocks */
+ return ~0U;
+}
+
+static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
{
if (idx >= NB_OSC) {
return 0;
}
- return priv->osc[idx];
+ return stm32mp1_osc[idx];
}
-static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id)
+static int stm32mp1_clk_get_gated_id(unsigned long id)
{
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
- int i;
- int nb_clks = priv->data->nb_gate;
+ unsigned int i;
- for (i = 0; i < nb_clks; i++) {
- if (gate[i].index == id) {
+ for (i = 0U; i < NB_GATES; i++) {
+ if (gate_ref(i)->index == id) {
return i;
}
}
@@ -483,77 +755,70 @@ static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id)
return -EINVAL;
}
-static enum stm32mp1_parent_sel
-stm32mp1_clk_get_sel(struct stm32mp1_clk_priv *priv, int i)
+static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
{
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
-
- return gate[i].sel;
+ return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
}
-static enum stm32mp1_parent_id
-stm32mp1_clk_get_fixed_parent(struct stm32mp1_clk_priv *priv, int i)
+static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
{
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
-
- return gate[i].fixed;
+ return (enum stm32mp1_parent_id)gate_ref(i)->fixed;
}
-static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv,
- unsigned long id)
+static int stm32mp1_clk_get_parent(unsigned long id)
{
- const struct stm32mp1_clk_sel *sel = priv->data->sel;
+ const struct stm32mp1_clk_sel *sel;
uint32_t j, p_sel;
int i;
enum stm32mp1_parent_id p;
enum stm32mp1_parent_sel s;
+ uintptr_t rcc_base = stm32mp_rcc_base();
- for (j = 0; j < ARRAY_SIZE(stm32mp1_clks); j++) {
+ for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) {
if (stm32mp1_clks[j][0] == id) {
return (int)stm32mp1_clks[j][1];
}
}
- i = stm32mp1_clk_get_id(priv, id);
+ i = stm32mp1_clk_get_gated_id(id);
if (i < 0) {
- return i;
+ panic();
}
- p = stm32mp1_clk_get_fixed_parent(priv, i);
+ p = stm32mp1_clk_get_fixed_parent(i);
if (p < _PARENT_NB) {
return (int)p;
}
- s = stm32mp1_clk_get_sel(priv, i);
- if (s >= _PARENT_SEL_NB) {
+ s = stm32mp1_clk_get_sel(i);
+ if (s == _UNKNOWN_SEL) {
return -EINVAL;
}
-
- p_sel = (mmio_read_32(priv->base + sel[s].offset) >> sel[s].src) &
- sel[s].msk;
-
- if (p_sel < sel[s].nb_parent) {
- return (int)sel[s].parent[p_sel];
+ if (s >= _PARENT_SEL_NB) {
+ panic();
}
- ERROR("%s: no parents defined for clk id %ld\n", __func__, id);
+ sel = clk_sel_ref(s);
+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk;
+ 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",
+ __func__,
+ stm32mp1_clk_parent_name[sel->parent[p_sel]],
+ stm32mp1_clk_parent_sel_name[s], id);
+#endif
+ return (int)sel->parent[p_sel];
+ }
return -EINVAL;
}
-static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id)
+static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
- uint32_t selr, src;
- unsigned long refclk;
-
- selr = mmio_read_32(priv->base + pll[pll_id].rckxselr);
- src = selr & RCC_SELR_REFCLK_SRC_MASK;
+ uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
+ uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
- refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]);
-
- return refclk;
+ return stm32mp1_clk_get_fixed(pll->refclk[src]);
}
/*
@@ -562,20 +827,19 @@ static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv,
* - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1)
* => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
*/
-static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id)
+static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
unsigned long refclk, fvco;
uint32_t cfgr1, fracr, divm, divn;
+ uintptr_t rcc_base = stm32mp_rcc_base();
- cfgr1 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr1);
- fracr = mmio_read_32(priv->base + pll[pll_id].pllxfracr);
+ cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
+ fracr = mmio_read_32(rcc_base + pll->pllxfracr);
divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
- refclk = stm32mp1_pll_get_fref_ck(priv, pll_id);
+ refclk = stm32mp1_pll_get_fref(pll);
/*
* With FRACV :
@@ -584,13 +848,13 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv,
* Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
*/
if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
- uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK)
- >> RCC_PLLNFRACR_FRACV_SHIFT;
+ uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
+ RCC_PLLNFRACR_FRACV_SHIFT;
unsigned long long numerator, denominator;
- numerator = ((unsigned long long)divn + 1U) << 13;
- numerator = (refclk * numerator) + fracv;
- denominator = ((unsigned long long)divm + 1U) << 13;
+ numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
+ numerator = refclk * numerator;
+ denominator = ((unsigned long long)divm + 1U) << 13;
fvco = (unsigned long)(numerator / denominator);
} else {
fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
@@ -599,11 +863,10 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv,
return fvco;
}
-static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id,
+static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
enum stm32mp1_div_id div_id)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
unsigned long dfout;
uint32_t cfgr2, divy;
@@ -611,42 +874,43 @@ static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv,
return 0;
}
- cfgr2 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr2);
+ cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
- dfout = stm32mp1_pll_get_fvco(priv, pll_id) / (divy + 1U);
+ dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
+
return dfout;
}
-static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
+static unsigned long get_clock_rate(int p)
{
uint32_t reg, clkdiv;
unsigned long clock = 0;
+ uintptr_t rcc_base = stm32mp_rcc_base();
switch (p) {
case _CK_MPU:
/* MPU sub system */
- reg = mmio_read_32(priv->base + RCC_MPCKSELR);
+ reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_MPCKSELR_HSI:
- clock = stm32mp1_clk_get_fixed(priv, _HSI);
+ clock = stm32mp1_clk_get_fixed(_HSI);
break;
case RCC_MPCKSELR_HSE:
- clock = stm32mp1_clk_get_fixed(priv, _HSE);
+ clock = stm32mp1_clk_get_fixed(_HSE);
break;
case RCC_MPCKSELR_PLL:
- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
break;
case RCC_MPCKSELR_PLL_MPUDIV:
- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
- reg = mmio_read_32(priv->base + RCC_MPCKDIVR);
+ reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
clkdiv = reg & RCC_MPUDIV_MASK;
if (clkdiv != 0U) {
clock /= stm32mp1_mpu_div[clkdiv];
}
-
break;
default:
break;
@@ -658,49 +922,94 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
case _HCLK6:
case _PCLK4:
case _PCLK5:
- reg = mmio_read_32(priv->base + RCC_ASSCKSELR);
+ reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_ASSCKSELR_HSI:
- clock = stm32mp1_clk_get_fixed(priv, _HSI);
+ clock = stm32mp1_clk_get_fixed(_HSI);
break;
case RCC_ASSCKSELR_HSE:
- clock = stm32mp1_clk_get_fixed(priv, _HSE);
+ clock = stm32mp1_clk_get_fixed(_HSE);
break;
case RCC_ASSCKSELR_PLL:
- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
break;
default:
break;
}
/* System clock divider */
- reg = mmio_read_32(priv->base + RCC_AXIDIVR);
+ reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
switch (p) {
case _PCLK4:
- reg = mmio_read_32(priv->base + RCC_APB4DIVR);
+ reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
break;
case _PCLK5:
- reg = mmio_read_32(priv->base + RCC_APB5DIVR);
+ reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
+ break;
+ default:
+ break;
+ }
+ break;
+ /* MCU sub system */
+ case _CK_MCU:
+ case _PCLK1:
+ case _PCLK2:
+ case _PCLK3:
+ reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
+ switch (reg & RCC_SELR_SRC_MASK) {
+ case RCC_MSSCKSELR_HSI:
+ clock = stm32mp1_clk_get_fixed(_HSI);
+ break;
+ case RCC_MSSCKSELR_HSE:
+ clock = stm32mp1_clk_get_fixed(_HSE);
+ break;
+ case RCC_MSSCKSELR_CSI:
+ clock = stm32mp1_clk_get_fixed(_CSI);
+ break;
+ case RCC_MSSCKSELR_PLL:
+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
+ break;
+ default:
+ break;
+ }
+
+ /* MCU clock divider */
+ reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
+ clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
+
+ switch (p) {
+ case _PCLK1:
+ reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
break;
+ case _PCLK2:
+ reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
+ break;
+ case _PCLK3:
+ reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
+ clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
+ break;
+ case _CK_MCU:
default:
break;
}
break;
case _CK_PER:
- reg = mmio_read_32(priv->base + RCC_CPERCKSELR);
+ reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
switch (reg & RCC_SELR_SRC_MASK) {
case RCC_CPERCKSELR_HSI:
- clock = stm32mp1_clk_get_fixed(priv, _HSI);
+ clock = stm32mp1_clk_get_fixed(_HSI);
break;
case RCC_CPERCKSELR_HSE:
- clock = stm32mp1_clk_get_fixed(priv, _HSE);
+ clock = stm32mp1_clk_get_fixed(_HSE);
break;
case RCC_CPERCKSELR_CSI:
- clock = stm32mp1_clk_get_fixed(priv, _CSI);
+ clock = stm32mp1_clk_get_fixed(_CSI);
break;
default:
break;
@@ -708,65 +1017,65 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
break;
case _HSI:
case _HSI_KER:
- clock = stm32mp1_clk_get_fixed(priv, _HSI);
+ clock = stm32mp1_clk_get_fixed(_HSI);
break;
case _CSI:
case _CSI_KER:
- clock = stm32mp1_clk_get_fixed(priv, _CSI);
+ clock = stm32mp1_clk_get_fixed(_CSI);
break;
case _HSE:
case _HSE_KER:
- clock = stm32mp1_clk_get_fixed(priv, _HSE);
+ clock = stm32mp1_clk_get_fixed(_HSE);
break;
case _HSE_KER_DIV2:
- clock = stm32mp1_clk_get_fixed(priv, _HSE) >> 1;
+ clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
break;
case _LSI:
- clock = stm32mp1_clk_get_fixed(priv, _LSI);
+ clock = stm32mp1_clk_get_fixed(_LSI);
break;
case _LSE:
- clock = stm32mp1_clk_get_fixed(priv, _LSE);
+ clock = stm32mp1_clk_get_fixed(_LSE);
break;
/* PLL */
case _PLL1_P:
- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
break;
case _PLL1_Q:
- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_Q);
+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
break;
case _PLL1_R:
- clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_R);
+ clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
break;
case _PLL2_P:
- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
break;
case _PLL2_Q:
- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_Q);
+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
break;
case _PLL2_R:
- clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_R);
+ clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
break;
case _PLL3_P:
- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
break;
case _PLL3_Q:
- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_Q);
+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
break;
case _PLL3_R:
- clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_R);
+ clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
break;
case _PLL4_P:
- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_P);
+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
break;
case _PLL4_Q:
- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_Q);
+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
break;
case _PLL4_R:
- clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_R);
+ clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
break;
/* Other */
case _USB_PHY_48:
- clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48);
+ clock = USB_PHY_48_MHZ;
break;
default:
break;
@@ -775,112 +1084,155 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
return clock;
}
-bool stm32mp1_clk_is_enabled(unsigned long id)
+static void __clk_enable(struct stm32mp1_clk_gate const *gate)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (gate->set_clr != 0U) {
+ mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
+ } else {
+ stm32mp_mmio_setbits_32_shregs(rcc_base + gate->offset,
+ BIT(gate->bit));
+ }
+
+ VERBOSE("Clock %d has been enabled", gate->index);
+}
+
+static void __clk_disable(struct stm32mp1_clk_gate const *gate)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (gate->set_clr != 0U) {
+ mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
+ BIT(gate->bit));
+ } else {
+ stm32mp_mmio_clrbits_32_shregs(rcc_base + gate->offset,
+ BIT(gate->bit));
+ }
+
+ VERBOSE("Clock %d has been disabled", gate->index);
+}
+
+static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
+}
+
+unsigned int stm32mp1_clk_get_refcount(unsigned long id)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
- int i = stm32mp1_clk_get_id(priv, id);
+ int i = stm32mp1_clk_get_gated_id(id);
if (i < 0) {
- return false;
+ panic();
}
- return ((mmio_read_32(priv->base + gate[i].offset) &
- BIT(gate[i].bit)) != 0U);
+ return gate_refcounts[i];
}
-int stm32mp1_clk_enable(unsigned long id)
+void __stm32mp1_clk_enable(unsigned long id, bool secure)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
- int i = stm32mp1_clk_get_id(priv, id);
+ const struct stm32mp1_clk_gate *gate;
+ int i = stm32mp1_clk_get_gated_id(id);
+ unsigned int *refcnt;
if (i < 0) {
- return i;
+ ERROR("Clock %d can't be enabled\n", (uint32_t)id);
+ panic();
}
- if (gate[i].set_clr != 0U) {
- mmio_write_32(priv->base + gate[i].offset, BIT(gate[i].bit));
- } else {
- mmio_setbits_32(priv->base + gate[i].offset, BIT(gate[i].bit));
+ gate = gate_ref(i);
+ refcnt = &gate_refcounts[i];
+
+ stm32mp1_clk_lock(&refcount_lock);
+
+ if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
+ __clk_enable(gate);
}
- return 0;
+ stm32mp1_clk_unlock(&refcount_lock);
}
-int stm32mp1_clk_disable(unsigned long id)
+void __stm32mp1_clk_disable(unsigned long id, bool secure)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
- const struct stm32mp1_clk_gate *gate = priv->data->gate;
- int i = stm32mp1_clk_get_id(priv, id);
+ const struct stm32mp1_clk_gate *gate;
+ int i = stm32mp1_clk_get_gated_id(id);
+ unsigned int *refcnt;
if (i < 0) {
- return i;
+ ERROR("Clock %d can't be disabled\n", (uint32_t)id);
+ panic();
}
- if (gate[i].set_clr != 0U) {
- mmio_write_32(priv->base + gate[i].offset
- + RCC_MP_ENCLRR_OFFSET,
- BIT(gate[i].bit));
- } else {
- mmio_clrbits_32(priv->base + gate[i].offset, BIT(gate[i].bit));
+ gate = gate_ref(i);
+ refcnt = &gate_refcounts[i];
+
+ stm32mp1_clk_lock(&refcount_lock);
+
+ if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
+ __clk_disable(gate);
}
- return 0;
+ stm32mp1_clk_unlock(&refcount_lock);
}
-unsigned long stm32mp1_clk_get_rate(unsigned long id)
+bool stm32mp1_clk_is_enabled(unsigned long id)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
- int p = stm32mp1_clk_get_parent(priv, id);
- unsigned long rate;
+ int i = stm32mp1_clk_get_gated_id(id);
+
+ if (i < 0) {
+ panic();
+ }
+
+ return __clk_is_enabled(gate_ref(i));
+}
+
+unsigned long stm32mp_clk_get_rate(unsigned long id)
+{
+ int p = stm32mp1_clk_get_parent(id);
if (p < 0) {
return 0;
}
- rate = stm32mp1_clk_get(priv, p);
-
- return rate;
+ return get_clock_rate(p);
}
-static void stm32mp1_ls_osc_set(int enable, uint32_t rcc, uint32_t offset,
- uint32_t mask_on)
+static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
{
- uint32_t address = rcc + offset;
+ uint32_t address = stm32mp_rcc_base() + offset;
- if (enable != 0) {
+ if (enable) {
mmio_setbits_32(address, mask_on);
} else {
mmio_clrbits_32(address, mask_on);
}
}
-static void stm32mp1_hs_ocs_set(int enable, uint32_t rcc, uint32_t mask_on)
+static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
{
- if (enable != 0) {
- mmio_setbits_32(rcc + RCC_OCENSETR, mask_on);
- } else {
- mmio_setbits_32(rcc + RCC_OCENCLRR, mask_on);
- }
+ uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
+ uint32_t address = stm32mp_rcc_base() + offset;
+
+ mmio_write_32(address, mask_on);
}
-static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset,
- uint32_t mask_rdy)
+static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
{
- unsigned long start;
+ uint64_t start;
uint32_t mask_test;
- uint32_t address = rcc + offset;
+ uint32_t address = stm32mp_rcc_base() + offset;
- if (enable != 0) {
+ if (enable) {
mask_test = mask_rdy;
} else {
mask_test = 0;
}
- start = get_timer(0);
+ start = timeout_start();
while ((mmio_read_32(address) & mask_rdy) != mask_test) {
- if (get_timer(start) > OSCRDY_TIMEOUT) {
+ if (timeout_elapsed(start, OSCRDY_TIMEOUT)) {
ERROR("OSC %x @ %x timeout for enable=%d : 0x%x\n",
mask_rdy, address, enable, mmio_read_32(address));
return -ETIMEDOUT;
@@ -890,19 +1242,24 @@ static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset,
return 0;
}
-static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv)
+static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
{
uint32_t value;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (digbyp) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
+ }
- if (bypass) {
- mmio_setbits_32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP);
+ if (bypass || digbyp) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
}
/*
* Warning: not recommended to switch directly from "high drive"
* to "medium low drive", and vice-versa.
*/
- value = (mmio_read_32(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
+ value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
RCC_BDCR_LSEDRV_SHIFT;
while (value != lsedrv) {
@@ -912,77 +1269,85 @@ static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv)
value++;
}
- mmio_clrsetbits_32(rcc + RCC_BDCR,
+ mmio_clrsetbits_32(rcc_base + RCC_BDCR,
RCC_BDCR_LSEDRV_MASK,
value << RCC_BDCR_LSEDRV_SHIFT);
}
- stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON);
+ stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
}
-static void stm32mp1_lse_wait(uint32_t rcc)
+static void stm32mp1_lse_wait(void)
{
- if (stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
+ if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
VERBOSE("%s: failed\n", __func__);
}
}
-static void stm32mp1_lsi_set(uint32_t rcc, int enable)
+static void stm32mp1_lsi_set(bool enable)
{
- stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION);
- if (stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) !=
+ stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
+
+ if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) !=
0) {
VERBOSE("%s: failed\n", __func__);
}
}
-static void stm32mp1_hse_enable(uint32_t rcc, bool bypass, bool css)
+static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
{
- if (bypass) {
- mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP);
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (digbyp) {
+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
+ }
+
+ if (bypass || digbyp) {
+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
}
- stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON);
- if (stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY) !=
+ stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
+ if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) !=
0) {
VERBOSE("%s: failed\n", __func__);
}
if (css) {
- mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON);
+ mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
}
}
-static void stm32mp1_csi_set(uint32_t rcc, int enable)
+static void stm32mp1_csi_set(bool enable)
{
- stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION);
- if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) !=
+ stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
+ if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) !=
0) {
VERBOSE("%s: failed\n", __func__);
}
}
-static void stm32mp1_hsi_set(uint32_t rcc, int enable)
+static void stm32mp1_hsi_set(bool enable)
{
- stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION);
- if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) !=
+ stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
+ if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) !=
0) {
VERBOSE("%s: failed\n", __func__);
}
}
-static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv)
+static int stm32mp1_set_hsidiv(uint8_t hsidiv)
{
- unsigned long start;
- uint32_t address = rcc + RCC_OCRDYR;
+ uint64_t start;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+ uint32_t address = rcc_base + RCC_OCRDYR;
- mmio_clrsetbits_32(rcc + RCC_HSICFGR,
+ mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
RCC_HSICFGR_HSIDIV_MASK,
RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
- start = get_timer(0);
+ start = timeout_start();
while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
- if (get_timer(start) > HSIDIV_TIMEOUT) {
+ if (timeout_elapsed(start, HSIDIV_TIMEOUT)) {
ERROR("HSIDIV failed @ 0x%x: 0x%x\n",
address, mmio_read_32(address));
return -ETIMEDOUT;
@@ -992,7 +1357,7 @@ static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv)
return 0;
}
-static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq)
+static int stm32mp1_hsidiv(unsigned long hsifreq)
{
uint8_t hsidiv;
uint32_t hsidivfreq = MAX_HSI_HZ;
@@ -1011,31 +1376,103 @@ static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq)
}
if (hsidiv != 0U) {
- return stm32mp1_set_hsidiv(rcc, hsidiv);
+ return stm32mp1_set_hsidiv(hsidiv);
}
return 0;
}
-static void stm32mp1_pll_start(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id)
+static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
+ unsigned int clksrc,
+ uint32_t *pllcfg, int plloff)
+{
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uintptr_t rcc_base = stm32mp_rcc_base();
+ uint32_t pllxcr = rcc_base + pll->pllxcr;
+ enum stm32mp1_plltype type = pll->plltype;
+ uint32_t address = rcc_base + (clksrc >> 4);
+ unsigned long refclk;
+ uint32_t ifrge = 0U;
+ uint32_t src, value, fracv;
+
+ /* Check PLL output */
+ if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
+ return false;
+ }
+
+ /* Check current clksrc */
+ src = mmio_read_32(address) & RCC_SELR_SRC_MASK;
+ if (src != (clksrc & RCC_SELR_SRC_MASK)) {
+ return false;
+ }
+
+ /* Check Div */
+ src = mmio_read_32(rcc_base + pll->rckxselr) &
+ RCC_SELR_REFCLK_SRC_MASK;
+
+ refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
+ (pllcfg[PLLCFG_M] + 1U);
+
+ if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
+ (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
+ return false;
+ }
+
+ if ((type == PLL_800) && (refclk >= 8000000U)) {
+ ifrge = 1U;
+ }
+
+ value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
+ RCC_PLLNCFGR1_DIVN_MASK;
+ value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
+ RCC_PLLNCFGR1_DIVM_MASK;
+ value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
+ RCC_PLLNCFGR1_IFRGE_MASK;
+ if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
+ return false;
+ }
+
+ /* Fractional configuration */
+ fracv = fdt_read_uint32_default(plloff, "frac", 0);
+
+ value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
+ value |= RCC_PLLNFRACR_FRACLE;
+ if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
+ return false;
+ }
+
+ /* Output config */
+ value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
+ RCC_PLLNCFGR2_DIVP_MASK;
+ value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
+ RCC_PLLNCFGR2_DIVQ_MASK;
+ value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
+ RCC_PLLNCFGR2_DIVR_MASK;
+ if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
+ return false;
+ }
+
+ return true;
+}
+
+static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
- mmio_write_32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_PLLON);
+ mmio_write_32(pllxcr, RCC_PLLNCR_PLLON);
}
-static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id, uint32_t output)
+static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
- uint32_t pllxcr = priv->base + pll[pll_id].pllxcr;
- unsigned long start;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
+ uint64_t start;
- start = get_timer(0);
+ start = timeout_start();
/* Wait PLL lock */
while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
- if (get_timer(start) > PLLRDY_TIMEOUT) {
+ if (timeout_elapsed(start, PLLRDY_TIMEOUT)) {
ERROR("PLL%d start failed @ 0x%x: 0x%x\n",
pll_id, pllxcr, mmio_read_32(pllxcr));
return -ETIMEDOUT;
@@ -1048,12 +1485,11 @@ static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv,
return 0;
}
-static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id)
+static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
- uint32_t pllxcr = priv->base + pll[pll_id].pllxcr;
- unsigned long start;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uint32_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
+ uint64_t start;
/* Stop all output */
mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
@@ -1062,10 +1498,10 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv,
/* Stop PLL */
mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
- start = get_timer(0);
+ start = timeout_start();
/* Wait PLL stopped */
while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
- if (get_timer(start) > PLLRDY_TIMEOUT) {
+ if (timeout_elapsed(start, PLLRDY_TIMEOUT)) {
ERROR("PLL%d stop failed @ 0x%x: 0x%x\n",
pll_id, pllxcr, mmio_read_32(pllxcr));
return -ETIMEDOUT;
@@ -1075,12 +1511,11 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv,
return 0;
}
-static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id,
+static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
uint32_t *pllcfg)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
- uint32_t rcc = priv->base;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uintptr_t rcc_base = stm32mp_rcc_base();
uint32_t value;
value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
@@ -1089,24 +1524,23 @@ static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv,
RCC_PLLNCFGR2_DIVQ_MASK;
value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
RCC_PLLNCFGR2_DIVR_MASK;
- mmio_write_32(rcc + pll[pll_id].pllxcfgr2, value);
+ mmio_write_32(rcc_base + pll->pllxcfgr2, value);
}
-static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id,
+static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
uint32_t *pllcfg, uint32_t fracv)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
- uint32_t rcc = priv->base;
- enum stm32mp1_plltype type = pll[pll_id].plltype;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uint32_t rcc_base = stm32mp_rcc_base();
+ enum stm32mp1_plltype type = pll->plltype;
unsigned long refclk;
uint32_t ifrge = 0;
uint32_t src, value;
- src = mmio_read_32(priv->base + pll[pll_id].rckxselr) &
+ src = mmio_read_32(rcc_base + pll->rckxselr) &
RCC_SELR_REFCLK_SRC_MASK;
- refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]) /
+ refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
(pllcfg[PLLCFG_M] + 1U);
if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
@@ -1124,28 +1558,26 @@ static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv,
RCC_PLLNCFGR1_DIVM_MASK;
value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
RCC_PLLNCFGR1_IFRGE_MASK;
- mmio_write_32(rcc + pll[pll_id].pllxcfgr1, value);
+ mmio_write_32(rcc_base + pll->pllxcfgr1, value);
/* Fractional configuration */
value = 0;
- mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+ mmio_write_32(rcc_base + pll->pllxfracr, value);
value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
- mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+ mmio_write_32(rcc_base + pll->pllxfracr, value);
value |= RCC_PLLNFRACR_FRACLE;
- mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+ mmio_write_32(rcc_base + pll->pllxfracr, value);
- stm32mp1_pll_config_output(priv, pll_id, pllcfg);
+ stm32mp1_pll_config_output(pll_id, pllcfg);
return 0;
}
-static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv,
- enum stm32mp1_pll_id pll_id,
- uint32_t *csg)
+static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
{
- const struct stm32mp1_clk_pll *pll = priv->data->pll;
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
uint32_t pllxcsg = 0;
pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
@@ -1157,21 +1589,20 @@ static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv,
pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
RCC_PLLNCSGR_SSCG_MODE_MASK;
- mmio_write_32(priv->base + pll[pll_id].pllxcsgr, pllxcsg);
+ mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
}
-static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv,
- unsigned int clksrc)
+static int stm32mp1_set_clksrc(unsigned int clksrc)
{
- uint32_t address = priv->base + (clksrc >> 4);
- unsigned long start;
+ uint32_t address = stm32mp_rcc_base() + (clksrc >> 4);
+ uint64_t start;
mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK,
clksrc & RCC_SELR_SRC_MASK);
- start = get_timer(0);
+ start = timeout_start();
while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) {
- if (get_timer(start) > CLKSRC_TIMEOUT) {
+ if (timeout_elapsed(start, CLKSRC_TIMEOUT)) {
ERROR("CLKSRC %x start failed @ 0x%x: 0x%x\n",
clksrc, address, mmio_read_32(address));
return -ETIMEDOUT;
@@ -1183,14 +1614,14 @@ static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv,
static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address)
{
- unsigned long start;
+ uint64_t start;
mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
clkdiv & RCC_DIVR_DIV_MASK);
- start = get_timer(0);
+ start = timeout_start();
while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
- if (get_timer(start) > CLKDIV_TIMEOUT) {
+ if (timeout_elapsed(start, CLKDIV_TIMEOUT)) {
ERROR("CLKDIV %x start failed @ 0x%x: 0x%x\n",
clkdiv, address, mmio_read_32(address));
return -ETIMEDOUT;
@@ -1200,10 +1631,9 @@ static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address)
return 0;
}
-static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv,
- uint32_t clksrc, uint32_t clkdiv)
+static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
{
- uint32_t address = priv->base + (clksrc >> 4);
+ uint32_t address = stm32mp_rcc_base() + (clksrc >> 4);
/*
* Binding clksrc :
@@ -1224,10 +1654,9 @@ static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv,
}
}
-static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv,
- unsigned int clksrc, bool lse_css)
+static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
{
- uint32_t address = priv->base + RCC_BDCR;
+ uint32_t address = stm32mp_rcc_base() + RCC_BDCR;
if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
(clksrc != (uint32_t)CLK_RTC_DISABLED)) {
@@ -1243,52 +1672,73 @@ static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv,
}
}
-#define CNTCVL_OFF 0x008
-#define CNTCVU_OFF 0x00C
-
-static void stm32mp1_stgen_config(struct stm32mp1_clk_priv *priv)
+static void stm32mp1_stgen_config(void)
{
uintptr_t stgen;
- int p;
uint32_t cntfid0;
unsigned long rate;
+ unsigned long long counter;
stgen = fdt_get_stgen_base();
-
cntfid0 = mmio_read_32(stgen + CNTFID_OFF);
- p = stm32mp1_clk_get_parent(priv, STGEN_K);
- rate = stm32mp1_clk_get(priv, p);
+ rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
- if (cntfid0 != rate) {
- unsigned long long counter;
+ if (cntfid0 == rate) {
+ return;
+ }
- mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
- counter = (unsigned long long)
- mmio_read_32(stgen + CNTCVL_OFF);
- counter |= ((unsigned long long)
- (mmio_read_32(stgen + CNTCVU_OFF))) << 32;
- counter = (counter * rate / cntfid0);
- mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
- mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
- mmio_write_32(stgen + CNTFID_OFF, rate);
- mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+ mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+ counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF);
+ counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32;
+ counter = (counter * rate / cntfid0);
- write_cntfrq((u_register_t)rate);
+ mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
+ mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
+ mmio_write_32(stgen + CNTFID_OFF, rate);
+ mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
- /* Need to update timer with new frequency */
- generic_delay_timer_init();
- }
+ write_cntfrq((u_register_t)rate);
+
+ /* Need to update timer with new frequency */
+ generic_delay_timer_init();
}
-void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
+unsigned long stm32mp_clk_timer_get_rate(unsigned long id)
{
- uintptr_t stgen;
- unsigned long long cnt;
+ unsigned long parent_rate;
+ uint32_t prescaler, timpre;
+ uintptr_t rcc_base = stm32mp_rcc_base();
- stgen = fdt_get_stgen_base();
-
- cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
- mmio_read_32(stgen + CNTCVL_OFF);
+ parent_rate = stm32mp_clk_get_rate(id);
+
+ if (id < TIM1_K) {
+ prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
+ RCC_APBXDIV_MASK;
+ timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
+ RCC_TIMGXPRER_TIMGXPRE;
+ } else {
+ prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
+ RCC_APBXDIV_MASK;
+ timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
+ RCC_TIMGXPRER_TIMGXPRE;
+ }
+
+ if (!prescaler) {
+ return parent_rate;
+ }
+
+ return parent_rate * (timpre + 1) * 2;
+}
+
+void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
+{
+ uintptr_t stgen;
+ unsigned long long cnt;
+
+ stgen = fdt_get_stgen_base();
+
+ cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
+ mmio_read_32(stgen + CNTCVL_OFF);
cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
@@ -1298,9 +1748,46 @@ void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
}
-static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs)
+/*******************************************************************************
+ * This function determines the number of needed RTC calendar read operations
+ * to get consistent values (1 or 2 depending on clock frequencies).
+ * If APB1 frequency is lower than 7 times the RTC one, the software has to
+ * read the calendar time and date registers twice.
+ * Returns true if read twice is needed, false else.
+ ******************************************************************************/
+bool stm32mp1_rtc_get_read_twice(void)
{
- uint32_t address = priv->base + ((pkcs >> 4) & 0xFFFU);
+ unsigned long apb1_freq;
+ uint32_t rtc_freq;
+ uint32_t apb1_div;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ switch ((mmio_read_32(rcc_base + RCC_BDCR) &
+ RCC_BDCR_RTCSRC_MASK) >> RCC_BDCR_RTCSRC_SHIFT) {
+ case 1:
+ rtc_freq = stm32mp_clk_get_rate(CK_LSE);
+ break;
+ case 2:
+ rtc_freq = stm32mp_clk_get_rate(CK_LSI);
+ break;
+ case 3:
+ rtc_freq = stm32mp_clk_get_rate(CK_HSE);
+ rtc_freq /= (mmio_read_32(rcc_base + RCC_RTCDIVR) &
+ RCC_DIVR_DIV_MASK) + 1U;
+ break;
+ default:
+ panic();
+ }
+
+ apb1_div = mmio_read_32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK;
+ apb1_freq = stm32mp_clk_get_rate(CK_MCU) >> apb1_div;
+
+ return apb1_freq < (rtc_freq * 7U);
+}
+
+static void stm32mp1_pkcs_config(uint32_t pkcs)
+{
+ uint32_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
uint32_t value = pkcs & 0xFU;
uint32_t mask = 0xFU;
@@ -1314,8 +1801,7 @@ static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs)
int stm32mp1_clk_init(void)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
- uint32_t rcc = priv->base;
+ uint32_t rcc_base = stm32mp_rcc_base();
unsigned int clksrc[CLKSRC_NB];
unsigned int clkdiv[CLKDIV_NB];
unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
@@ -1323,11 +1809,16 @@ int stm32mp1_clk_init(void)
int ret, len;
enum stm32mp1_pll_id i;
bool lse_css = false;
- const uint32_t *pkcs_cell;
+ bool pll3_preserve = false;
+ bool pll4_preserve = false;
+ bool pll4_bootrom = false;
+ const fdt32_t *pkcs_cell;
+ int stgen_p = stm32mp1_clk_get_parent((int)STGEN_K);
+ int usbphy_p = stm32mp1_clk_get_parent((int)USBPHY_K);
/* Check status field to disable security */
if (!fdt_get_rcc_secure_status()) {
- mmio_write_32(rcc + RCC_TZCR, 0);
+ mmio_write_32(rcc_base + RCC_TZCR, 0);
}
ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc,
@@ -1359,113 +1850,149 @@ int stm32mp1_clk_init(void)
}
}
- stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
- stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
+ stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
+ stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
/*
* Switch ON oscillator found in device-tree.
* Note: HSI already ON after BootROM stage.
*/
- if (priv->osc[_LSI] != 0U) {
- stm32mp1_lsi_set(rcc, 1);
+ if (stm32mp1_osc[_LSI] != 0U) {
+ stm32mp1_lsi_set(true);
}
- if (priv->osc[_LSE] != 0U) {
- bool bypass;
+ if (stm32mp1_osc[_LSE] != 0U) {
+ bool bypass, digbyp;
uint32_t lsedrv;
bypass = fdt_osc_read_bool(_LSE, "st,bypass");
+ digbyp = fdt_osc_read_bool(_LSE, "st,digbypass");
lse_css = fdt_osc_read_bool(_LSE, "st,css");
lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
LSEDRV_MEDIUM_HIGH);
- stm32mp1_lse_enable(rcc, bypass, lsedrv);
+ stm32mp1_lse_enable(bypass, digbyp, lsedrv);
}
- if (priv->osc[_HSE] != 0U) {
- bool bypass, css;
+ if (stm32mp1_osc[_HSE] != 0U) {
+ bool bypass, digbyp, css;
- bypass = fdt_osc_read_bool(_LSE, "st,bypass");
- css = fdt_osc_read_bool(_LSE, "st,css");
- stm32mp1_hse_enable(rcc, bypass, css);
+ bypass = fdt_osc_read_bool(_HSE, "st,bypass");
+ digbyp = fdt_osc_read_bool(_HSE, "st,digbypass");
+ css = fdt_osc_read_bool(_HSE, "st,css");
+ stm32mp1_hse_enable(bypass, digbyp, css);
}
/*
* CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
* => switch on CSI even if node is not present in device tree
*/
- stm32mp1_csi_set(rcc, 1);
+ stm32mp1_csi_set(true);
/* Come back to HSI */
- ret = stm32mp1_set_clksrc(priv, CLK_MPU_HSI);
+ ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clksrc(priv, CLK_AXI_HSI);
+ ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
if (ret != 0) {
return ret;
}
+ if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
+ RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
+ pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
+ clksrc[CLKSRC_PLL3],
+ pllcfg[_PLL3],
+ plloff[_PLL3]);
+ pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
+ clksrc[CLKSRC_PLL4],
+ pllcfg[_PLL4],
+ plloff[_PLL4]);
+ }
+ /* Don't initialize PLL4, when used by BOOTROM */
+ if ((get_boot_device() == BOOT_DEVICE_USB) &&
+ ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
+ pll4_bootrom = true;
+ pll4_preserve = true;
+ }
+
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
- if (i == _PLL4)
+ if (((i == _PLL3) && pll3_preserve) ||
+ ((i == _PLL4) && pll4_preserve)) {
continue;
- ret = stm32mp1_pll_stop(priv, i);
+ }
+
+ ret = stm32mp1_pll_stop(i);
if (ret != 0) {
return ret;
}
}
/* Configure HSIDIV */
- if (priv->osc[_HSI] != 0U) {
- ret = stm32mp1_hsidiv(rcc, priv->osc[_HSI]);
+ if (stm32mp1_osc[_HSI] != 0U) {
+ ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
if (ret != 0) {
return ret;
}
- stm32mp1_stgen_config(priv);
+ stm32mp1_stgen_config();
}
/* Select DIV */
/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
- mmio_write_32(rcc + RCC_MPCKDIVR,
+ mmio_write_32(rcc_base + RCC_MPCKDIVR,
clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR);
+ ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
if (ret != 0) {
return ret;
}
/* No ready bit for RTC */
- mmio_write_32(rcc + RCC_RTCDIVR,
+ mmio_write_32(rcc_base + RCC_RTCDIVR,
clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
/* Configure PLLs source */
- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL12]);
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL3]);
- if (ret != 0) {
- return ret;
+
+ if (!pll3_preserve) {
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
+ if (ret != 0) {
+ return ret;
+ }
}
- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL4]);
- if (ret != 0) {
- return ret;
+ if (!pll4_preserve) {
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
+ if (ret != 0) {
+ return ret;
+ }
}
/* Configure and start PLLs */
@@ -1473,25 +2000,36 @@ int stm32mp1_clk_init(void)
uint32_t fracv;
uint32_t csg[PLLCSG_NB];
+ if (((i == _PLL3) && pll3_preserve) ||
+ ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
+ continue;
+ }
+
if (!fdt_check_node(plloff[i])) {
continue;
}
+ if ((i == _PLL4) && pll4_bootrom) {
+ /* Set output divider if not done by the Bootrom */
+ stm32mp1_pll_config_output(i, pllcfg[i]);
+ continue;
+ }
+
fracv = fdt_read_uint32_default(plloff[i], "frac", 0);
- ret = stm32mp1_pll_config(priv, i, pllcfg[i], fracv);
+ ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
if (ret != 0) {
return ret;
}
ret = fdt_read_uint32_array(plloff[i], "csg", csg,
(uint32_t)PLLCSG_NB);
if (ret == 0) {
- stm32mp1_pll_csg(priv, i, csg);
+ stm32mp1_pll_csg(i, csg);
} else if (ret != -FDT_ERR_NOTFOUND) {
return ret;
}
- stm32mp1_pll_start(priv, i);
+ stm32mp1_pll_start(i);
}
/* Wait and start PLLs ouptut when ready */
for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
@@ -1499,43 +2037,50 @@ int stm32mp1_clk_init(void)
continue;
}
- ret = stm32mp1_pll_output(priv, i, pllcfg[i][PLLCFG_O]);
+ ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
if (ret != 0) {
return ret;
}
}
/* Wait LSE ready before to use it */
- if (priv->osc[_LSE] != 0U) {
- stm32mp1_lse_wait(rcc);
+ if (stm32mp1_osc[_LSE] != 0U) {
+ stm32mp1_lse_wait();
}
/* Configure with expected clock source */
- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_MPU]);
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
if (ret != 0) {
return ret;
}
- ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_AXI]);
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
if (ret != 0) {
return ret;
}
- stm32mp1_set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css);
+ ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
+ if (ret != 0) {
+ return ret;
+ }
+ stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
/* Configure PKCK */
pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
if (pkcs_cell != NULL) {
bool ckper_disabled = false;
uint32_t j;
+ uint32_t usbreg_bootrom = 0U;
- priv->pkcs_usb_value = 0;
+ if (pll4_bootrom) {
+ usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
+ }
for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
- uint32_t pkcs = (uint32_t)fdt32_to_cpu(pkcs_cell[j]);
+ uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
ckper_disabled = true;
continue;
}
- stm32mp1_pkcs_config(priv, pkcs);
+ stm32mp1_pkcs_config(pkcs);
}
/*
@@ -1545,18 +2090,37 @@ int stm32mp1_clk_init(void)
* => deactivated CKPER only after switching clock
*/
if (ckper_disabled) {
- stm32mp1_pkcs_config(priv, CLK_CKPER_DISABLED);
+ stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
+ }
+
+ if (pll4_bootrom) {
+ uint32_t usbreg_value, usbreg_mask;
+ const struct stm32mp1_clk_sel *sel;
+
+ sel = clk_sel_ref(_USBPHY_SEL);
+ usbreg_mask = (uint32_t)sel->msk << sel->src;
+ sel = clk_sel_ref(_USBO_SEL);
+ usbreg_mask |= (uint32_t)sel->msk << sel->src;
+
+ usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
+ usbreg_mask;
+ usbreg_bootrom &= usbreg_mask;
+ if (usbreg_bootrom != usbreg_value) {
+ VERBOSE("forbidden new USB clk path\n");
+ VERBOSE("vs bootrom on USB boot\n");
+ return -FDT_ERR_BADVALUE;
+ }
}
}
/* Switch OFF HSI if not found in device-tree */
- if (priv->osc[_HSI] == 0U) {
- stm32mp1_hsi_set(rcc, 0);
+ if (stm32mp1_osc[_HSI] == 0U) {
+ stm32mp1_hsi_set(false);
}
- stm32mp1_stgen_config(priv);
+ stm32mp1_stgen_config();
/* Software Self-Refresh mode (SSR) during DDR initilialization */
- mmio_clrsetbits_32(priv->base + RCC_DDRITFCR,
+ mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
RCC_DDRITFCR_DDRCKMOD_MASK,
RCC_DDRITFCR_DDRCKMOD_SSR <<
RCC_DDRITFCR_DDRCKMOD_SHIFT);
@@ -1565,48 +2129,711 @@ int stm32mp1_clk_init(void)
}
static void stm32mp1_osc_clk_init(const char *name,
- struct stm32mp1_clk_priv *priv,
enum stm32mp_osc_id index)
{
uint32_t frequency;
- priv->osc[index] = 0;
+ if (fdt_osc_read_freq(name, &frequency) == 0) {
+ stm32mp1_osc[index] = frequency;
+ }
+}
+
+#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;
- if (fdt_osc_read_freq(name, &frequency) != 0) {
- ERROR("%s frequency request failed\n", name);
+ 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();
- } else {
- priv->osc[index] = frequency;
}
}
+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)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
enum stm32mp_osc_id i;
for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
- stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], priv, i);
+ stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
}
}
-int stm32mp1_clk_probe(void)
+/*
+ * Lookup platform clock from enable bit location in RCC registers.
+ * Return a valid clock ID on success, return ~0 on error.
+ */
+unsigned long stm32mp1_clk_rcc2id(unsigned int offset, unsigned int bit)
{
- struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+ return get_id_from_rcc_bit(offset, bit);
+}
- priv->base = fdt_rcc_read_addr();
- if (priv->base == 0U) {
- return -EINVAL;
+/*
+ * Get the parent ID of the target parent clock, for tagging as secure
+ * shared clock dependencies.
+ */
+static int get_parent_id_parent(unsigned int parent_id)
+{
+ enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
+ enum stm32mp1_pll_id pll_id;
+ uint32_t p_sel;
+
+ switch (parent_id) {
+ case _ACLK:
+ case _PCLK4:
+ case _PCLK5:
+ s = _ASS_SEL;
+ break;
+ case _PLL1_P:
+ case _PLL1_Q:
+ case _PLL1_R:
+ pll_id = _PLL1;
+ break;
+ case _PLL2_P:
+ case _PLL2_Q:
+ case _PLL2_R:
+ pll_id = _PLL2;
+ break;
+ case _PLL3_P:
+ case _PLL3_Q:
+ case _PLL3_R:
+ pll_id = _PLL3;
+ break;
+ case _PLL4_P:
+ case _PLL4_Q:
+ case _PLL4_R:
+ pll_id = _PLL4;
+ break;
+ case _PCLK1:
+ case _PCLK2:
+ case _HCLK2:
+ case _HCLK6:
+ case _CK_PER:
+ case _CK_MPU:
+ case _CK_MCU:
+ case _USB_PHY_48:
+ /* We do not expected to access these */
+ panic();
+ break;
+ default:
+ /* Other parents have no parent */
+ return -1;
}
- priv->data = &stm32mp1_data;
+ if (s != _UNKNOWN_SEL) {
+ const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
+ uintptr_t rcc_base = stm32mp_rcc_base();
- if ((priv->data->gate == NULL) || (priv->data->sel == NULL) ||
- (priv->data->pll == NULL)) {
- return -EINVAL;
+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
+ sel->msk;
+
+ if (p_sel < sel->nb_parent) {
+ return (int)sel->parent[p_sel];
+ }
+ } else {
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
+ RCC_SELR_REFCLK_SRC_MASK;
+
+ if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
+ return (int)pll->refclk[p_sel];
+ }
}
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ VERBOSE("No parent selected for %s",
+ stm32mp1_clk_parent_name[parent_id]);
+#endif
+
+ return -1;
+}
+
+static void secure_parent_clocks(unsigned long parent_id)
+{
+ int grandparent_id;
+
+ switch (parent_id) {
+ /* Secure only the parents for these clocks */
+ case _ACLK:
+ case _HCLK2:
+ case _HCLK6:
+ case _PCLK4:
+ case _PCLK5:
+ break;
+ /* PLLs */
+ case _PLL1_P:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_P);
+ break;
+ case _PLL1_Q:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_Q);
+ break;
+ case _PLL1_R:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL1_R);
+ break;
+
+ case _PLL2_P:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_P);
+ break;
+ case _PLL2_Q:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_Q);
+ break;
+ case _PLL2_R:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL2_R);
+ break;
+
+ case _PLL3_P:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_P);
+ break;
+ case _PLL3_Q:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_Q);
+ break;
+ case _PLL3_R:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_PLL3_R);
+ break;
+
+ /* Source clocks */
+ case _HSI:
+ case _HSI_KER:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_HSI);
+ break;
+ case _LSI:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_LSI);
+ break;
+ case _CSI:
+ case _CSI_KER:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_CSI);
+ break;
+ case _HSE:
+ case _HSE_KER:
+ case _HSE_KER_DIV2:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_HSE);
+ break;
+ case _LSE:
+ stm32mp1_register_secure_periph(STM32MP1_SHRES_LSE);
+ break;
+
+ default:
+ panic();
+ }
+
+ grandparent_id = get_parent_id_parent(parent_id);
+ if (grandparent_id >= 0) {
+ secure_parent_clocks(grandparent_id);
+ }
+}
+
+void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
+{
+ int parent_id;
+
+ if (!stm32mp1_rcc_is_secure()) {
+ return;
+ }
+
+ switch (clock_id) {
+ case PLL1:
+ parent_id = get_parent_id_parent(_PLL1_P);
+ break;
+ case PLL2:
+ parent_id = get_parent_id_parent(_PLL2_P);
+ break;
+ case PLL3:
+ parent_id = get_parent_id_parent(_PLL3_P);
+ break;
+ case PLL4:
+ ERROR("PLL4 cannot be secured\n");
+ panic();
+ break;
+ default:
+ /* Others are expected gateable clock */
+ parent_id = stm32mp1_clk_get_parent(clock_id);
+ break;
+ }
+
+ if (parent_id < 0) {
+ ERROR("No parent for clock %lu", clock_id);
+ panic();
+ }
+
+ secure_parent_clocks(parent_id);
+}
+
+/* Sync secure clock refcount after all drivers probe/inits, */
+void stm32mp1_update_earlyboot_clocks_state(void)
+{
+ unsigned int idx;
+
+ for (idx = 0U; idx < NB_GATES; idx++) {
+ const struct stm32mp1_clk_gate *gate = gate_ref(idx);
+ unsigned long clock_id = gate_ref(idx)->index;
+
+ /* Drop non secure refcnt on non shared shareable clocks */
+ if (__clk_is_enabled(gate) &&
+ stm32mp1_clock_is_shareable(clock_id) &&
+ !stm32mp1_clock_is_shared(clock_id)) {
+ stm32mp1_clk_disable_non_secure(clock_id);
+ }
+ }
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ /* Dump clocks state */
+ for (idx = 0U; idx < NB_GATES; idx++) {
+ const struct stm32mp1_clk_gate *gate = gate_ref(idx);
+ unsigned long __unused clock_id = gate->index;
+ unsigned int __unused refcnt = gate_refcounts[idx];
+ int __unused p = stm32mp1_clk_get_parent(clock_id);
+
+ VERBOSE("stm32mp1 clk %lu %sabled (refcnt %d) (parent %d %s)\n",
+ clock_id, __clk_is_enabled(gate) ? "en" : "dis",
+ refcnt, p,
+ p < 0 ? "n.a" : stm32mp1_clk_parent_sel_name[p]);
+ }
+#endif
+}
+
+static void sync_earlyboot_clocks_state(void)
+{
+ unsigned int idx;
+ int res;
+
+ for (idx = 0U; idx < NB_GATES; idx++) {
+ assert(gate_refcounts[idx] == 0);
+ }
+
+ /* Set a non secure refcnt for shareable clocks enabled from boot */
+ for (idx = 0U; idx < NB_GATES; idx++) {
+ struct stm32mp1_clk_gate const *gate = gate_ref(idx);
+
+ if (__clk_is_enabled(gate) &&
+ stm32mp1_clock_is_shareable(gate->index)) {
+ gate_refcounts[idx] = SHREFCNT_NONSECURE_FLAG;
+ }
+ }
+
+ /*
+ * Register secure clock parents and init a refcount for
+ * secure only resources that are not registered from a driver probe.
+ * - DDR controller and phy clocks.
+ * - TZC400, ETZPC and STGEN clocks.
+ * - RTCAPB clocks on multi-core
+ */
+ stm32mp1_register_clock_parents_secure(DDRC1);
+ stm32mp1_clk_enable_secure(DDRC1);
+ stm32mp1_register_clock_parents_secure(DDRC1LP);
+ stm32mp1_clk_enable_secure(DDRC1LP);
+ stm32mp1_register_clock_parents_secure(DDRC2);
+ stm32mp1_clk_enable_secure(DDRC2);
+ stm32mp1_register_clock_parents_secure(DDRC2LP);
+ stm32mp1_clk_enable_secure(DDRC2LP);
+ stm32mp1_register_clock_parents_secure(DDRPHYC);
+ stm32mp1_clk_enable_secure(DDRPHYC);
+ stm32mp1_register_clock_parents_secure(DDRPHYCLP);
+ stm32mp1_clk_enable_secure(DDRPHYCLP);
+ stm32mp1_register_clock_parents_secure(DDRCAPB);
+ stm32mp1_clk_enable_secure(DDRCAPB);
+ stm32mp1_register_clock_parents_secure(AXIDCG);
+ stm32mp1_clk_enable_secure(AXIDCG);
+ stm32mp1_register_clock_parents_secure(DDRPHYCAPB);
+ stm32mp1_clk_enable_secure(DDRPHYCAPB);
+ stm32mp1_register_clock_parents_secure(DDRPHYCAPBLP);
+ stm32mp1_clk_enable_secure(DDRPHYCAPBLP);
+
+ stm32mp1_register_clock_parents_secure(TZPC);
+ stm32mp1_clk_enable_secure(TZPC);
+ stm32mp1_register_clock_parents_secure(TZC1);
+ stm32mp1_clk_enable_secure(TZC1);
+ stm32mp1_register_clock_parents_secure(TZC2);
+ stm32mp1_clk_enable_secure(TZC2);
+ stm32mp1_register_clock_parents_secure(STGEN_K);
+ stm32mp1_clk_enable_secure(STGEN_K);
+
+ stm32mp1_register_clock_parents_secure(BSEC);
+ 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
+}
+
+int stm32mp1_clk_probe(void)
+{
stm32mp1_osc_init();
+ sync_earlyboot_clocks_state();
+
return 0;
}
diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c
index d4c69cb..99a7360 100644
--- a/drivers/st/clk/stm32mp1_clkfunc.c
+++ b/drivers/st/clk/stm32mp1_clkfunc.c
@@ -7,16 +7,13 @@
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <errno.h>
#include <libfdt.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
#include <stm32mp1_clk.h>
#include <stm32mp1_clkfunc.h>
-#include <stm32mp1_dt.h>
-
-#define DT_RCC_NODE_NAME "rcc@50000000"
-#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
-#define DT_RCC_COMPAT "syscon"
-#define DT_STGEN_COMPAT "st,stm32-stgen"
-#define DT_UART_COMPAT "st,stm32h7-uart"
-#define DT_USART_COMPAT "st,stm32h7-usart"
const char *stm32mp_osc_node_label[NB_OSC] = {
[_LSI] = "clk-lsi",
@@ -24,15 +21,14 @@ const char *stm32mp_osc_node_label[NB_OSC] = {
[_HSI] = "clk-hsi",
[_HSE] = "clk-hse",
[_CSI] = "clk-csi",
- [_I2S_CKIN] = "i2s_ckin",
- [_USB_PHY_48] = "ck_usbo_48m"
+ [_I2S_CKIN] = "i2s_ckin"
};
/*******************************************************************************
* This function reads the frequency of an oscillator from its name.
* It reads the value indicated inside the device tree.
- * Returns 0 if success, and a negative value else.
- * If success, value is stored in the second parameter.
+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure.
+ * On success, value is stored in the second parameter.
******************************************************************************/
int fdt_osc_read_freq(const char *name, uint32_t *freq)
{
@@ -124,7 +120,7 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name)
/*******************************************************************************
* This function reads a value of a oscillator property from its id.
- * Returns value if success, and a default value if property not found.
+ * Returns value on success, and a default value if property not found.
* Default value is passed as parameter.
******************************************************************************/
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
@@ -166,200 +162,19 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
return dflt_value;
}
-/*******************************************************************************
- * This function reads the rcc base address.
- * It reads the value indicated inside the device tree.
- * Returns address if success, and 0 value else.
- ******************************************************************************/
-uint32_t fdt_rcc_read_addr(void)
-{
- int node, subnode;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return 0;
- }
-
- node = fdt_path_offset(fdt, "/soc");
- if (node < 0) {
- return 0;
- }
-
- fdt_for_each_subnode(subnode, fdt, node) {
- const char *cchar;
- int ret;
-
- cchar = fdt_get_name(fdt, subnode, &ret);
- if (cchar == NULL) {
- return 0;
- }
-
- if (strncmp(cchar, DT_RCC_NODE_NAME, (size_t)ret) == 0) {
- const fdt32_t *cuint;
-
- cuint = fdt_getprop(fdt, subnode, "reg", NULL);
- if (cuint == NULL) {
- return 0;
- }
-
- return fdt32_to_cpu(*cuint);
- }
- }
-
- return 0;
-}
/*******************************************************************************
- * This function reads a series of parameters in rcc-clk section.
- * It reads the values indicated inside the device tree, from property name.
- * The number of parameters is also indicated as entry parameter.
+ * This function get interrupt name.
+ * It reads the values indicated the enabling status.
* Returns 0 if success, and a negative value else.
- * If success, values are stored at the second parameter address.
- ******************************************************************************/
-int fdt_rcc_read_uint32_array(const char *prop_name,
- uint32_t *array, uint32_t count)
-{
- int node;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return -ENOENT;
- }
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- return fdt_read_uint32_array(node, prop_name, array, count);
-}
-
-/*******************************************************************************
- * This function gets the subnode offset in rcc-clk section from its name.
- * It reads the values indicated inside the device tree.
- * Returns offset if success, and a negative value else.
- ******************************************************************************/
-int fdt_rcc_subnode_offset(const char *name)
-{
- int node, subnode;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return -ENOENT;
- }
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- subnode = fdt_subnode_offset(fdt, node, name);
- if (subnode <= 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- return subnode;
-}
-
-/*******************************************************************************
- * This function gets the pointer to a rcc-clk property from its name.
- * It reads the values indicated inside the device tree.
- * Length of the property is stored in the second parameter.
- * Returns pointer if success, and NULL value else.
- ******************************************************************************/
-const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
-{
- const uint32_t *cuint;
- int node, len;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return NULL;
- }
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
- if (node < 0) {
- return NULL;
- }
-
- cuint = fdt_getprop(fdt, node, prop_name, &len);
- if (cuint == NULL) {
- return NULL;
- }
-
- *lenp = len;
- return cuint;
-}
-
-/*******************************************************************************
- * This function gets the secure status for rcc node.
- * It reads secure-status in device tree.
- * Returns 1 if rcc is available from secure world, 0 else.
******************************************************************************/
-bool fdt_get_rcc_secure_status(void)
+int fdt_rcc_enable_it(const char *name)
{
- int node;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return false;
- }
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT);
- if (node < 0) {
- return false;
- }
-
- return fdt_check_secure_status(node);
-}
-
-/*******************************************************************************
- * This function reads the stgen base address.
- * It reads the value indicated inside the device tree.
- * Returns address if success, and NULL value else.
- ******************************************************************************/
-uintptr_t fdt_get_stgen_base(void)
-{
- int node;
- const fdt32_t *cuint;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return 0;
- }
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT);
- if (node < 0) {
- return 0;
- }
-
- cuint = fdt_getprop(fdt, node, "reg", NULL);
- if (cuint == NULL) {
- return 0;
- }
-
- return fdt32_to_cpu(*cuint);
-}
-
-/*******************************************************************************
- * This function gets the clock ID of the given node.
- * It reads the value indicated inside the device tree.
- * Returns ID if success, and a negative value else.
- ******************************************************************************/
-int fdt_get_clock_id(int node)
-{
- const fdt32_t *cuint;
void *fdt;
if (fdt_get_address(&fdt) == 0) {
return -ENOENT;
}
- cuint = fdt_getprop(fdt, node, "clocks", NULL);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- cuint++;
- return (int)fdt32_to_cpu(*cuint);
+ return stm32_gic_enable_spi(fdt_get_rcc_node(fdt), name);
}
diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c
new file mode 100644
index 0000000..5c7e202
--- /dev/null
+++ b/drivers/st/clk/stm32mp_clkfunc.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <libfdt.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+
+#define DT_STGEN_COMPAT "st,stm32-stgen"
+#define DT_UART_COMPAT "st,stm32h7-uart"
+
+/*******************************************************************************
+ * This function returns the RCC node in the device tree.
+ ******************************************************************************/
+int fdt_get_rcc_node(void *fdt)
+{
+ return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+}
+
+/*******************************************************************************
+ * This function reads the rcc base address.
+ * It reads the value indicated inside the device tree.
+ * Returns address on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t fdt_rcc_read_addr(void)
+{
+ int node;
+ void *fdt;
+ const fdt32_t *cuint;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return 0;
+ }
+
+ node = fdt_get_rcc_node(fdt);
+ if (node < 0) {
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function reads a series of parameters in rcc-clk section.
+ * It reads the values indicated inside the device tree, from property name.
+ * The number of parameters is also indicated as entry parameter.
+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure.
+ * On success, values are stored at the second parameter address.
+ ******************************************************************************/
+int fdt_rcc_read_uint32_array(const char *prop_name,
+ uint32_t *array, uint32_t count)
+{
+ int node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ node = fdt_get_rcc_node(fdt);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return fdt_read_uint32_array(node, prop_name, array, count);
+}
+
+/*******************************************************************************
+ * This function reads a property rcc-clk section.
+ * It reads the values indicated inside the device tree, from property name.
+ * Returns dflt_value if property is not found, and a property value on
+ * success.
+ ******************************************************************************/
+uint32_t fdt_rcc_read_uint32_default(const char *prop_name, uint32_t dflt_value)
+{
+ int node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return dflt_value;
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+ if (node < 0) {
+ return dflt_value;
+ }
+
+ return fdt_read_uint32_default(node, prop_name, dflt_value);
+}
+
+/*******************************************************************************
+ * This function gets the subnode offset in rcc-clk section from its name.
+ * It reads the values indicated inside the device tree.
+ * Returns offset on success, and a negative FDT/ERRNO error code on failure.
+ ******************************************************************************/
+int fdt_rcc_subnode_offset(const char *name)
+{
+ int node, subnode;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ node = fdt_get_rcc_node(fdt);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ subnode = fdt_subnode_offset(fdt, node, name);
+ if (subnode <= 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return subnode;
+}
+
+/*******************************************************************************
+ * This function gets the pointer to a rcc-clk property from its name.
+ * It reads the values indicated inside the device tree.
+ * Length of the property is stored in the second parameter.
+ * Returns pointer on success, and NULL value on failure.
+ ******************************************************************************/
+const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
+{
+ const fdt32_t *cuint;
+ int node, len;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return NULL;
+ }
+
+ node = fdt_get_rcc_node(fdt);
+ if (node < 0) {
+ return NULL;
+ }
+
+ cuint = fdt_getprop(fdt, node, prop_name, &len);
+ if (cuint == NULL) {
+ return NULL;
+ }
+
+ *lenp = len;
+ return cuint;
+}
+
+/*******************************************************************************
+ * This function gets the secure status for rcc node.
+ * It reads secure-status in device tree.
+ * Returns true if rcc is available from secure world, false if not.
+ ******************************************************************************/
+bool fdt_get_rcc_secure_status(void)
+{
+ int node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return false;
+ }
+
+ node = fdt_get_rcc_node(fdt);
+ if (node < 0) {
+ return false;
+ }
+
+ return !!(fdt_get_status(node) & DT_SECURE);
+}
+
+/*******************************************************************************
+ * This function reads the stgen base address.
+ * It reads the value indicated inside the device tree.
+ * Returns address on success, and NULL value on failure.
+ ******************************************************************************/
+uintptr_t fdt_get_stgen_base(void)
+{
+ int node;
+ const fdt32_t *cuint;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return 0;
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT);
+ if (node < 0) {
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets the clock ID of the given node.
+ * It reads the value indicated inside the device tree.
+ * Returns ID on success, and a negative FDT/ERRNO error code on failure.
+ ******************************************************************************/
+int fdt_get_clock_id(int node)
+{
+ const fdt32_t *cuint;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ cuint = fdt_getprop(fdt, node, "clocks", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ cuint++;
+ return (int)fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets the clock ID of the given node using clock-names.
+ * It reads the value indicated inside the device tree.
+ * Returns ID on success, and a negative FDT/ERRNO error code on failure.
+ ******************************************************************************/
+int fdt_get_clock_id_by_name(int node, const char *name)
+{
+ const fdt32_t *cuint;
+ void *fdt;
+ int index, len;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ index = fdt_stringlist_search(fdt, node, "clock-names", name);
+ if (index < 0) {
+ return index;
+ }
+
+ cuint = fdt_getprop(fdt, node, "clocks", &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((index * (int)sizeof(uint32_t)) > len) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ cuint += (index << 1) + 1;
+ return (int)fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets the frequency of the specified uart instance.
+ * From this instance, all the uarts nodes in DT are parsed, and the register
+ * base is compared to the instance. If match between these two values, then
+ * the clock source is read from the DT and we deduce the frequency.
+ * Returns clock frequency on success, 0 value on failure.
+ ******************************************************************************/
+unsigned long fdt_get_uart_clock_freq(uintptr_t instance)
+{
+ int node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return 0;
+ }
+
+ /* Check for UART nodes */
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_UART_COMPAT);
+ while (node != -FDT_ERR_NOTFOUND) {
+ const fdt32_t *cuint;
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL)
+ goto next;
+
+ if ((uintptr_t)fdt32_to_cpu(*cuint) == instance) {
+ unsigned long clk_id;
+
+ cuint = fdt_getprop(fdt, node, "clocks", NULL);
+ if (cuint == NULL)
+ goto next;
+
+ cuint++;
+ clk_id = (unsigned long)(fdt32_to_cpu(*cuint));
+
+ return stm32mp_clk_get_rate(clk_id);
+ }
+next:
+ node = fdt_node_offset_by_compatible(fdt, node, DT_UART_COMPAT);
+ }
+
+ return 0;
+}
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
index eed1d76..ae5668a 100644
--- a/drivers/st/ddr/stm32mp1_ddr.c
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -8,18 +8,14 @@
#include <arch_helpers.h>
#include <debug.h>
#include <delay_timer.h>
-#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <errno.h>
#include <mmio.h>
#include <platform.h>
+#include <platform_def.h>
#include <stddef.h>
-#include <stm32mp1_clk.h>
-#include <stm32mp1_ddr.h>
-#include <stm32mp1_ddr_regs.h>
-#include <stm32mp1_dt.h>
-#include <stm32mp1_pmic.h>
-#include <stm32mp1_pwr.h>
-#include <stm32mp1_ram.h>
-#include <stm32mp1_rcc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_pmic.h>
struct reg_desc {
const char *name;
@@ -29,7 +25,8 @@ struct reg_desc {
#define INVALID_OFFSET 0xFFU
-#define TIMESLOT_1US (plat_get_syscnt_freq2() / 1000000U)
+#define TIMESLOT_1US us2tick(1)
+#define TIMEOUT_1S s2tick(1)
#define DDRCTL_REG(x, y) \
{ \
@@ -231,40 +228,67 @@ struct ddr_reg_info {
static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
[REG_REG] = {
- "static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE
+ .name = "static",
+ .desc = ddr_reg,
+ .size = ARRAY_SIZE(ddr_reg),
+ .base = DDR_BASE
},
[REG_TIMING] = {
- "timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE
+ .name = "timing",
+ .desc = ddr_timing,
+ .size = ARRAY_SIZE(ddr_timing),
+ .base = DDR_BASE
},
[REG_PERF] = {
- "perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE
+ .name = "perf",
+ .desc = ddr_perf,
+ .size = ARRAY_SIZE(ddr_perf),
+ .base = DDR_BASE
},
[REG_MAP] = {
- "map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE
+ .name = "map",
+ .desc = ddr_map,
+ .size = ARRAY_SIZE(ddr_map),
+ .base = DDR_BASE
},
[REGPHY_REG] = {
- "static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE
+ .name = "static",
+ .desc = ddrphy_reg,
+ .size = ARRAY_SIZE(ddrphy_reg),
+ .base = DDRPHY_BASE
},
[REGPHY_TIMING] = {
- "timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE
+ .name = "timing",
+ .desc = ddrphy_timing,
+ .size = ARRAY_SIZE(ddrphy_timing),
+ .base = DDRPHY_BASE
},
[REGPHY_CAL] = {
- "cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE
+ .name = "cal",
+ .desc = ddrphy_cal,
+ .size = ARRAY_SIZE(ddrphy_cal),
+ .base = DDRPHY_BASE
},
[REG_DYN] = {
- "dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE
+ .name = "dyn",
+ .desc = ddr_dyn,
+ .size = ARRAY_SIZE(ddr_dyn),
+ .base = DDR_BASE
},
[REGPHY_DYN] = {
- "dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE
+ .name = "dyn",
+ .desc = ddrphy_dyn,
+ .size = ARRAY_SIZE(ddrphy_dyn),
+ .base = DDRPHY_BASE
},
};
-static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base)
+static uintptr_t get_base_addr(const struct ddr_info *priv, enum base_type base)
{
if (base == DDRPHY_BASE) {
- return (uint32_t)priv->phy;
+ return (uintptr_t)priv->phy;
} else {
- return (uint32_t)priv->ctl;
+ return (uintptr_t)priv->ctl;
}
}
@@ -273,21 +297,22 @@ static void set_reg(const struct ddr_info *priv,
const void *param)
{
unsigned int i;
- unsigned int *ptr, value;
+ unsigned int value;
enum base_type base = ddr_registers[type].base;
- uint32_t base_addr = get_base_addr(priv, base);
+ uintptr_t base_addr = get_base_addr(priv, base);
const struct reg_desc *desc = ddr_registers[type].desc;
VERBOSE("init %s\n", ddr_registers[type].name);
for (i = 0; i < ddr_registers[type].size; i++) {
- ptr = (unsigned int *)(base_addr + desc[i].offset);
+ uintptr_t ptr = base_addr + desc[i].offset;
+
if (desc[i].par_offset == INVALID_OFFSET) {
ERROR("invalid parameter offset for %s", desc[i].name);
panic();
} else {
- value = *((uint32_t *)((uint32_t)param +
+ value = *((uint32_t *)((uintptr_t)param +
desc[i].par_offset));
- mmio_write_32((uint32_t)ptr, value);
+ mmio_write_32(ptr, value);
}
}
}
@@ -296,26 +321,27 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
{
uint32_t pgsr;
int error = 0;
- unsigned long start;
- unsigned long time0, time;
+ uint64_t start, time0;
- start = get_timer(0);
+ start = timeout_start();
time0 = start;
do {
- pgsr = mmio_read_32((uint32_t)&phy->pgsr);
- time = get_timer(start);
+ uint64_t time;
+
+ pgsr = mmio_read_32((uintptr_t)&phy->pgsr);
+ time = timeout_start() - start;
if (time != time0) {
- VERBOSE(" > [0x%x] pgsr = 0x%x &\n",
- (uint32_t)&phy->pgsr, pgsr);
- VERBOSE(" [0x%x] pir = 0x%x (time=%x)\n",
- (uint32_t)&phy->pir,
- mmio_read_32((uint32_t)&phy->pir),
- (uint32_t)time);
+ VERBOSE(" > [0x%lx] pgsr = 0x%x &\n",
+ (uintptr_t)&phy->pgsr, pgsr);
+ VERBOSE(" [0x%lx] pir = 0x%x (time=%llx)\n",
+ (uintptr_t)&phy->pir,
+ mmio_read_32((uintptr_t)&phy->pir),
+ time);
}
time0 = time;
- if (time > plat_get_syscnt_freq2()) {
+ if (time > TIMEOUT_1S) {
panic();
}
if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) {
@@ -339,18 +365,18 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
error++;
}
} while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0);
- VERBOSE("\n[0x%x] pgsr = 0x%x\n",
- (uint32_t)&phy->pgsr, pgsr);
+ VERBOSE("\n[0x%lx] pgsr = 0x%x\n",
+ (uintptr_t)&phy->pgsr, pgsr);
}
static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir)
{
uint32_t pir_init = pir | DDRPHYC_PIR_INIT;
- mmio_write_32((uint32_t)&phy->pir, pir_init);
- VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n",
- (uint32_t)&phy->pir, pir_init,
- mmio_read_32((uint32_t)&phy->pir));
+ mmio_write_32((uintptr_t)&phy->pir, pir_init);
+ VERBOSE("[0x%lx] pir = 0x%x -> 0x%x\n",
+ (uintptr_t)&phy->pir, pir_init,
+ mmio_read_32((uintptr_t)&phy->pir));
/* Need to wait 10 configuration clock before start polling */
udelay(10);
@@ -362,56 +388,57 @@ static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir)
/* Start quasi dynamic register update */
static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl)
{
- mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
- VERBOSE("[0x%x] swctl = 0x%x\n",
- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl));
+ mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
+ VERBOSE("[0x%lx] swctl = 0x%x\n",
+ (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl));
}
/* Wait quasi dynamic register update */
static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl)
{
- unsigned long start;
+ uint64_t start;
uint32_t swstat;
- mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
- VERBOSE("[0x%x] swctl = 0x%x\n",
- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl));
+ mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
+ VERBOSE("[0x%lx] swctl = 0x%x\n",
+ (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl));
- start = get_timer(0);
+ start = timeout_start();
do {
- swstat = mmio_read_32((uint32_t)&ctl->swstat);
- VERBOSE("[0x%x] swstat = 0x%x ",
- (uint32_t)&ctl->swstat, swstat);
- VERBOSE("timer in ms 0x%x = start 0x%lx\r",
- get_timer(0), start);
- if (get_timer(start) > plat_get_syscnt_freq2()) {
+ swstat = mmio_read_32((uintptr_t)&ctl->swstat);
+ VERBOSE("[0x%lx] swstat = 0x%x ",
+ (uintptr_t)&ctl->swstat, swstat);
+ VERBOSE("timer in ms 0x%llx = start 0x%llx\r",
+ timeout_start(), start);
+ if (timeout_elapsed(start, TIMEOUT_1S)) {
panic();
}
} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U);
- VERBOSE("[0x%x] swstat = 0x%x\n",
- (uint32_t)&ctl->swstat, swstat);
+ VERBOSE("[0x%lx] swstat = 0x%x\n",
+ (uintptr_t)&ctl->swstat, swstat);
}
/* Wait quasi dynamic register update */
static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode)
{
- unsigned long start;
+ uint64_t start;
uint32_t stat;
- uint32_t operating_mode;
- uint32_t selref_type;
int break_loop = 0;
- start = get_timer(0);
+ start = timeout_start();
for ( ; ; ) {
- stat = mmio_read_32((uint32_t)&priv->ctl->stat);
+ uint32_t operating_mode;
+ uint32_t selref_type;
+
+ stat = mmio_read_32((uintptr_t)&priv->ctl->stat);
operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK;
selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK;
- VERBOSE("[0x%x] stat = 0x%x\n",
- (uint32_t)&priv->ctl->stat, stat);
- VERBOSE("timer in ms 0x%x = start 0x%lx\r",
- get_timer(0), start);
- if (get_timer(start) > plat_get_syscnt_freq2()) {
+ VERBOSE("[0x%lx] stat = 0x%x\n",
+ (uintptr_t)&priv->ctl->stat, stat);
+ VERBOSE("timer in ms 0x%llx = start 0x%llx\r",
+ timeout_start(), start);
+ if (timeout_elapsed(start, TIMEOUT_1S)) {
panic();
}
@@ -439,8 +466,8 @@ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode)
}
}
- VERBOSE("[0x%x] stat = 0x%x\n",
- (uint32_t)&priv->ctl->stat, stat);
+ VERBOSE("[0x%lx] stat = 0x%x\n",
+ (uintptr_t)&priv->ctl->stat, stat);
}
/* Mode Register Writes (MRW or MRS) */
@@ -457,7 +484,7 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr,
* No write should be performed to MRCTRL0 and MRCTRL1
* if MRSTAT.mr_wr_busy = 1.
*/
- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) &
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
;
}
@@ -470,14 +497,14 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr,
DDRCTRL_MRCTRL0_MR_RANK_ALL |
(((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) &
DDRCTRL_MRCTRL0_MR_ADDR_MASK);
- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
- VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n",
- (uint32_t)&priv->ctl->mrctrl0,
- mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0);
- mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data);
- VERBOSE("[0x%x] mrctrl1 = 0x%x\n",
- (uint32_t)&priv->ctl->mrctrl1,
- mmio_read_32((uint32_t)&priv->ctl->mrctrl1));
+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0);
+ VERBOSE("[0x%lx] mrctrl0 = 0x%x (0x%x)\n",
+ (uintptr_t)&priv->ctl->mrctrl0,
+ mmio_read_32((uintptr_t)&priv->ctl->mrctrl0), mrctrl0);
+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl1, data);
+ VERBOSE("[0x%lx] mrctrl1 = 0x%x\n",
+ (uintptr_t)&priv->ctl->mrctrl1,
+ mmio_read_32((uintptr_t)&priv->ctl->mrctrl1));
/*
* 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This
@@ -487,22 +514,22 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr,
* initiated until it is deasserted.
*/
mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR;
- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0);
- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) &
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
;
}
- VERBOSE("[0x%x] mrctrl0 = 0x%x\n",
- (uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+ VERBOSE("[0x%lx] mrctrl0 = 0x%x\n",
+ (uintptr_t)&priv->ctl->mrctrl0, mrctrl0);
}
/* Switch DDR3 from DLL-on to DLL-off */
static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
{
- uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1);
- uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2);
+ uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1);
+ uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2);
uint32_t dbgcam;
VERBOSE("mr1: 0x%x\n", mr1);
@@ -512,10 +539,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
* 1. Set the DBG1.dis_hif = 1.
* This prevents further reads/writes being received on the HIF.
*/
- mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
- VERBOSE("[0x%x] dbg1 = 0x%x\n",
- (uint32_t)&priv->ctl->dbg1,
- mmio_read_32((uint32_t)&priv->ctl->dbg1));
+ mmio_setbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
+ VERBOSE("[0x%lx] dbg1 = 0x%x\n",
+ (uintptr_t)&priv->ctl->dbg1,
+ mmio_read_32((uintptr_t)&priv->ctl->dbg1));
/*
* 2. Ensure all commands have been flushed from the uMCTL2 by polling
@@ -526,9 +553,9 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
* DBGCAM.dbg_hpr_q_depth = 0.
*/
do {
- dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam);
- VERBOSE("[0x%x] dbgcam = 0x%x\n",
- (uint32_t)&priv->ctl->dbgcam, dbgcam);
+ dbgcam = mmio_read_32((uintptr_t)&priv->ctl->dbgcam);
+ VERBOSE("[0x%lx] dbgcam = 0x%x\n",
+ (uintptr_t)&priv->ctl->dbgcam, dbgcam);
} while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) ==
DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) &&
((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U));
@@ -572,11 +599,11 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
* PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure
* the DDRC has entered self-refresh.
*/
- mmio_setbits_32((uint32_t)&priv->ctl->pwrctl,
+ mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl,
DDRCTRL_PWRCTL_SELFREF_SW);
- VERBOSE("[0x%x] pwrctl = 0x%x\n",
- (uint32_t)&priv->ctl->pwrctl,
- mmio_read_32((uint32_t)&priv->ctl->pwrctl));
+ VERBOSE("[0x%lx] pwrctl = 0x%x\n",
+ (uintptr_t)&priv->ctl->pwrctl,
+ mmio_read_32((uintptr_t)&priv->ctl->pwrctl));
/*
* 8. Wait until STAT.operating_mode[1:0]==11 indicating that the
@@ -592,10 +619,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
*/
stm32mp1_start_sw_done(priv->ctl);
- mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE);
- VERBOSE("[0x%x] mstr = 0x%x\n",
- (uint32_t)&priv->ctl->mstr,
- mmio_read_32((uint32_t)&priv->ctl->mstr));
+ mmio_setbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE);
+ VERBOSE("[0x%lx] mstr = 0x%x\n",
+ (uintptr_t)&priv->ctl->mstr,
+ mmio_read_32((uintptr_t)&priv->ctl->mstr));
stm32mp1_wait_sw_done_ack(priv->ctl);
@@ -608,27 +635,27 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
*/
/* Change Bypass Mode Frequency Range */
- if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) {
- mmio_clrbits_32((uint32_t)&priv->phy->dllgcr,
+ if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) {
+ mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr,
DDRPHYC_DLLGCR_BPS200);
} else {
- mmio_setbits_32((uint32_t)&priv->phy->dllgcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dllgcr,
DDRPHYC_DLLGCR_BPS200);
}
- mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS);
+ mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
/* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
- mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl,
DDRCTRL_PWRCTL_SELFREF_SW);
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
@@ -644,20 +671,20 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv)
*/
/* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */
- mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
- VERBOSE("[0x%x] dbg1 = 0x%x\n",
- (uint32_t)&priv->ctl->dbg1,
- mmio_read_32((uint32_t)&priv->ctl->dbg1));
+ mmio_clrbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
+ VERBOSE("[0x%lx] dbg1 = 0x%x\n",
+ (uintptr_t)&priv->ctl->dbg1,
+ mmio_read_32((uintptr_t)&priv->ctl->dbg1));
}
static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
{
stm32mp1_start_sw_done(ctl);
/* Quasi-dynamic register update*/
- mmio_setbits_32((uint32_t)&ctl->rfshctl3,
+ mmio_setbits_32((uintptr_t)&ctl->rfshctl3,
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
- mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
- mmio_clrbits_32((uint32_t)&ctl->dfimisc,
+ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
+ mmio_clrbits_32((uintptr_t)&ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
stm32mp1_wait_sw_done_ack(ctl);
}
@@ -667,21 +694,99 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
{
stm32mp1_start_sw_done(ctl);
if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) {
- mmio_clrbits_32((uint32_t)&ctl->rfshctl3,
+ mmio_clrbits_32((uintptr_t)&ctl->rfshctl3,
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
}
if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) {
- mmio_setbits_32((uint32_t)&ctl->pwrctl,
+ mmio_setbits_32((uintptr_t)&ctl->pwrctl,
DDRCTRL_PWRCTL_POWERDOWN_EN);
}
- mmio_setbits_32((uint32_t)&ctl->dfimisc,
+ mmio_setbits_32((uintptr_t)&ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
stm32mp1_wait_sw_done_ack(ctl);
}
+static void stm32mp1_refresh_cmd(struct stm32mp1_ddrctl *ctl)
+{
+ uint32_t dbgstat;
+
+ do {
+ dbgstat = mmio_read_32((uintptr_t)&ctl->dbgstat);
+ } while ((dbgstat & DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY) != 0U);
+
+ mmio_setbits_32((uintptr_t)&ctl->dbgcmd, DDRCTRL_DBGCMD_RANK0_REFRESH);
+}
+
+/* Refresh compensation by forcing refresh command
+ * Rule1: Tref should be always < tREFW ? R x tREBW/8
+ * Rule2: refcomp = RU(Tref/tREFI) = RU(RxTref/tREFW)
+ */
+static
+void stm32mp1_refresh_compensation(const struct stm32mp1_ddr_config *config,
+ struct stm32mp1_ddrctl *ctl,
+ uint64_t start)
+{
+ uint32_t tck_ps;
+ uint64_t time, time_us, tref, trefi, refcomp, i;
+
+ time = timeout_start() - start;
+ time_us = time / TIMESLOT_1US;
+ tck_ps = 1000000000U / config->info.speed;
+ if (tck_ps == 0U) {
+ return;
+ }
+ /* ref = refresh time in tck */
+ tref = time_us * 1000000U / tck_ps;
+ trefi = ((mmio_read_32((uintptr_t)&ctl->rfshtmg) &
+ DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK)
+ >> DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT) * 32U;
+ if (trefi == 0U) {
+ return;
+ }
+
+ /* div round up : number of refresh to compensate */
+ refcomp = (tref + trefi - 1U) / trefi;
+
+ for (i = 0; i < refcomp; i++) {
+ stm32mp1_refresh_cmd(ctl);
+ }
+}
+
+static void stm32mp1_self_refresh_zcal(struct ddr_info *priv, uint32_t zdata)
+{
+ /* sequence for PUBL I/O Data Retention during Power-Down */
+
+ /* 10. Override ZQ calibration with previously (pre-retention)
+ * calibrated values. This is done by writing 1 to ZQ0CRN.ZDEN
+ * and the override data to ZQ0CRN.ZDATA.
+ */
+ mmio_setbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN);
+
+ mmio_clrsetbits_32((uintptr_t)&priv->phy->zq0cr0,
+ DDRPHYC_ZQ0CRN_ZDATA_MASK,
+ zdata << DDRPHYC_ZQ0CRN_ZDATA_SHIFT);
+
+ /* 11. De-assert the PHY_top data retention enable signals
+ * (ret_en or ret_en_i/ret_en_n_i).
+ */
+ mmio_setbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRSRDIS);
+ mmio_clrbits_32((uintptr_t)(priv->pwr) + PWR_CR3, PWR_CR3_DDRRETEN);
+
+ /* 12. Remove ZQ calibration override by writing 0 to ZQ0CRN.ZDEN. */
+ mmio_clrbits_32((uintptr_t)&priv->phy->zq0cr0, DDRPHYC_ZQ0CRN_ZDEN);
+
+ /* 13. Trigger ZQ calibration by writing 1 to PIR.INIT
+ * and '1' to PIR.ZCAL
+ */
+ /* 14. Wait for ZQ calibration to finish by polling a 1 status
+ * on PGSR.IDONE.
+ */
+ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_ZCAL);
+}
+
static int board_ddr_power_init(enum ddr_type ddr_type)
{
- if (dt_check_pmic()) {
+ if (dt_pmic_status() > 0) {
return pmic_ddr_power_init(ddr_type);
}
@@ -691,13 +796,18 @@ static int board_ddr_power_init(enum ddr_type ddr_type)
void stm32mp1_ddr_init(struct ddr_info *priv,
struct stm32mp1_ddr_config *config)
{
- uint32_t pir;
- int ret;
+ uint32_t pir, ddr_reten;
+ int ret = -EINVAL;
+ uint64_t time;
if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) {
ret = board_ddr_power_init(STM32MP_DDR3);
- } else {
+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) {
ret = board_ddr_power_init(STM32MP_LPDDR2);
+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) {
+ ret = board_ddr_power_init(STM32MP_LPDDR3);
+ } else {
+ ERROR("DDR type not supported\n");
}
if (ret != 0) {
@@ -705,8 +815,29 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
}
VERBOSE("name = %s\n", config->info.name);
- VERBOSE("speed = %d MHz\n", config->info.speed);
+ VERBOSE("speed = %d kHz\n", config->info.speed);
VERBOSE("size = 0x%x\n", config->info.size);
+ if (config->self_refresh) {
+ VERBOSE("sel-refresh exit (zdata = 0x%x)\n", config->zdata);
+ }
+
+ /* Check DDR PHY pads retention */
+ ddr_reten = mmio_read_32((uint32_t)(priv->pwr) + PWR_CR3) &
+ PWR_CR3_DDRRETEN;
+ if (config->self_refresh) {
+ if (ddr_reten == 0U) {
+ VERBOSE("self-refresh aborted: no retention\n");
+ config->self_refresh = false;
+ }
+ } else {
+ if (ddr_reten != 0U) {
+ VERBOSE("disable DDR PHY retention\n");
+ mmio_setbits_32((uint32_t)(priv->pwr) + PWR_CR3,
+ PWR_CR3_DDRSRDIS);
+ mmio_clrbits_32((uint32_t)(priv->pwr) + PWR_CR3,
+ PWR_CR3_DDRRETEN);
+ }
+ }
/* DDR INIT SEQUENCE */
@@ -744,11 +875,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
/* 1.5. initialize registers ddr_umctl2 */
/* Stop uMCTL2 before PHY is ready */
- mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
- VERBOSE("[0x%x] dfimisc = 0x%x\n",
- (uint32_t)&priv->ctl->dfimisc,
- mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+ VERBOSE("[0x%lx] dfimisc = 0x%x\n",
+ (uintptr_t)&priv->ctl->dfimisc,
+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc));
set_reg(priv, REG_REG, &config->c_reg);
@@ -757,23 +888,31 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
(DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE))
== (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) {
VERBOSE("deactivate DLL OFF in mstr\n");
- mmio_clrbits_32((uint32_t)&priv->ctl->mstr,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->mstr,
DDRCTRL_MSTR_DLL_OFF_MODE);
- VERBOSE("[0x%x] mstr = 0x%x\n",
- (uint32_t)&priv->ctl->mstr,
- mmio_read_32((uint32_t)&priv->ctl->mstr));
+ VERBOSE("[0x%lx] mstr = 0x%x\n",
+ (uintptr_t)&priv->ctl->mstr,
+ mmio_read_32((uintptr_t)&priv->ctl->mstr));
}
set_reg(priv, REG_TIMING, &config->c_timing);
set_reg(priv, REG_MAP, &config->c_map);
- /* Skip CTRL init, SDRAM init is done by PHY PUBL */
- mmio_clrsetbits_32((uint32_t)&priv->ctl->init0,
- DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
- DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
- VERBOSE("[0x%x] init0 = 0x%x\n",
- (uint32_t)&priv->ctl->init0,
- mmio_read_32((uint32_t)&priv->ctl->init0));
+ /* Keep the controller in self-refresh mode */
+ if (config->self_refresh) {
+ mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl,
+ DDRCTRL_PWRCTL_SELFREF_SW);
+ }
+
+ {
+ /* Skip CTRL init, SDRAM init is done by PHY PUBL */
+ mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0,
+ DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
+ DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
+ VERBOSE("[0x%lx] init0 = 0x%x\n",
+ (uintptr_t)&priv->ctl->init0,
+ mmio_read_32((uintptr_t)&priv->ctl->init0));
+ }
set_reg(priv, REG_PERF, &config->c_perf);
@@ -786,6 +925,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
* 3. start PHY init by accessing relevant PUBL registers
* (DXGCR, DCR, PTR*, MR*, DTPR*)
*/
+
set_reg(priv, REGPHY_REG, &config->p_reg);
set_reg(priv, REGPHY_TIMING, &config->p_timing);
set_reg(priv, REGPHY_CAL, &config->p_cal);
@@ -795,10 +935,10 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
(DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE))
== (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) {
VERBOSE("deactivate DLL OFF in mr1\n");
- mmio_clrbits_32((uint32_t)&priv->phy->mr1, BIT(0));
- VERBOSE("[0x%x] mr1 = 0x%x\n",
- (uint32_t)&priv->phy->mr1,
- mmio_read_32((uint32_t)&priv->phy->mr1));
+ mmio_clrbits_32((uintptr_t)&priv->phy->mr1, BIT(0));
+ VERBOSE("[0x%lx] mr1 = 0x%x\n",
+ (uintptr_t)&priv->phy->mr1,
+ mmio_read_32((uintptr_t)&priv->phy->mr1));
}
/*
@@ -820,19 +960,31 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */
}
+ /* Treat self-refresh exit : hot boot */
+ if (config->self_refresh) {
+ /* DDR in self refresh mode, remove zcal & reset & init */
+ pir &= ~(DDRPHYC_PIR_ZCAL & DDRPHYC_PIR_DRAMRST
+ & DDRPHYC_PIR_DRAMINIT);
+ pir |= DDRPHYC_PIR_ZCALBYP;
+ }
+
stm32mp1_ddrphy_init(priv->phy, pir);
+ if (config->self_refresh) {
+ stm32mp1_self_refresh_zcal(priv, config->zdata);
+ }
+
/*
* 6. SET DFIMISC.dfi_init_complete_en to 1
* Enable quasi-dynamic register programming.
*/
stm32mp1_start_sw_done(priv->ctl);
- mmio_setbits_32((uint32_t)&priv->ctl->dfimisc,
+ mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
- VERBOSE("[0x%x] dfimisc = 0x%x\n",
- (uint32_t)&priv->ctl->dfimisc,
- mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+ VERBOSE("[0x%lx] dfimisc = 0x%x\n",
+ (uintptr_t)&priv->ctl->dfimisc,
+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc));
stm32mp1_wait_sw_done_ack(priv->ctl);
@@ -842,6 +994,13 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
*/
/* Wait uMCTL2 ready */
+
+ /* Trigger self-refresh exit */
+ if (config->self_refresh) {
+ mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl,
+ DDRCTRL_PWRCTL_SELFREF_SW);
+ }
+
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
/* Switch to DLL OFF mode */
@@ -851,6 +1010,8 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
VERBOSE("DDR DQS training : ");
+ time = timeout_start();
+
/*
* 8. Disable Auto refresh and power down by setting
* - RFSHCTL3.dis_au_refresh = 1
@@ -875,6 +1036,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */
stm32mp1_ddrphy_idone_wait(priv->phy);
+ /* Refresh compensation: forcing refresh command */
+ if (config->self_refresh) {
+ stm32mp1_refresh_compensation(config, priv->ctl, time);
+ }
+
/*
* 12. set back registers in step 8 to the orginal values if desidered
*/
@@ -882,14 +1048,16 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
config->c_reg.pwrctl);
/* Enable uMCTL2 AXI port 0 */
- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
- VERBOSE("[0x%x] pctrl_0 = 0x%x\n",
- (uint32_t)&priv->ctl->pctrl_0,
- mmio_read_32((uint32_t)&priv->ctl->pctrl_0));
+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ VERBOSE("[0x%lx] pctrl_0 = 0x%x\n",
+ (uintptr_t)&priv->ctl->pctrl_0,
+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_0));
/* Enable uMCTL2 AXI port 1 */
- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
- VERBOSE("[0x%x] pctrl_1 = 0x%x\n",
- (uint32_t)&priv->ctl->pctrl_1,
- mmio_read_32((uint32_t)&priv->ctl->pctrl_1));
+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_1,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ VERBOSE("[0x%lx] pctrl_1 = 0x%x\n",
+ (uintptr_t)&priv->ctl->pctrl_1,
+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_1));
}
diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c
index 325c0b8..63f254f 100644
--- a/drivers/st/ddr/stm32mp1_ddr_helpers.c
+++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c
@@ -4,17 +4,521 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arch_helpers.h>
+#include <debug.h>
+#include <delay_timer.h>
#include <mmio.h>
+#include <platform.h>
#include <platform_def.h>
-#include <stm32mp1_ddr_helpers.h>
-#include <stm32mp1_rcc.h>
+#include <stm32mp_common.h>
+
+#define TIMEOUT_500US us2tick(500)
void ddr_enable_clock(void)
{
- mmio_setbits_32(RCC_BASE + RCC_DDRITFCR,
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR,
RCC_DDRITFCR_DDRC1EN |
RCC_DDRITFCR_DDRC2EN |
RCC_DDRITFCR_DDRPHYCEN |
RCC_DDRITFCR_DDRPHYCAPBEN |
RCC_DDRITFCR_DDRCAPBEN);
+
+ stm32mp1_clk_rcc_regs_unlock();
+}
+
+static void do_sw_handshake(void)
+{
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
+}
+
+static void do_sw_ack(void)
+{
+ uint64_t start;
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_SWCTL, DDRCTRL_SWCTL_SW_DONE);
+
+ start = timeout_start();
+ while ((mmio_read_32(ddrctrl_base + DDRCTRL_SWSTAT) &
+ DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U) {
+ if (timeout_elapsed(start, TIMEOUT_500US)) {
+ panic();
+ }
+ }
+}
+
+static int ddr_sw_self_refresh_in(void)
+{
+ uint64_t start;
+ uint32_t stat;
+ uint32_t operating_mode;
+ uint32_t selref_type;
+ uint8_t op_mode_changed = 0;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+ uintptr_t pwr_base = stm32mp_pwr_base();
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base();
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Blocks AXI ports from taking anymore transactions */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_0,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PCTRL_1,
+ DDRCTRL_PCTRL_N_PORT_EN);
+
+ /* Waits unit all AXI ports are idle
+ * Poll PSTAT.rd_port_busy_n = 0
+ * Poll PSTAT.wr_port_busy_n = 0
+ */
+ start = timeout_start();
+ while (mmio_read_32(ddrctrl_base + DDRCTRL_PSTAT)) {
+ if (timeout_elapsed(start, TIMEOUT_500US)) {
+ goto pstat_failed;
+ }
+ }
+ /* SW Self-Refresh entry */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_SELFREF_SW);
+
+ /* Wait operating mode change in self-refresh mode
+ * with STAT.operating_mode[1:0]==11.
+ * Ensure transition to self-refresh was due to software
+ * by checking also that STAT.selfref_type[1:0]=2.
+ */
+ start = timeout_start();
+ while (!timeout_elapsed(start, TIMEOUT_500US)) {
+ stat = mmio_read_32(ddrctrl_base + DDRCTRL_STAT);
+ operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK;
+ selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK;
+
+ if ((operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) &&
+ (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) {
+ op_mode_changed = 1;
+ break;
+ }
+ }
+
+ if (op_mode_changed == 0U)
+ goto selfref_sw_failed;
+
+ /* IOs powering down (PUBL registers) */
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDR);
+
+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
+ DDRPHYC_ACIOCR_CKPDD_MASK,
+ DDRPHYC_ACIOCR_CKPDD_0);
+
+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
+ DDRPHYC_ACIOCR_CKPDR_MASK,
+ DDRPHYC_ACIOCR_CKPDR_0);
+
+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
+ DDRPHYC_ACIOCR_CSPDD_MASK,
+ DDRPHYC_ACIOCR_CSPDD_0);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
+
+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR,
+ DDRPHYC_DSGCR_ODTPDD_MASK,
+ DDRPHYC_DSGCR_ODTPDD_0);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD);
+
+ mmio_clrsetbits_32(ddrphyc_base + DDRPHYC_DSGCR,
+ DDRPHYC_DSGCR_CKEPDD_MASK,
+ DDRPHYC_DSGCR_CKEPDD_0);
+
+ /* Disable PZQ cell (PUBL register) */
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD);
+
+ /* Activate sw retention in PWRCTRL */
+ pwr_regs_lock();
+ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN);
+ pwr_regs_unlock();
+
+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
+ stm32mp1_clk_rcc_regs_lock();
+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Disable all DLLs: GLITCH window */
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR,
+ DDRPHYC_ACDLLCR_DLLDIS);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ /* Switch controller clocks (uMCTL2/PUBL) to DLL output clock */
+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
+
+ /* Deactivate all DDR clocks */
+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR,
+ RCC_DDRITFCR_DDRC1EN |
+ RCC_DDRITFCR_DDRC2EN |
+ RCC_DDRITFCR_DDRCAPBEN |
+ RCC_DDRITFCR_DDRPHYCAPBEN);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ return 0;
+
+selfref_sw_failed:
+ /* This bit should be cleared to restore DDR in its previous state */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_SELFREF_SW);
+
+pstat_failed:
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_0,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1,
+ DDRCTRL_PCTRL_N_PORT_EN);
+
+ return -1;
+}
+
+int ddr_sw_self_refresh_exit(void)
+{
+ uint64_t start;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+ uintptr_t pwr_base = stm32mp_pwr_base();
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base();
+
+ /* Enable all clocks */
+ ddr_enable_clock();
+
+ do_sw_handshake();
+
+ /* Mask dfi_init_complete_en */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_DFIMISC,
+ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+ do_sw_ack();
+
+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
+ stm32mp1_clk_rcc_regs_lock();
+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Enable all DLLs: GLITCH window */
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR,
+ DDRPHYC_ACDLLCR_DLLDIS);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX0DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX1DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX2DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DX3DLLCR,
+ DDRPHYC_DXNDLLCR_DLLDIS);
+
+ /* Additional delay to avoid early DLL clock switch */
+ udelay(10);
+
+ /* Switch controller clocks (uMCTL2/PUBL) to DLL ref clock */
+ stm32mp1_clk_rcc_regs_lock();
+ mmio_clrbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_GSKPCTRL);
+ stm32mp1_clk_rcc_regs_unlock();
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACDLLCR,
+ DDRPHYC_ACDLLCR_DLLSRST);
+
+ udelay(10);
+
+ mmio_setbits_32(ddrphyc_base + DDRPHYC_ACDLLCR,
+ DDRPHYC_ACDLLCR_DLLSRST);
+
+ /* PHY partial init: (DLL lock and ITM reset) */
+ mmio_write_32(ddrphyc_base + DDRPHYC_PIR,
+ DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK |
+ DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_INIT);
+
+ /* Need to wait at least 10 clock cycles before accessing PGSR */
+ udelay(1);
+
+ /* Pool end of init */
+ start = timeout_start();
+
+ while ((mmio_read_32(ddrphyc_base + DDRPHYC_PGSR) &
+ DDRPHYC_PGSR_IDONE) == 0U) {
+ if (timeout_elapsed(start, TIMEOUT_500US)) {
+ return -1;
+ }
+ }
+
+ do_sw_handshake();
+
+ /* Unmask dfi_init_complete_en to uMCTL2 */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_DFIMISC,
+ DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+ do_sw_ack();
+
+ /* Deactivate sw retention in PWR */
+ pwr_regs_lock();
+ mmio_clrbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRRETEN);
+ pwr_regs_unlock();
+
+ /* Enable PZQ cell (PUBL register) */
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ZQ0CR0, DDRPHYC_ZQ0CRN_ZQPD);
+
+ /* Enable pad drivers */
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR, DDRPHYC_ACIOCR_ACPDD);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
+ DDRPHYC_ACIOCR_CKPDD_MASK);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_ACIOCR,
+ DDRPHYC_ACIOCR_CSPDD_MASK);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDD);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DXCCR, DDRPHYC_DXCCR_DXPDR);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR,
+ DDRPHYC_DSGCR_ODTPDD_MASK);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR, DDRPHYC_DSGCR_NL2PD);
+
+ mmio_clrbits_32(ddrphyc_base + DDRPHYC_DSGCR,
+ DDRPHYC_DSGCR_CKEPDD_MASK);
+
+ /* Remove selfrefresh */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_SELFREF_SW);
+
+ /* Wait operating_mode == normal */
+ start = timeout_start();
+ while ((mmio_read_32(ddrctrl_base + DDRCTRL_STAT) &
+ DDRCTRL_STAT_OPERATING_MODE_MASK) !=
+ DDRCTRL_STAT_OPERATING_MODE_NORMAL) {
+ if (timeout_elapsed(start, TIMEOUT_500US)) {
+ return -1;
+ }
+ }
+
+ /* AXI ports are no longer blocked from taking transactions */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_0,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PCTRL_1,
+ DDRCTRL_PCTRL_N_PORT_EN);
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_setbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ return 0;
+}
+
+int ddr_standby_sr_entry(uint32_t *zq0cr0_zdata)
+{
+ uintptr_t pwr_base = stm32mp_pwr_base();
+ uintptr_t ddrphyc_base = stm32mp_ddrphyc_base();
+
+ /* Save IOs calibration values */
+ if (zq0cr0_zdata != NULL) {
+ *zq0cr0_zdata = mmio_read_32(ddrphyc_base + DDRPHYC_ZQ0CR0) &
+ DDRPHYC_ZQ0CRN_ZDATA_MASK;
+ }
+
+ /* Put DDR in Self-Refresh */
+ if (ddr_sw_self_refresh_in() != 0) {
+ return -1;
+ }
+
+ /* Enable I/O retention mode in standby */
+ pwr_regs_lock();
+ mmio_setbits_32(pwr_base + PWR_CR3, PWR_CR3_DDRSREN);
+ pwr_regs_unlock();
+
+ return 0;
+}
+
+void ddr_sr_mode_ssr(void)
+{
+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR;
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1EN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2EN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBLPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBLPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCAPBEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCEN);
+
+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN);
+
+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Disable HW LP interface of uMCTL2 */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_HWLPCTL,
+ DDRCTRL_HWLPCTL_HW_LP_EN);
+
+ /* Configure Automatic LP modes of uMCTL2 */
+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0);
+
+ /*
+ * Disable Clock disable with LP modes
+ * (used in RUN mode for LPDDR2 with specific timing).
+ */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE);
+
+ /* Disable automatic Self-Refresh mode */
+ mmio_clrbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_SELFREF_EN);
+}
+
+void ddr_sr_mode_asr(void)
+{
+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR;
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN);
+
+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK,
+ RCC_DDRITFCR_DDRCKMOD_ASR1);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Enable HW LP interface of uMCTL2 */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL,
+ DDRCTRL_HWLPCTL_HW_LP_EN);
+
+ /* Configure Automatic LP modes of uMCTL2 */
+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0);
+
+ /*
+ * Enable Clock disable with LP modes
+ * (used in RUN mode for LPDDR2 with specific timing).
+ */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE);
+
+ /* Enable automatic Self-Refresh for ASR mode */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_SELFREF_EN);
+}
+
+void ddr_sr_mode_hsr(void)
+{
+ uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR;
+ uintptr_t ddrctrl_base = stm32mp_ddrctrl_base();
+
+ stm32mp1_clk_rcc_regs_lock();
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_AXIDCGEN);
+
+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC1LPEN);
+
+ mmio_clrbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRC2LPEN);
+
+ mmio_setbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRPHYCLPEN);
+
+ mmio_clrsetbits_32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK,
+ RCC_DDRITFCR_DDRCKMOD_HSR1);
+
+ stm32mp1_clk_rcc_regs_unlock();
+
+ /* Enable HW LP interface of uMCTL2 */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_HWLPCTL,
+ DDRCTRL_HWLPCTL_HW_LP_EN);
+
+ /* Configure Automatic LP modes of uMCTL2 */
+ mmio_clrsetbits_32(ddrctrl_base + DDRCTRL_PWRTMG,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK,
+ DDRCTRL_PWRTMG_SELFREF_TO_X32_0);
+
+ /*
+ * Enable Clock disable with LP modes
+ * (used in RUN mode for LPDDR2 with specific timing).
+ */
+ mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL,
+ DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE);
+}
+
+bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length)
+{
+ uint64_t pa;
+
+ write_ats1cpw(address);
+
+ isb();
+
+ pa = read64_par();
+
+ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) != PAR_NS_MASK) ||
+ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) == PAR_F_MASK)) {
+ return false;
+ }
+
+ write_ats1cpw(address + length - 1U);
+
+ isb();
+
+ pa = read64_par();
+
+ if ((((pa >> PAR_NS_SHIFT) & PAR_NS_MASK) == PAR_NS_MASK) &&
+ (((pa >> PAR_F_SHIFT) & PAR_F_MASK) != PAR_F_MASK)) {
+ return true;
+ }
+
+ return false;
}
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 6d515ec..82b8fda 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -7,36 +7,30 @@
#include <arch_helpers.h>
#include <boot_api.h>
#include <debug.h>
-#include <dt-bindings/clock/stm32mp1-clks.h>
#include <errno.h>
#include <libfdt.h>
#include <mmio.h>
#include <platform_def.h>
-#include <stm32mp1_clk.h>
-#include <stm32mp1_ddr.h>
-#include <stm32mp1_ddr_helpers.h>
-#include <stm32mp1_dt.h>
-#include <stm32mp1_private.h>
-#include <stm32mp1_ram.h>
-#include <stm32mp1_rcc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
#define DDR_PATTERN 0xAAAAAAAAU
#define DDR_ANTIPATTERN 0x55555555U
static struct ddr_info ddr_priv_data;
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
{
unsigned long ddrphy_clk, ddr_clk, mem_speed_hz;
ddr_enable_clock();
- ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC);
+ ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC);
- VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n",
- mem_speed, ddrphy_clk / 1000U / 1000U);
+ VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n",
+ mem_speed, ddrphy_clk / 1000U);
- mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U;
+ mem_speed_hz = mem_speed * 1000U;
/* Max 10% frequency delta */
if (ddrphy_clk > mem_speed_hz) {
@@ -44,15 +38,35 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
} else {
ddr_clk = mem_speed_hz - ddrphy_clk;
}
- if (ddr_clk > mem_speed_hz) {
- ERROR("DDR expected freq %d MHz, current is %ld MHz\n",
- mem_speed, ddrphy_clk / 1000U / 1000U);
+ if (ddr_clk > (mem_speed_hz / 10)) {
+ ERROR("DDR expected freq %d kHz, current is %ld kHz\n",
+ mem_speed, ddrphy_clk / 1000U);
return -1;
}
return 0;
}
/*******************************************************************************
+ * This function tests a simple read/write access to the DDR.
+ * Note that the previous content is restored after test.
+ * Returns 0 if success, and address value else.
+ ******************************************************************************/
+static uint32_t ddr_test_rw_access(void)
+{
+ uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE);
+
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
+
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return (uint32_t)STM32MP_DDR_BASE;
+ }
+
+ mmio_write_32(STM32MP_DDR_BASE, saved_value);
+
+ return 0;
+}
+
+/*******************************************************************************
* This function tests the DDR data bus wiring.
* This is inspired from the Data Bus Test algorithm written by Michael Barr
* in "Programming Embedded Systems in C and C++" book.
@@ -65,10 +79,10 @@ static uint32_t ddr_test_data_bus(void)
uint32_t pattern;
for (pattern = 1U; pattern != 0U; pattern <<= 1) {
- mmio_write_32(STM32MP1_DDR_BASE, pattern);
+ mmio_write_32(STM32MP_DDR_BASE, pattern);
- if (mmio_read_32(STM32MP1_DDR_BASE) != pattern) {
- return (uint32_t)STM32MP1_DDR_BASE;
+ if (mmio_read_32(STM32MP_DDR_BASE) != pattern) {
+ return (uint32_t)STM32MP_DDR_BASE;
}
}
@@ -92,44 +106,44 @@ static uint32_t ddr_test_addr_bus(void)
/* Write the default pattern at each of the power-of-two offsets. */
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
offset <<= 1) {
- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)offset,
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset,
DDR_PATTERN);
}
/* Check for address bits stuck high. */
- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
DDR_ANTIPATTERN);
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
offset <<= 1) {
- if (mmio_read_32(STM32MP1_DDR_BASE + (uint32_t)offset) !=
+ if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) !=
DDR_PATTERN) {
- return (uint32_t)(STM32MP1_DDR_BASE + offset);
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
}
}
- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN);
/* Check for address bits stuck low or shorted. */
for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U;
testoffset <<= 1) {
- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
DDR_ANTIPATTERN);
- if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) {
- return STM32MP1_DDR_BASE;
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
+ return STM32MP_DDR_BASE;
}
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U;
offset <<= 1) {
- if ((mmio_read_32(STM32MP1_DDR_BASE +
+ if ((mmio_read_32(STM32MP_DDR_BASE +
(uint32_t)offset) != DDR_PATTERN) &&
(offset != testoffset)) {
- return (uint32_t)(STM32MP1_DDR_BASE + offset);
+ return (uint32_t)(STM32MP_DDR_BASE + offset);
}
}
- mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset,
+ mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset,
DDR_PATTERN);
}
@@ -147,13 +161,13 @@ static uint32_t ddr_check_size(void)
{
uint32_t offset = sizeof(uint32_t);
- mmio_write_32(STM32MP1_DDR_BASE, DDR_PATTERN);
+ mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN);
- while (offset < STM32MP1_DDR_MAX_SIZE) {
- mmio_write_32(STM32MP1_DDR_BASE + offset, DDR_ANTIPATTERN);
+ while (offset < STM32MP_DDR_MAX_SIZE) {
+ mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN);
dsb();
- if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) {
+ if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) {
break;
}
@@ -171,8 +185,12 @@ static int stm32mp1_ddr_setup(void)
int ret;
struct stm32mp1_ddr_config config;
int node, len;
- uint32_t tamp_clk_off = 0, uret, idx;
+ uint32_t magic, uret, idx;
void *fdt;
+ uint32_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uint32_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
#define PARAM(x, y) \
{ \
@@ -208,11 +226,16 @@ static int stm32mp1_ddr_setup(void)
return -EINVAL;
}
- config.info.speed =
- (uint16_t)fdt_read_uint32_default(node, "st,mem-speed",
- STM32MP1_DDR_SPEED_DFLT);
- config.info.size = fdt_read_uint32_default(node, "st,mem-size",
- STM32MP1_DDR_SIZE_DFLT);
+ config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0);
+ if (!config.info.speed) {
+ VERBOSE("%s: no st,mem-speed\n", __func__);
+ return -EINVAL;
+ }
+ config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0);
+ if (!config.info.size) {
+ VERBOSE("%s: no st,mem-size\n", __func__);
+ return -EINVAL;
+ }
config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len);
if (config.info.name == NULL) {
VERBOSE("%s: no st,mem-name\n", __func__);
@@ -222,7 +245,7 @@ static int stm32mp1_ddr_setup(void)
for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
ret = fdt_read_uint32_array(node, param[idx].name,
- (void *)((uint32_t)&config +
+ (void *)((uintptr_t)&config +
param[idx].offset),
param[idx].size);
@@ -235,19 +258,18 @@ static int stm32mp1_ddr_setup(void)
}
}
- if (!stm32mp1_clk_is_enabled(RTCAPB)) {
- tamp_clk_off = 1;
- if (stm32mp1_clk_enable(RTCAPB) != 0) {
- return -EINVAL;
- }
- }
+ config.self_refresh = false;
- if (tamp_clk_off != 0U) {
- if (stm32mp1_clk_disable(RTCAPB) != 0) {
- return -EINVAL;
- }
+ stm32mp_clk_enable(RTCAPB);
+
+ magic = mmio_read_32(bkpr_core1_magic);
+ if (magic == BOOT_API_A7_CORE0_MAGIC_NUMBER) {
+ config.self_refresh = true;
+ config.zdata = stm32_get_zdata_from_context();
}
+ stm32mp_clk_disable(RTCAPB);
+
/* Disable axidcg clock gating during init */
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
@@ -256,36 +278,60 @@ static int stm32mp1_ddr_setup(void)
/* Enable axidcg clock gating */
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN);
+ /* check if DDR content is lost (self-refresh aborted) */
+ if ((magic == BOOT_API_A7_CORE0_MAGIC_NUMBER) && !config.self_refresh) {
+ /* clear Backup register */
+ mmio_write_32(bkpr_core1_addr, 0);
+ /* clear magic number */
+ mmio_write_32(bkpr_core1_magic, 0);
+ }
+
priv->info.size = config.info.size;
VERBOSE("%s : ram size(%x, %x)\n", __func__,
(uint32_t)priv->info.base, (uint32_t)priv->info.size);
- dcsw_op_all(DC_OP_CISW);
+#ifndef DCACHE_OFF
write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
+ dcsw_op_all(DC_OP_CISW);
+#endif
+
+ if (config.self_refresh) {
+ uret = ddr_test_rw_access();
+ if (uret != 0U) {
+ ERROR("DDR rw test: Can't access memory @ 0x%x\n",
+ uret);
+ panic();
+ }
- uret = ddr_test_data_bus();
- if (uret != 0U) {
- ERROR("DDR data bus test: can't access memory @ 0x%x\n",
- uret);
- panic();
- }
+ /* Restore area overwritten by training */
+ stm32_restore_ddr_training_area();
+ } else {
+ uret = ddr_test_data_bus();
+ if (uret != 0U) {
+ ERROR("DDR data bus test: can't access memory @ 0x%x\n",
+ uret);
+ panic();
+ }
- uret = ddr_test_addr_bus();
- if (uret != 0U) {
- ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
- uret);
- panic();
- }
+ uret = ddr_test_addr_bus();
+ if (uret != 0U) {
+ ERROR("DDR addr bus test: can't access memory @ 0x%x\n",
+ uret);
+ panic();
+ }
- uret = ddr_check_size();
- if (uret < config.info.size) {
- ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
- uret, config.info.size);
- panic();
+ uret = ddr_check_size();
+ if (uret < config.info.size) {
+ ERROR("DDR size: 0x%x does not match DT config: 0x%x\n",
+ uret, config.info.size);
+ panic();
+ }
}
+#ifndef DCACHE_OFF
write_sctlr(read_sctlr() | SCTLR_C_BIT);
+#endif
return 0;
}
@@ -296,12 +342,12 @@ int stm32mp1_ddr_probe(void)
VERBOSE("STM32MP DDR probe\n");
- priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE;
- priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE;
- priv->pwr = PWR_BASE;
- priv->rcc = RCC_BASE;
+ priv->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base();
+ priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base();
+ priv->pwr = stm32mp_pwr_base();
+ priv->rcc = stm32mp_rcc_base();
- priv->info.base = STM32MP1_DDR_BASE;
+ priv->info.base = STM32MP_DDR_BASE;
priv->info.size = 0;
return stm32mp1_ddr_setup();
diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c
new file mode 100644
index 0000000..06c3282
--- /dev/null
+++ b/drivers/st/etzpc/etzpc.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <errno.h>
+#include <etzpc.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <utils_def.h>
+
+/* Device Tree related definitions */
+#define ETZPC_COMPAT "st,stm32-etzpc"
+#define ETZPC_LOCK_MASK 0x1U
+#define ETZPC_MODE_SHIFT 8
+#define ETZPC_MODE_MASK GENMASK(1, 0)
+#define ETZPC_ID_SHIFT 16
+#define ETZPC_ID_MASK GENMASK(7, 0)
+
+/* ID Registers */
+#define ETZPC_TZMA0_SIZE 0x000U
+#define ETZPC_DECPROT0 0x010U
+#define ETZPC_DECPROT_LOCK0 0x030U
+#define ETZPC_HWCFGR 0x3F0U
+#define ETZPC_VERR 0x3F4U
+
+/* ID Registers fields */
+#define ETZPC_TZMA0_SIZE_LOCK BIT(31)
+#define ETZPC_DECPROT0_MASK GENMASK(1, 0)
+#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0
+#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8
+#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16
+#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24
+
+#define DECPROT_SHIFT 1
+#define IDS_PER_DECPROT_REGS 16U
+#define IDS_PER_DECPROT_LOCK_REGS 32U
+
+/*
+ * etzpc_instance.
+ * base : register base address set during init given by user
+ * chunk_size : supported TZMA size steps
+ * num_tzma: number of TZMA zone read from register at init
+ * num_ahb_sec : number of securable AHB master zone read from register
+ * num_per_sec : number of securable AHB & APB Peripherals read from register
+ * revision : IP revision read from register at init
+ */
+struct etzpc_instance {
+ uintptr_t base;
+ uint8_t chunck_size;
+ uint8_t num_tzma;
+ uint8_t num_per_sec;
+ uint8_t num_ahb_sec;
+ uint8_t revision;
+};
+
+/* Only 1 instance of the ETZPC is expected per platform */
+static struct etzpc_instance etzpc_dev;
+
+struct dt_id_attr {
+ fdt32_t id_attr[STM32MP1_ETZPC_MAX_ID];
+};
+
+/*
+ * Implementation uses uint8_t to store each securable DECPROT configuration.
+ * When resuming from deep suspend, the DECPROT configurations are restored.
+ */
+#define PERIPH_LOCK_BIT BIT(7)
+#define PERIPH_ATTR_MASK GENMASK(2, 0)
+
+static bool valid_decprot_id(unsigned int id)
+{
+ return id < (unsigned int)etzpc_dev.num_per_sec;
+}
+
+#if ENABLE_ASSERTIONS
+static bool valid_tzma_id(unsigned int id)
+{
+ return id < (unsigned int)etzpc_dev.num_tzma;
+}
+#endif
+
+static int etzpc_dt_conf_decprot(int node)
+{
+ const struct dt_id_attr *conf_list;
+ void *fdt;
+ unsigned int i;
+ int len = 0;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ conf_list = (const struct dt_id_attr *)fdt_getprop(fdt, node,
+ "st,decprot", &len);
+ if (conf_list == NULL) {
+ INFO("No ETZPC configuration in DT, use default\n");
+ return 0;
+ }
+
+ for (i = 0U; i < (unsigned int)len / sizeof(uint32_t); i++) {
+ enum etzpc_decprot_attributes attr;
+ uint32_t value;
+ uint32_t id;
+ uint32_t mode;
+
+ value = fdt32_to_cpu(conf_list->id_attr[i]);
+
+ id = ((value >> ETZPC_ID_SHIFT) & ETZPC_ID_MASK);
+ if (!valid_decprot_id(id)) {
+ ERROR("Invalid DECPROT %d", id);
+ return -1;
+ }
+
+ mode = (value >> ETZPC_MODE_SHIFT) & ETZPC_MODE_MASK;
+ attr = stm32mp_etzpc_binding2decprot(mode);
+
+ stm32mp1_register_etzpc_decprot(id, attr);
+
+ etzpc_configure_decprot(id, attr);
+
+ if ((value & ETZPC_LOCK_MASK) != 0U) {
+ etzpc_lock_decprot(id);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * etzpc_configure_decprot : Load a DECPROT configuration
+ * decprot_id : ID of the IP
+ * decprot_attr : Restriction access attribute
+ */
+void etzpc_configure_decprot(uint32_t decprot_id,
+ enum etzpc_decprot_attributes decprot_attr)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+ uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK;
+
+ assert(valid_decprot_id(decprot_id));
+
+ mmio_clrsetbits_32(etzpc_dev.base + ETZPC_DECPROT0 + offset,
+ (uint32_t)ETZPC_DECPROT0_MASK << shift,
+ masked_decprot << shift);
+}
+
+/*
+ * etzpc_get_decprot : Get the DECPROT attribute
+ * decprot_id : ID of the IP
+ * return : Attribute of this DECPROT
+ */
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+ uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+ uintptr_t base_decprot = etzpc_dev.base + offset;
+ uint32_t value;
+
+ assert(valid_decprot_id(decprot_id));
+
+ value = (mmio_read_32(base_decprot + ETZPC_DECPROT0) >> shift) &
+ ETZPC_DECPROT0_MASK;
+
+ return (enum etzpc_decprot_attributes)value;
+}
+
+/*
+ * etzpc_lock_decprot : Lock access to the DECPROT attribute
+ * decprot_id : ID of the IP
+ */
+void etzpc_lock_decprot(uint32_t decprot_id)
+{
+ uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
+ uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
+ uintptr_t base_decprot = etzpc_dev.base + offset;
+
+ assert(valid_decprot_id(decprot_id));
+
+ mmio_write_32(base_decprot + ETZPC_DECPROT_LOCK0, shift);
+}
+
+/*
+ * etzpc_configure_tzma : Configure the target TZMA read only size
+ * tzma_id : ID of the memory
+ * tzma_value : read-only size
+ */
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ mmio_write_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id), tzma_value);
+}
+
+/*
+ * etzpc_get_tzma : Get the target TZMA read only size
+ * tzma_id : TZMA ID
+ * return : Size of read only size
+ */
+uint16_t etzpc_get_tzma(uint32_t tzma_id)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ return (uint16_t)mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id));
+}
+
+/*
+ * etzpc_lock_tzma : Lock the target TZMA
+ * tzma_id : TZMA ID
+ */
+void etzpc_lock_tzma(uint32_t tzma_id)
+{
+ assert(valid_tzma_id(tzma_id));
+
+ mmio_setbits_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK);
+}
+
+/*
+ * etzpc_get_lock_tzma : Return the lock status of the target TZMA
+ * tzma_id : TZMA ID
+ * return : True if TZMA is locked, false otherwise
+ */
+bool etzpc_get_lock_tzma(uint32_t tzma_id)
+{
+ uint32_t tzma_size;
+
+ assert(valid_tzma_id(tzma_id));
+
+ tzma_size = mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+ (sizeof(uint32_t) * tzma_id));
+
+ return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0;
+}
+
+/*
+ * etzpc_get_num_per_sec : Return the DECPROT ID limit value
+ */
+uint8_t etzpc_get_num_per_sec(void)
+{
+ return etzpc_dev.num_per_sec;
+}
+
+/*
+ * etzpc_get_revision : Return the ETZPC IP revision
+ */
+uint8_t etzpc_get_revision(void)
+{
+ return etzpc_dev.revision;
+}
+
+/*
+ * etzpc_get_base_address : Return the ETZPC IP base address
+ */
+uintptr_t etzpc_get_base_address(void)
+{
+ return etzpc_dev.base;
+}
+
+/*
+ * etzpc_init : Initialize the ETZPC driver
+ * Return 0 on success else a non zero value
+ */
+int etzpc_init(void)
+{
+ uint32_t hwcfg;
+ int node;
+ struct dt_node_info etzpc_info;
+
+ node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT);
+ if (node < 0) {
+ return -EIO;
+ }
+
+ /* Check ETZPC is secure only */
+ if (etzpc_info.status != DT_SECURE) {
+ return -EACCES;
+ }
+
+ etzpc_dev.base = etzpc_info.base;
+
+ hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR);
+
+ etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT);
+ etzpc_dev.num_per_sec = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_NUM_PER_SEC_SHIFT);
+ etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT);
+ etzpc_dev.chunck_size = (uint8_t)(hwcfg >>
+ ETZPC_HWCFGR_CHUNCKS1N4_SHIFT);
+
+ etzpc_dev.revision = mmio_read_8(etzpc_dev.base + ETZPC_VERR);
+
+ VERBOSE("ETZPC version 0x%x", etzpc_dev.revision);
+
+ return etzpc_dt_conf_decprot(node);
+}
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index 200b473..fc0dce8 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -4,83 +4,280 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <bl_common.h>
#include <debug.h>
+#include <errno.h>
+#include <libfdt.h>
#include <mmio.h>
+#include <platform_def.h>
#include <stdbool.h>
#include <stm32_gpio.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
-static bool check_gpio(uint32_t bank, uint32_t pin)
+#define DT_GPIO_BANK_SHIFT 12
+#define DT_GPIO_BANK_MASK 0x1F000U
+#define DT_GPIO_PIN_SHIFT 8
+#define DT_GPIO_PIN_MASK 0xF00U
+#define DT_GPIO_MODE_MASK 0xFFU
+
+/*******************************************************************************
+ * This function gets GPIO bank node in DT.
+ * Returns node offset if status is okay in DT, else return 0
+ ******************************************************************************/
+static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node)
{
- if (pin > GPIO_PIN_MAX) {
- ERROR("%s: wrong pin number (%d)\n", __func__, pin);
- return false;
- }
+ int pinctrl_subnode;
+
+ fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
+ uint32_t bank_offset;
+ const fdt32_t *cuint;
+
+ if (fdt_getprop(fdt, pinctrl_subnode,
+ "gpio-controller", NULL) == NULL) {
+ continue;
+ }
- if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) {
- ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank);
- return false;
+ cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ bank_offset = stm32_get_gpio_bank_offset(bank);
+
+ if ((fdt32_to_cpu(*cuint) == bank_offset) &&
+ (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) {
+ return pinctrl_subnode;
+ }
}
- return true;
+ return 0;
}
-void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
- uint32_t pull, uint32_t alternate)
+/*******************************************************************************
+ * This function gets the pin settings from DT information.
+ * When analyze and parsing is done, set the GPIO registers.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+static int dt_set_gpio_config(void *fdt, int node, uint8_t status)
{
- volatile uint32_t bank_address;
+ const fdt32_t *cuint, *slewrate;
+ int len;
+ int pinctrl_node;
+ uint32_t i;
+ uint32_t speed = GPIO_SPEED_LOW;
+ uint32_t pull = GPIO_NO_PULL;
+
+ cuint = fdt_getprop(fdt, node, "pinmux", &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node));
+ if (pinctrl_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
- if (!check_gpio(bank, pin)) {
- return;
+ slewrate = fdt_getprop(fdt, node, "slew-rate", NULL);
+ if (slewrate != NULL) {
+ speed = fdt32_to_cpu(*slewrate);
}
- if (bank == GPIO_BANK_Z) {
- bank_address = STM32_GPIOZ_BANK;
+ if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) {
+ pull = GPIO_PULL_UP;
+ } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) {
+ pull = GPIO_PULL_DOWN;
} else {
- bank_address = STM32_GPIOA_BANK +
- (bank * STM32_GPIO_BANK_OFFSET);
+ VERBOSE("No bias configured in node %d\n", node);
+ }
+
+ for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
+ uint32_t pincfg;
+ uint32_t bank;
+ uint32_t pin;
+ uint32_t mode;
+ uint32_t alternate = GPIO_ALTERNATE_(0);
+ int bank_node;
+ int clk;
+
+ pincfg = fdt32_to_cpu(*cuint);
+ cuint++;
+
+ bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT;
+
+ pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT;
+
+ mode = pincfg & DT_GPIO_MODE_MASK;
+
+ switch (mode) {
+ case 0:
+ mode = GPIO_MODE_INPUT;
+ break;
+ case 1 ... 16:
+ alternate = mode - 1U;
+ mode = GPIO_MODE_ALTERNATE;
+ break;
+ case 17:
+ mode = GPIO_MODE_ANALOG;
+ break;
+ default:
+ mode = GPIO_MODE_OUTPUT;
+ break;
+ }
+
+ if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) {
+ mode |= GPIO_OPEN_DRAIN;
+ }
+
+ bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node);
+ if (bank_node == 0) {
+ ERROR("PINCTRL inconsistent in DT\n");
+ panic();
+ }
+
+ clk = fdt_get_clock_id(bank_node);
+ if (clk < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ /* Platform knows the clock: assert it is okay */
+ assert(clk == stm32_get_gpio_bank_clock(bank));
+
+ set_gpio(bank, pin, mode, speed, pull, alternate, status);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function gets the pin settings from DT information.
+ * When analyze and parsing is done, set the GPIO registers.
+ * Returns 0 on success and a negative FDT/ERRNO error code on failure.
+ ******************************************************************************/
+int dt_set_pinctrl_config(int node)
+{
+ const fdt32_t *cuint;
+ int lenp = 0;
+ uint32_t i;
+ uint8_t status = fdt_get_status(node);
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ if (status == DT_DISABLED) {
+ return -FDT_ERR_NOTFOUND;
}
- mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET,
+ cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ for (i = 0; i < ((uint32_t)lenp / 4U); i++) {
+ int p_node, p_subnode;
+
+ p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (p_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ fdt_for_each_subnode(p_subnode, fdt, p_node) {
+ int ret = dt_set_gpio_config(fdt, p_subnode, status);
+
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ cuint++;
+ }
+
+ return 0;
+}
+
+void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
+ uint32_t pull, uint32_t alternate, uint8_t status)
+{
+ uintptr_t base = stm32_get_gpio_bank_base(bank);
+ int clock = stm32_get_gpio_bank_clock(bank);
+
+ assert(pin <= GPIO_PIN_MAX);
+
+ stm32mp_clk_enable((unsigned long)clock);
+
+ mmio_clrbits_32(base + GPIO_MODE_OFFSET,
((uint32_t)GPIO_MODE_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_MODE_OFFSET,
+ mmio_setbits_32(base + GPIO_MODE_OFFSET,
(mode & ~GPIO_OPEN_DRAIN) << (pin << 1));
if ((mode & GPIO_OPEN_DRAIN) != 0U) {
- mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET,
- BIT(pin));
+ mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
+ } else {
+ mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
}
- mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET,
+ mmio_clrbits_32(base + GPIO_SPEED_OFFSET,
((uint32_t)GPIO_SPEED_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1));
+ mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1));
- mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET,
+ mmio_clrbits_32(base + GPIO_PUPD_OFFSET,
((uint32_t)GPIO_PULL_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1));
+ mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1));
if (pin < GPIO_ALT_LOWER_LIMIT) {
- mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET,
+ mmio_clrbits_32(base + GPIO_AFRL_OFFSET,
((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2)));
- mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET,
+ mmio_setbits_32(base + GPIO_AFRL_OFFSET,
alternate << (pin << 2));
} else {
- mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET,
+ mmio_clrbits_32(base + GPIO_AFRH_OFFSET,
((uint32_t)GPIO_ALTERNATE_MASK <<
((pin - GPIO_ALT_LOWER_LIMIT) << 2)));
- mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET,
+ mmio_setbits_32(base + GPIO_AFRH_OFFSET,
alternate << ((pin - GPIO_ALT_LOWER_LIMIT) <<
2));
}
VERBOSE("GPIO %u mode set to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_MODE_OFFSET));
+ mmio_read_32(base + GPIO_MODE_OFFSET));
VERBOSE("GPIO %u speed set to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_SPEED_OFFSET));
+ mmio_read_32(base + GPIO_SPEED_OFFSET));
VERBOSE("GPIO %u mode pull to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_PUPD_OFFSET));
+ mmio_read_32(base + GPIO_PUPD_OFFSET));
VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_AFRL_OFFSET));
+ mmio_read_32(base + GPIO_AFRL_OFFSET));
VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_AFRH_OFFSET));
+ mmio_read_32(base + GPIO_AFRH_OFFSET));
+
+ stm32mp_clk_disable((unsigned long)clock);
+
+ if (status == DT_SECURE) {
+ stm32mp_register_secure_gpio(bank, pin);
+ } else {
+ stm32mp_register_non_secure_gpio(bank, pin);
+ }
+}
+
+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
+{
+ uintptr_t base = stm32_get_gpio_bank_base(bank);
+ int clock = stm32_get_gpio_bank_clock(bank);
+
+ assert(pin <= GPIO_PIN_MAX);
+
+ assert(!(secure && stm32mp_gpio_bank_is_non_secure(bank)));
+
+ stm32mp_clk_enable((unsigned long)clock);
+
+ if (secure) {
+ mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
+ } else {
+ mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
+ }
+
+ stm32mp_clk_disable((unsigned long)clock);
}
diff --git a/drivers/st/hash/hash_sec.c b/drivers/st/hash/hash_sec.c
new file mode 100644
index 0000000..a3c588a
--- /dev/null
+++ b/drivers/st/hash/hash_sec.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <hash_sec.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+#define RESET 0
+
+#define timer_GetTimeSec() (uint32_t)read_cntpct_el0()
+
+static void HASH_WriteData(HASH_HandleTypeDef *hHash, const uint8_t *pInBuffer,
+ uint32_t SizeInBytes);
+static void HASH_GetDigest(HASH_HandleTypeDef *hHash, uint8_t *pMsgDigest);
+static uint32_t HASH_WaitBusyClearWithTimeout(HASH_HandleTypeDef *hHash,
+ uint32_t timeout);
+static uint32_t HASH_WaitDcisClearWithTimeout(HASH_HandleTypeDef *hHash,
+ uint32_t timeout);
+
+/*****************************************************************************
+ *
+ * Function: HASH_SHA256_Init
+ *
+ * Description: Initializes the HASH peripheral
+ *
+ * Parameters: hHash : pointer to a HASH_HandleTypeDef structure that contains
+ * the configuration information for HASH module
+ *
+ * Return: none
+ *
+ *****************************************************************************/
+Std_ReturnType HASH_SHA256_Init(HASH_HandleTypeDef *hHash)
+{
+ /* Check the hash handle allocation */
+ if (!hHash) {
+ return STD_NOT_OK;
+ }
+
+ hHash->Instance = (HASH_TypeDef *)HASH_BASE;
+
+ /* Enable HASH1 clock */
+ stm32mp_clk_enable(HASH1);
+
+ hHash->Error = HASH_INIT_NOT_DONE;
+
+ hHash->pHashInBuffPtr = NULL;
+
+ hHash->pHashOutBuffPtr = NULL;
+
+ /* Set the data type to 8 bits */
+ hHash->Instance->CR |= HASH_DATATYPE_8B;
+
+ /* Select the SHA256 mode and reset the HASH processor core,
+ * so that the HASH will be ready to compute the message digest
+ * of a new message
+ */
+ hHash->Instance->CR |= HASH_AlgoSelection_SHA256 | HASH_CR_INIT;
+
+ /* Return function status */
+ hHash->Error = HASH_INIT_DONE;
+
+ return STD_OK;
+}
+
+/*****************************************************************************
+ *
+ * Function: HASH_SHA256_Start
+ *
+ * Description: Initializes the HASH peripheral in SHA256 mode
+ * then processes pInBuffer.
+ * The digest is available in pOutBuffer.
+ *
+ * Parameters: hHash : pointer to a HASH_HandleTypeDef structure that contains
+ * the configuration information for HASH module
+ *
+ * pInBuffer: Pointer to the input buffer (buffer to be hashed).
+ *
+ * sizeInBytes: Length of the input buffer in bytes.
+ * If the Size is not multiple of 64 bytes,
+ * the padding is managed by hardware.
+ *
+ * pOutBuffer: Pointer to the computed digest.
+ * Its size must be 32 bytes.
+ *
+ * Timeout: Specify Timeout value
+ *
+ * Return: none
+ *
+ *****************************************************************************/
+Std_ReturnType HASH_SHA256_Start(HASH_HandleTypeDef *hHash,
+ const uint8_t *pInBuffer, uint32_t sizeInBytes,
+ uint8_t *pOutBuffer, uint32_t Timeout)
+{
+ uint32_t timeoutDetected = 0;
+
+ /* Check the hash handle allocation */
+ if (!hHash) {
+ return STD_NOT_OK;
+ }
+
+ hHash->pHashInBuffPtr = pInBuffer;
+ hHash->pHashOutBuffPtr = pOutBuffer;
+
+ /* Configure the number of valid bits in last word 32 bits
+ * of the bit stream
+ */
+ __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(sizeInBytes);
+
+ /* Fill in entire input buffer to be hashed in HASH DIN register
+ * Note : intermediate digest is computed each time 64 bytes are written
+ * in HASH_DIN register
+ */
+ HASH_WriteData(hHash, pInBuffer, sizeInBytes);
+
+ /* Start the Final Digest calculation */
+ hHash->Instance->STR |= HASH_STR_DCAL;
+
+ /* Check for timeout */
+ timeoutDetected = HASH_WaitBusyClearWithTimeout(hHash, Timeout);
+ if (timeoutDetected != 0) {
+ hHash->Error = HASH_TIMEOUT;
+ return STD_NOT_OK;
+ }
+
+ /* Read the message digest in output buffer */
+ HASH_GetDigest(hHash, pOutBuffer);
+
+ hHash->Error = HASH_DIGEST_DONE;
+
+ return STD_OK;
+}
+
+/*****************************************************************************
+ *
+ * Function: HASH_SHA256_Accumulate
+ *
+ * Description: Initializes the HASH peripheral in SHA256 mode then processes
+ * pInBuffer.
+ *
+ * Parameters: hHash: pointer to a HASH_HandleTypeDef structure that contains
+ * the configuration information for HASH module
+ *
+ * pInBuffer: Pointer to the input buffer (buffer to be hashed).
+ *
+ * sizeInBytes: Length of the input buffer in bytes.
+ * If the Size is not multiple of 64 bytes, the padding is managed
+ * by hardware.
+ *
+ * Return: none
+ *
+ *****************************************************************************/
+Std_ReturnType HASH_SHA256_Accumulate(HASH_HandleTypeDef *hHash,
+ const uint8_t *pInBuffer,
+ uint32_t sizeInBytes)
+{
+ /* Check the hash handle allocation */
+ if (!hHash) {
+ return STD_NOT_OK;
+ }
+
+ hHash->pHashInBuffPtr = pInBuffer;
+
+ /* Configure the number of valid bits in last 32 bits word
+ * of the message
+ */
+ __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(sizeInBytes);
+
+ /* Write input buffer in data register */
+ HASH_WriteData(hHash, pInBuffer, sizeInBytes);
+
+ /* Return function status */
+ hHash->Error = HASH_ACCU_DONE;
+
+ return STD_OK;
+}
+
+/*****************************************************************************
+ *
+ * Function: HASH_SHA256_Finish
+ *
+ * Description: Returns the computed digest in SHA256.
+ *
+ * Parameters: hHash: pointer to a HASH_HandleTypeDef structure that contains
+ * the configuration information for HASH module
+ *
+ * pOutBuffer: Pointer to the computed digest.
+ * Its size must be 32 bytes.
+ *
+ * Timeout: Timeout value
+ *
+ * Return: none
+ *
+ *****************************************************************************/
+Std_ReturnType HASH_SHA256_Finish(HASH_HandleTypeDef *hHash,
+ uint8_t *pOutBuffer, uint32_t Timeout)
+{
+ uint32_t timeoutDetected = 0;
+
+ /* Check the hash handle allocation */
+ if (!hHash) {
+ return STD_NOT_OK;
+ }
+
+ hHash->pHashOutBuffPtr = pOutBuffer;
+
+ /* Check for the Timeout */
+ timeoutDetected = HASH_WaitDcisClearWithTimeout(hHash, Timeout);
+ if (timeoutDetected != 0) {
+ hHash->Error = HASH_TIMEOUT;
+ return STD_NOT_OK;
+ }
+
+ /* Read the message digest */
+ HASH_GetDigest(hHash, pOutBuffer);
+
+ /* Return function status */
+ hHash->Error = HASH_FINISHED;
+
+ return STD_OK;
+}
+
+/* Static functions ----------------------------------------------------------*/
+
+/**
+ * @brief Writes the input buffer in HASH_DIN register.
+ * @param pInBuffer: Pointer to input buffer
+ * @param SizeInBytes : The size of input buffer (in bytes)
+ * @retval None
+ */
+static void HASH_WriteData(HASH_HandleTypeDef *hHash, const uint8_t *pInBuffer,
+ uint32_t SizeInBytes)
+{
+ uint32_t *pInWord32 = (uint32_t *)pInBuffer;
+ uint32_t nbBlocks = (SizeInBytes / HASH_BLOCK_SIZE_NB_BYTES);
+ uint32_t remainingBytesInLastBlock = (SizeInBytes %
+ HASH_BLOCK_SIZE_NB_BYTES);
+ uint32_t remainingBytesInLastWord = (SizeInBytes % 4);
+ uint32_t idxBlock = 0;
+ uint32_t idxWord32;
+
+ /* For all blocks */
+ for (idxBlock = 0; idxBlock < nbBlocks; idxBlock++) {
+ for (idxWord32 = 0; idxWord32 < (HASH_BLOCK_SIZE_NB_BYTES / 4);
+ idxWord32++) {
+ hHash->Instance->DIN = *pInWord32;
+ pInWord32++;
+ }
+
+ /* Wait until end of computation of intermediate digest */
+ while ((hHash->Instance->SR & HASH_SR_DINIS) == HASH_SR_DINIS) {
+ ;
+ }
+ }
+
+ if (remainingBytesInLastBlock != 0) {
+ uint32_t nbWords32Remaining = (remainingBytesInLastBlock / 4);
+
+ for (idxWord32 = 0; idxWord32 < nbWords32Remaining;
+ idxWord32++) {
+ hHash->Instance->DIN = *pInWord32;
+ pInWord32++;
+ }
+ }
+
+ if (remainingBytesInLastWord != 0) {
+ hHash->Instance->DIN = *pInWord32;
+ }
+}
+
+#ifndef __CC_ARM
+/* __rev is a builtin command in ARM compiler
+ * it needs to be remapped on __builtin_bswap32 for GCC
+ */
+#define __rev __builtin_bswap32
+#endif
+
+/**
+ * @brief Provides the message digest result.
+ * @param hHash: Hash handle
+ * @param pMsgDigest: Pointer to the message digest
+ * @retval None
+ */
+static void HASH_GetDigest(HASH_HandleTypeDef *hHash, uint8_t *pMsgDigest)
+{
+ uintptr_t msgdigest = (uintptr_t)pMsgDigest;
+
+ /* Read the message digest */
+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[0]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[1]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[2]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[3]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(hHash->Instance->HR[4]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[5]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[6]);
+ msgdigest += 4;
+ *(uintptr_t *)(msgdigest) = __rev(HASH_DIGEST->HR[7]);
+}
+
+/**
+ * @brief This function waits until bit HASH_SR_BUSY is 1b0' before a timeout.
+ * @param [in] hHash : hash handle
+ * @param [in] timeout : timeout value
+ *
+ * @retval timeoutDetected : value 0x1 if timeout was detected while
+ * waiting for bit BUSY to be cleared.
+ ******************************************************************************
+ */
+
+static uint32_t HASH_WaitBusyClearWithTimeout(HASH_HandleTypeDef *hHash,
+ uint32_t timeout)
+{
+ uint32_t timerValInit = 0;
+ uint32_t timeoutDetected = 0;
+
+ /* Get timer current value at start of loop */
+ timerValInit = timer_GetTimeSec();
+
+ while (((hHash->Instance->SR & HASH_SR_BUSY) == HASH_SR_BUSY) &&
+ (timeoutDetected == 0)) {
+ /* Sense timeout occurrence */
+ if ((timer_GetTimeSec() - timerValInit) >= timeout) {
+ timeoutDetected = 1;
+ }
+ }
+
+ return timeoutDetected;
+}
+
+/**
+ * @brief This function waits until bit HASH_SR_DCIS is 1b0' before a timeout.
+ * @param [in] hHash : hash handle
+ * @param [in] timeout : timeout value
+ *
+ * @retval timeoutDetected : value 0x1 if timeout was detected while
+ * waiting for bit DCIS to be cleared.
+ ******************************************************************************
+ */
+
+static uint32_t HASH_WaitDcisClearWithTimeout(HASH_HandleTypeDef *hHash,
+ uint32_t timeout)
+{
+ uint32_t timerValInit = 0;
+ uint32_t timeoutDetected = 0;
+
+ /* Get timer current value at start of loop */
+ timerValInit = timer_GetTimeSec();
+
+ while ((HAL_IS_BIT_CLR(hHash->Instance->SR, HASH_SR_DCIS)) &&
+ (timeoutDetected == 0)) {
+ /* Sense timeout occurrence */
+ if ((timer_GetTimeSec() - timerValInit) >= timeout) {
+ timeoutDetected = 1;
+ }
+ }
+
+ return timeoutDetected;
+}
diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
new file mode 100644
index 0000000..694a76a
--- /dev/null
+++ b/drivers/st/i2c/stm32_i2c.c
@@ -0,0 +1,1371 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <limits.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_gpio.h>
+#include <stm32_i2c.h>
+#include <stm32mp_common.h>
+#include <utils.h>
+
+/* STM32 I2C registers offsets */
+#define I2C_CR1 0x00U
+#define I2C_CR2 0x04U
+#define I2C_OAR1 0x08U
+#define I2C_OAR2 0x0CU
+#define I2C_TIMINGR 0x10U
+#define I2C_TIMEOUTR 0x14U
+#define I2C_ISR 0x18U
+#define I2C_ICR 0x1CU
+#define I2C_PECR 0x20U
+#define I2C_RXDR 0x24U
+#define I2C_TXDR 0x28U
+
+#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU
+
+#define MAX_NBYTE_SIZE 255U
+
+#define I2C_NSEC_PER_SEC 1000000000L
+
+/*
+ * struct i2c_spec_s - Private I2C timing specifications.
+ * @rate: I2C bus speed (Hz)
+ * @rate_min: 80% of I2C bus speed (Hz)
+ * @rate_max: 120% of I2C bus speed (Hz)
+ * @fall_max: Max fall time of both SDA and SCL signals (ns)
+ * @rise_max: Max rise time of both SDA and SCL signals (ns)
+ * @hddat_min: Min data hold time (ns)
+ * @vddat_max: Max data valid time (ns)
+ * @sudat_min: Min data setup time (ns)
+ * @l_min: Min low period of the SCL clock (ns)
+ * @h_min: Min high period of the SCL clock (ns)
+ */
+struct i2c_spec_s {
+ uint32_t rate;
+ uint32_t rate_min;
+ uint32_t rate_max;
+ uint32_t fall_max;
+ uint32_t rise_max;
+ uint32_t hddat_min;
+ uint32_t vddat_max;
+ uint32_t sudat_min;
+ uint32_t l_min;
+ uint32_t h_min;
+};
+
+/*
+ * struct i2c_timing_s - Private I2C output parameters.
+ * @scldel: Data setup time
+ * @sdadel: Data hold time
+ * @sclh: SCL high period (master mode)
+ * @sclh: SCL low period (master mode)
+ * @is_saved: True if relating to a configuration candidate
+ */
+struct i2c_timing_s {
+ uint8_t scldel;
+ uint8_t sdadel;
+ uint8_t sclh;
+ uint8_t scll;
+ bool is_saved;
+};
+
+/**
+ * All these values are coming from I2C Specification, Version 6.0, 4th of
+ * April 2014.
+ *
+ * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast,
+ * and Fast-mode Plus I2C-bus devices.
+ */
+static const struct i2c_spec_s i2c_specs[] = {
+ [I2C_SPEED_STANDARD] = {
+ .rate = STANDARD_RATE,
+ .rate_min = 8000,
+ .rate_max = 120000,
+ .fall_max = 300,
+ .rise_max = 1000,
+ .hddat_min = 0,
+ .vddat_max = 3450,
+ .sudat_min = 250,
+ .l_min = 4700,
+ .h_min = 4000,
+ },
+ [I2C_SPEED_FAST] = {
+ .rate = FAST_RATE,
+ .rate_min = 320000,
+ .rate_max = 480000,
+ .fall_max = 300,
+ .rise_max = 300,
+ .hddat_min = 0,
+ .vddat_max = 900,
+ .sudat_min = 100,
+ .l_min = 1300,
+ .h_min = 600,
+ },
+ [I2C_SPEED_FAST_PLUS] = {
+ .rate = FAST_PLUS_RATE,
+ .rate_min = 800000,
+ .rate_max = 1200000,
+ .fall_max = 100,
+ .rise_max = 120,
+ .hddat_min = 0,
+ .vddat_max = 450,
+ .sudat_min = 50,
+ .l_min = 500,
+ .h_min = 260,
+ },
+};
+
+static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
+ uint16_t dev_addr, uint16_t mem_addr,
+ uint16_t mem_add_size,
+ uint64_t tick_to, uint64_t tick_start);
+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint64_t tick_to, uint64_t tick_start);
+
+/* Private functions to handle flags during polling transfer */
+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
+ uint8_t awaited_value,
+ uint64_t tick_to, uint64_t tick_start);
+static int i2c_wait_txis(struct i2c_handle_s *hi2c,
+ uint64_t tick_to, uint64_t tick_start);
+static int i2c_wait_stop(struct i2c_handle_s *hi2c,
+ uint64_t tick_to, uint64_t tick_start);
+static int i2c_ack_failed(struct i2c_handle_s *hi2c,
+ uint64_t tick_to, uint64_t tick_start);
+
+/* Private function to flush TXDR register */
+static void i2c_flush_txdr(struct i2c_handle_s *hi2c);
+
+/* Private function to start, restart or stop a transfer */
+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t size, uint32_t i2c_mode,
+ uint32_t request);
+
+static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
+{
+ hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+ hi2c->i2c_state = I2C_STATE_READY;
+}
+
+/*
+ * @brief Compute the I2C device timings.
+ * @param init: Ref to the initialization configuration structure
+ * @param clock_src: I2C clock source frequency (Hz)
+ * @param timing: Pointer to the final computed timing result
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_compute_timing(struct stm32_i2c_init_s *init,
+ uint32_t clock_src, uint32_t *timing)
+{
+ enum i2c_speed_e mode = init->speed_mode;
+ uint32_t speed_freq;
+ uint32_t i2cclk = udiv_round_nearest(I2C_NSEC_PER_SEC, clock_src);
+ uint32_t i2cbus;
+ uint32_t p_prev = I2C_TIMINGR_PRESC_MAX;
+ uint32_t af_delay_min;
+ uint32_t af_delay_max;
+ uint32_t dnf_delay;
+ uint32_t tsync;
+ uint32_t clk_min;
+ uint32_t clk_max;
+ int clk_error_prev;
+ uint16_t p;
+ uint16_t l;
+ uint16_t a;
+ uint16_t h;
+ int sdadel_min;
+ int sdadel_max;
+ uint32_t sdadel_min_u;
+ uint32_t sdadel_max_u;
+ uint32_t scldel_min;
+ int s = -1;
+ struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX];
+
+ switch (mode) {
+ case I2C_SPEED_STANDARD ... I2C_SPEED_FAST_PLUS:
+ break;
+ default:
+ ERROR("I2C speed out of bound {%d/%d}\n",
+ mode, I2C_SPEED_FAST_PLUS);
+ return -EINVAL;
+ }
+
+ speed_freq = i2c_specs[mode].rate;
+ i2cbus = udiv_round_nearest(I2C_NSEC_PER_SEC, speed_freq);
+ clk_error_prev = INT_MAX;
+
+ if ((init->rise_time > i2c_specs[mode].rise_max) ||
+ (init->fall_time > i2c_specs[mode].fall_max)) {
+ ERROR(" I2C timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
+ init->rise_time, i2c_specs[mode].rise_max,
+ init->fall_time, i2c_specs[mode].fall_max);
+ return -EINVAL;
+ }
+
+ if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) {
+ ERROR("DNF out of bound %d/%d\n",
+ init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX);
+ return -EINVAL;
+ }
+
+ /* Analog and Digital Filters */
+ af_delay_min = (init->analog_filter ?
+ STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0);
+ af_delay_max = (init->analog_filter ?
+ STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0);
+ dnf_delay = init->digital_filter_coef * i2cclk;
+
+ sdadel_min = i2c_specs[mode].hddat_min + init->fall_time -
+ af_delay_min - ((init->digital_filter_coef + 3) * i2cclk);
+
+ sdadel_max = i2c_specs[mode].vddat_max - init->rise_time -
+ af_delay_max - ((init->digital_filter_coef + 4) * i2cclk);
+
+ scldel_min = init->rise_time + i2c_specs[mode].sudat_min;
+
+ if (sdadel_min < 0) {
+ sdadel_min_u = 0;
+ } else {
+ sdadel_min_u = (uint32_t)sdadel_min;
+ }
+
+ if (sdadel_max < 0) {
+ sdadel_max_u = 0;
+ } else {
+ sdadel_max_u = (uint32_t)sdadel_max;
+ }
+
+ VERBOSE("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u\n",
+ sdadel_min_u, sdadel_max_u, scldel_min);
+
+ zeromem(&solutions, sizeof(solutions));
+
+ /* Compute possible values for PRESC, SCLDEL and SDADEL */
+ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) {
+ for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) {
+ uint32_t scldel = (l + 1) * (p + 1) * i2cclk;
+
+ if (scldel < scldel_min) {
+ continue;
+ }
+
+ for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) {
+ uint32_t sdadel = (a * (p + 1) + 1) * i2cclk;
+
+ if ((sdadel >= sdadel_min_u) &&
+ (sdadel <= sdadel_max_u) &&
+ (p != p_prev)) {
+ solutions[p].scldel = l;
+ solutions[p].sdadel = a;
+ solutions[p].is_saved = true;
+ p_prev = p;
+ break;
+ }
+ }
+
+ if (p_prev == p) {
+ break;
+ }
+ }
+ }
+
+ if (p_prev == I2C_TIMINGR_PRESC_MAX) {
+ ERROR(" I2C no Prescaler solution\n");
+ return -EPERM;
+ }
+
+ tsync = af_delay_min + dnf_delay + (2 * i2cclk);
+ clk_max = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_min;
+ clk_min = I2C_NSEC_PER_SEC / i2c_specs[mode].rate_max;
+
+ /*
+ * Among prescaler possibilities discovered above figures out SCL Low
+ * and High Period. Provided:
+ * - SCL Low Period has to be higher than Low Period of the SCL Clock
+ * defined by I2C Specification. I2C Clock has to be lower than
+ * (SCL Low Period - Analog/Digital filters) / 4.
+ * - SCL High Period has to be lower than High Period of the SCL Clock
+ * defined by I2C Specification.
+ * - I2C Clock has to be lower than SCL High Period.
+ */
+ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) {
+ uint32_t prescaler = (p + 1) * i2cclk;
+
+ if (!solutions[p].is_saved) {
+ continue;
+ }
+
+ for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) {
+ uint32_t tscl_l = ((l + 1) * prescaler) + tsync;
+
+ if ((tscl_l < i2c_specs[mode].l_min) ||
+ (i2cclk >=
+ ((tscl_l - af_delay_min - dnf_delay) / 4))) {
+ continue;
+ }
+
+ for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) {
+ uint32_t tscl_h = ((h + 1) * prescaler) + tsync;
+ uint32_t tscl = tscl_l + tscl_h +
+ init->rise_time +
+ init->fall_time;
+
+ if ((tscl >= clk_min) && (tscl <= clk_max) &&
+ (tscl_h >= i2c_specs[mode].h_min) &&
+ (i2cclk < tscl_h)) {
+ int clk_error = tscl - i2cbus;
+
+ if (clk_error < 0) {
+ clk_error = -clk_error;
+ }
+
+ if (clk_error < clk_error_prev) {
+ clk_error_prev = clk_error;
+ solutions[p].scll = l;
+ solutions[p].sclh = h;
+ s = p;
+ }
+ }
+ }
+ }
+ }
+
+ if (s < 0) {
+ ERROR(" I2C no solution at all\n");
+ return -EPERM;
+ }
+
+ /* Finalize timing settings */
+ *timing = I2C_SET_TIMINGR_PRESC(s) |
+ I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) |
+ I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) |
+ I2C_SET_TIMINGR_SCLH(solutions[s].sclh) |
+ I2C_SET_TIMINGR_SCLL(solutions[s].scll);
+
+ VERBOSE("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%i/%i\n",
+ s, solutions[s].scldel, solutions[s].sdadel);
+ VERBOSE("I2C TIMINGR (SCLH/SCLL): %i/%i\n",
+ solutions[s].sclh, solutions[s].scll);
+ VERBOSE("I2C TIMINGR: 0x%x\n", *timing);
+
+ return 0;
+}
+
+/*
+ * @brief Setup the I2C device timings.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param init: Ref to the initialization configuration structure
+ * @param timing: Pointer to the final computed timing result
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_setup_timing(struct i2c_handle_s *hi2c,
+ struct stm32_i2c_init_s *init,
+ uint32_t *timing)
+{
+ int rc = 0;
+ uint32_t clock_src;
+
+ clock_src = stm32mp_clk_get_rate(hi2c->clock);
+ if (clock_src == 0U) {
+ ERROR("I2C clock rate is 0\n");
+ return -EINVAL;
+ }
+
+ do {
+ rc = i2c_compute_timing(init, clock_src, timing);
+ if (rc != 0) {
+ ERROR("Failed to compute I2C timings\n");
+ if (init->speed_mode > I2C_SPEED_STANDARD) {
+ init->speed_mode--;
+ WARN("Downgrade I2C speed to %uHz)\n",
+ i2c_specs[init->speed_mode].rate);
+ } else {
+ break;
+ }
+ }
+ } while (rc != 0);
+
+ if (rc != 0) {
+ ERROR("Impossible to compute I2C timings\n");
+ return rc;
+ }
+
+ VERBOSE("I2C Speed Mode(%i), Freq(%i), Clk Source(%i)\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);
+ VERBOSE("I2C Analog Filter(%s), DNF(%i)\n",
+ (init->analog_filter ? "On" : "Off"),
+ init->digital_filter_coef);
+
+ return 0;
+}
+
+/*
+ * @brief Configure I2C Analog noise filter.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C peripheral.
+ * @param analog_filter: New state of the Analog filter
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
+ uint32_t analog_filter)
+{
+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+ return -EBUSY;
+ }
+
+ hi2c->lock = 1;
+
+ hi2c->i2c_state = I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+ /* Reset I2Cx ANOFF bit */
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
+
+ /* Set analog filter bit*/
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
+
+ /* Enable the selected I2C peripheral */
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+ hi2c->i2c_state = I2C_STATE_READY;
+
+ hi2c->lock = 0;
+
+ return 0;
+}
+
+/*
+ * @brief Get I2C setup information from the device tree and set pinctrl
+ * configuration.
+ * @param fdt: Pointer to the device tree
+ * @param node: I2C node offset
+ * @param init: Ref to the initialization configuration structure
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
+ struct stm32_i2c_init_s *init)
+{
+ const fdt32_t *cuint;
+
+ cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
+ if (cuint == NULL) {
+ init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
+ } else {
+ init->rise_time = fdt32_to_cpu(*cuint);
+ }
+
+ cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
+ if (cuint == NULL) {
+ init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
+ } else {
+ init->fall_time = fdt32_to_cpu(*cuint);
+ }
+
+ cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
+ if (cuint == NULL) {
+ init->speed_mode = STM32_I2C_SPEED_DEFAULT;
+ } else {
+ switch (fdt32_to_cpu(*cuint)) {
+ case STANDARD_RATE:
+ init->speed_mode = I2C_SPEED_STANDARD;
+ break;
+ case FAST_RATE:
+ init->speed_mode = I2C_SPEED_FAST;
+ break;
+ case FAST_PLUS_RATE:
+ init->speed_mode = I2C_SPEED_FAST_PLUS;
+ break;
+ default:
+ init->speed_mode = STM32_I2C_SPEED_DEFAULT;
+ break;
+ }
+ }
+
+ return dt_set_pinctrl_config(node);
+}
+
+/*
+ * @brief Initialize the I2C device.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param init_data: Initialization configuration structure
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_init(struct i2c_handle_s *hi2c,
+ struct stm32_i2c_init_s *init_data)
+{
+ int rc = 0;
+ uint32_t timing;
+
+ if (hi2c == NULL) {
+ return -ENOENT;
+ }
+
+ if (hi2c->i2c_state == I2C_STATE_RESET) {
+ hi2c->lock = 0;
+ }
+
+ hi2c->i2c_state = I2C_STATE_BUSY;
+
+ rc = i2c_setup_timing(hi2c, init_data, &timing);
+ if (rc != 0) {
+ return rc;
+ }
+
+ stm32mp_clk_enable(hi2c->clock);
+
+ /* Disable the selected I2C peripheral */
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+ /* Configure I2Cx: Frequency range */
+ mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
+ timing & TIMINGR_CLEAR_MASK);
+
+ /* Disable Own Address1 before set the Own Address1 configuration */
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
+
+ /* Configure I2Cx: Own Address1 and ack own address1 mode */
+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
+ I2C_OAR1_OA1EN | init_data->own_address1);
+ } else { /* I2C_ADDRESSINGMODE_10BIT */
+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
+ I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
+ init_data->own_address1);
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0);
+
+ /* Configure I2Cx: Addressing Master mode */
+ if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
+ }
+
+ /*
+ * Enable the AUTOEND by default, and enable NACK
+ * (should be disabled only during Slave process).
+ */
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
+ I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+ /* Disable Own Address2 before set the Own Address2 configuration */
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
+
+ /* Configure I2Cx: Dual mode and Own Address2 */
+ mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
+ init_data->dual_address_mode |
+ init_data->own_address2 |
+ (init_data->own_address2_masks << 8));
+
+ /* Configure I2Cx: Generalcall and NoStretch mode */
+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
+ init_data->general_call_mode |
+ init_data->no_stretch_mode);
+
+ /* Enable the selected I2C peripheral */
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
+
+ hi2c->i2c_err = I2C_ERROR_NONE;
+ hi2c->i2c_state = I2C_STATE_READY;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+
+ rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ?
+ I2C_ANALOGFILTER_ENABLE :
+ I2C_ANALOGFILTER_DISABLE);
+ if (rc != 0) {
+ ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
+ stm32mp_clk_disable(hi2c->clock);
+ return rc;
+ }
+
+ stm32mp_clk_disable(hi2c->clock);
+
+ return rc;
+}
+
+/*
+ * @brief Generic function to write an amount of data in blocking mode
+ * (for Memory Mode and Master Mode)
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address (if Memory Mode)
+ * @param mem_add_size: Size of internal memory address (if Memory Mode)
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @param mode: Communication mode
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
+ enum i2c_mode_e mode)
+{
+ uint64_t tick_start;
+ uint64_t tick_to = ms2tick(timeout_ms);
+ int rc = -EIO;
+ uint8_t *p_buff = p_data;
+ uint32_t xfer_size;
+ uint32_t xfer_count = size;
+
+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
+ return -1;
+ }
+
+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+ return -EBUSY;
+ }
+
+ if ((p_data == NULL) || (size == 0U)) {
+ return -EINVAL;
+ }
+
+ stm32mp_clk_enable(hi2c->clock);
+
+ hi2c->lock = 1;
+
+ tick_start = timeout_start();
+
+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS),
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ hi2c->i2c_state = I2C_STATE_BUSY_TX;
+ hi2c->i2c_mode = mode;
+ hi2c->i2c_err = I2C_ERROR_NONE;
+
+ if (mode == I2C_MODE_MEM) {
+ /* In Memory Mode, Send Slave Address and Memory Address */
+ if (i2c_request_memory_write(hi2c, dev_addr,
+ mem_addr, mem_add_size,
+ tick_to, tick_start) != 0) {
+ goto bail;
+ }
+
+ if (xfer_count > MAX_NBYTE_SIZE) {
+ xfer_size = MAX_NBYTE_SIZE;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ } else {
+ xfer_size = xfer_count;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ } else {
+ /* In Master Mode, Send Slave Address */
+ if (xfer_count > MAX_NBYTE_SIZE) {
+ xfer_size = MAX_NBYTE_SIZE;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_RELOAD_MODE,
+ I2C_GENERATE_START_WRITE);
+ } else {
+ xfer_size = xfer_count;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_WRITE);
+ }
+ }
+
+ do {
+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff);
+ p_buff++;
+ xfer_count--;
+ xfer_size--;
+
+ if ((xfer_count != 0U) && (xfer_size == 0U)) {
+ /* Wait until TCR flag is set */
+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ if (xfer_count > MAX_NBYTE_SIZE) {
+ xfer_size = MAX_NBYTE_SIZE;
+ i2c_transfer_config(hi2c, dev_addr,
+ xfer_size,
+ I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ } else {
+ xfer_size = xfer_count;
+ i2c_transfer_config(hi2c, dev_addr,
+ xfer_size,
+ I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+
+ } while (xfer_count > 0U);
+
+ /*
+ * No need to Check TC flag, with AUTOEND mode the stop
+ * is automatically generated.
+ * Wait until STOPF flag is reset.
+ */
+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+ hi2c->i2c_state = I2C_STATE_READY;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+
+ rc = 0;
+
+bail:
+ hi2c->lock = 0;
+ stm32mp_clk_disable(hi2c->clock);
+
+ return rc;
+}
+
+/*
+ * @brief Write an amount of data in blocking mode to a specific memory
+ * address.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address
+ * @param mem_add_size: Size of internal memory address
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
+{
+ return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size,
+ p_data, size, timeout_ms, I2C_MODE_MEM);
+}
+
+/*
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint8_t *p_data, uint16_t size,
+ uint32_t timeout_ms)
+{
+ return i2c_write(hi2c, dev_addr, 0, 0,
+ p_data, size, timeout_ms, I2C_MODE_MASTER);
+}
+
+/*
+ * @brief Generic function to read an amount of data in blocking mode
+ * (for Memory Mode and Master Mode)
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address (if Memory Mode)
+ * @param mem_add_size: Size of internal memory address (if Memory Mode)
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @param mode: Communication mode
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
+ enum i2c_mode_e mode)
+{
+ uint64_t tick_start;
+ uint64_t tick_to = ms2tick(timeout_ms);
+ int rc = -EIO;
+ uint8_t *p_buff = p_data;
+ uint32_t xfer_count = size;
+ uint32_t xfer_size;
+
+ if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
+ return -1;
+ }
+
+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+ return -EBUSY;
+ }
+
+ if ((p_data == NULL) || (size == 0U)) {
+ return -EINVAL;
+ }
+
+ stm32mp_clk_enable(hi2c->clock);
+
+ hi2c->lock = 1;
+
+ tick_start = timeout_start();
+ if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, ms2tick(I2C_TIMEOUT_BUSY_MS),
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ hi2c->i2c_state = I2C_STATE_BUSY_RX;
+ hi2c->i2c_mode = mode;
+ hi2c->i2c_err = I2C_ERROR_NONE;
+
+ if (mode == I2C_MODE_MEM) {
+ /* Send Memory Address */
+ if (i2c_request_memory_read(hi2c, dev_addr,
+ mem_addr, mem_add_size,
+ tick_to, tick_start) != 0) {
+ goto bail;
+ }
+ }
+
+ /*
+ * Send Slave Address.
+ * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
+ * and generate RESTART.
+ */
+ if (xfer_count > MAX_NBYTE_SIZE) {
+ xfer_size = MAX_NBYTE_SIZE;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ } else {
+ xfer_size = xfer_count;
+ i2c_transfer_config(hi2c, dev_addr, xfer_size,
+ I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ do {
+ if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
+ p_buff++;
+ xfer_size--;
+ xfer_count--;
+
+ if ((xfer_count != 0U) && (xfer_size == 0U)) {
+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ if (xfer_count > MAX_NBYTE_SIZE) {
+ xfer_size = MAX_NBYTE_SIZE;
+ i2c_transfer_config(hi2c, dev_addr,
+ xfer_size,
+ I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ } else {
+ xfer_size = xfer_count;
+ i2c_transfer_config(hi2c, dev_addr,
+ xfer_size,
+ I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ } while (xfer_count > 0U);
+
+ /*
+ * No need to Check TC flag, with AUTOEND mode the stop
+ * is automatically generated.
+ * Wait until STOPF flag is reset.
+ */
+ if (i2c_wait_stop(hi2c, tick_to, tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+ hi2c->i2c_state = I2C_STATE_READY;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+
+ rc = 0;
+
+bail:
+ hi2c->lock = 0;
+ stm32mp_clk_disable(hi2c->clock);
+
+ return rc;
+}
+
+/*
+ * @brief Read an amount of data in blocking mode from a specific memory
+ * address.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address
+ * @param mem_add_size: Size of internal memory address
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
+{
+ return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size,
+ p_data, size, timeout_ms, I2C_MODE_MEM);
+}
+
+/*
+ * @brief Receives in master mode an amount of data in blocking mode.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param p_data: Pointer to data buffer
+ * @param size: Amount of data to be sent
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @retval 0 if OK, negative value else
+ */
+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint8_t *p_data, uint16_t size,
+ uint32_t timeout_ms)
+{
+ return i2c_read(hi2c, dev_addr, 0, 0,
+ p_data, size, timeout_ms, I2C_MODE_MASTER);
+}
+
+/*
+ * @brief Checks if target device is ready for communication.
+ * @note This function is used with Memory devices
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param trials: Number of trials
+ * @param timeout_ms: Timeout duration in milliseconds
+ * @retval True if device is ready, false else
+ */
+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
+ uint16_t dev_addr, uint32_t trials,
+ uint32_t timeout_ms)
+{
+ uint32_t i2c_trials = 0U;
+ bool rc = false;
+ uint64_t tick_to = ms2tick(timeout_ms);
+
+ if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
+ return rc;
+ }
+
+ stm32mp_clk_enable(hi2c->clock);
+
+ hi2c->lock = 1;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
+ 0U) {
+ goto bail;
+ }
+
+ hi2c->i2c_state = I2C_STATE_BUSY;
+ hi2c->i2c_err = I2C_ERROR_NONE;
+
+ do {
+ uint64_t tick_start;
+
+ /* Generate Start */
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) &
+ I2C_OAR1_OA1MODE) == 0) {
+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
+ (((uint32_t)dev_addr & I2C_CR2_SADD) |
+ I2C_CR2_START | I2C_CR2_AUTOEND) &
+ ~I2C_CR2_RD_WRN);
+ } else {
+ mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
+ (((uint32_t)dev_addr & I2C_CR2_SADD) |
+ I2C_CR2_START | I2C_CR2_ADD10) &
+ ~I2C_CR2_RD_WRN);
+ }
+
+ /*
+ * No need to Check TC flag, with AUTOEND mode the stop
+ * is automatically generated.
+ * Wait until STOPF flag is set or a NACK flag is set.
+ */
+ tick_start = timeout_start();
+ do {
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+ (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) {
+ break;
+ }
+
+ if (timeout_elapsed(tick_start, tick_to)) {
+ notif_i2c_timeout(hi2c);
+ goto bail;
+ }
+ } while (true);
+
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+ I2C_FLAG_AF) == 0U) {
+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
+ I2C_FLAG_STOPF);
+
+ hi2c->i2c_state = I2C_STATE_READY;
+
+ rc = true;
+ goto bail;
+ }
+
+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+ if (i2c_trials == trials) {
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
+ I2C_CR2_STOP);
+
+ if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, tick_to,
+ tick_start) != 0) {
+ goto bail;
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
+ I2C_FLAG_STOPF);
+ }
+
+ i2c_trials++;
+ } while (i2c_trials < trials);
+
+ notif_i2c_timeout(hi2c);
+
+bail:
+ hi2c->lock = 0;
+ stm32mp_clk_disable(hi2c->clock);
+
+ return rc;
+}
+
+/*
+ * @brief Master sends target device address followed by internal memory
+ * address for write request.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address
+ * @param mem_add_size: Size of internal memory address
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
+ uint16_t dev_addr, uint16_t mem_addr,
+ uint16_t mem_add_size, uint64_t tick_to,
+ uint64_t tick_start)
+{
+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
+ I2C_GENERATE_START_WRITE);
+
+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
+ /* Send Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)(mem_addr & 0x00FFU));
+ } else {
+ /* Send MSB of Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)((mem_addr & 0xFF00U) >> 8));
+
+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ /* Send LSB of Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)(mem_addr & 0x00FFU));
+ }
+
+ if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * @brief Master sends target device address followed by internal memory
+ * address for read request.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param dev_addr: Target device address
+ * @param mem_addr: Internal memory address
+ * @param mem_add_size: Size of internal memory address
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t mem_addr, uint16_t mem_add_size,
+ uint64_t tick_to, uint64_t tick_start)
+{
+ i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
+ I2C_GENERATE_START_WRITE);
+
+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
+ /* Send Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)(mem_addr & 0x00FFU));
+ } else {
+ /* Send MSB of Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)((mem_addr & 0xFF00U) >> 8));
+
+ if (i2c_wait_txis(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ /* Send LSB of Memory Address */
+ mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
+ (uint8_t)(mem_addr & 0x00FFU));
+ }
+
+ if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * @brief I2C Tx data register flush process.
+ * @param hi2c: I2C handle
+ * @retval None
+ */
+static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
+{
+ /*
+ * If a pending TXIS flag is set,
+ * write a dummy data in TXDR to clear it.
+ */
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
+ 0U) {
+ mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
+ }
+
+ /* Flush TX register if not empty */
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
+ 0U) {
+ mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
+ I2C_FLAG_TXE);
+ }
+}
+
+/*
+ * @brief This function handles I2C Communication timeout.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param flag: Specifies the I2C flag to check
+ * @param awaited_value: The awaited bit value for the flag (0 or 1)
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
+ uint8_t awaited_value, uint64_t tick_to,
+ uint64_t tick_start)
+{
+ for ( ; ; ) {
+ uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR);
+
+ if (!!(isr & flag) != !!awaited_value) {
+ return 0;
+ }
+
+ if (timeout_elapsed(tick_start, tick_to)) {
+ notif_i2c_timeout(hi2c);
+ hi2c->lock = 0;
+
+ return -EIO;
+ }
+ }
+}
+
+/*
+ * @brief This function handles I2C Communication timeout for specific usage
+ * of TXIS flag.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t tick_to,
+ uint64_t tick_start)
+{
+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+ I2C_FLAG_TXIS) == 0U) {
+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ if (timeout_elapsed(tick_start, tick_to)) {
+ notif_i2c_timeout(hi2c);
+ hi2c->lock = 0;
+
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * @brief This function handles I2C Communication timeout for specific
+ * usage of STOP flag.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t tick_to,
+ uint64_t tick_start)
+{
+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+ I2C_FLAG_STOPF) == 0U) {
+ if (i2c_ack_failed(hi2c, tick_to, tick_start) != 0) {
+ return -EIO;
+ }
+
+ if (timeout_elapsed(tick_start, tick_to)) {
+ notif_i2c_timeout(hi2c);
+ hi2c->lock = 0;
+
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * @brief This function handles Acknowledge failed detection during
+ * an I2C Communication.
+ * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
+ * the configuration information for the specified I2C.
+ * @param tick_to: Tick timeout duration
+ * @param tick_start: Tick start value
+ * @retval 0 if OK, negative value else
+ */
+static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t tick_to,
+ uint64_t tick_start)
+{
+ if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
+ return 0;
+ }
+
+ /*
+ * Wait until STOP Flag is reset.
+ * AutoEnd should be initiate after AF.
+ */
+ while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
+ I2C_FLAG_STOPF) == 0U) {
+ if (timeout_elapsed(tick_start, tick_to)) {
+ notif_i2c_timeout(hi2c);
+ hi2c->lock = 0;
+
+ return -EIO;
+ }
+ }
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
+
+ mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
+
+ i2c_flush_txdr(hi2c);
+
+ mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
+
+ hi2c->i2c_err |= I2C_ERROR_AF;
+ hi2c->i2c_state = I2C_STATE_READY;
+ hi2c->i2c_mode = I2C_MODE_NONE;
+
+ hi2c->lock = 0;
+
+ return -EIO;
+}
+
+/*
+ * @brief Handles I2Cx communication when starting transfer or during transfer
+ * (TC or TCR flag are set).
+ * @param hi2c: I2C handle
+ * @param dev_addr: Specifies the slave address to be programmed
+ * @param size: Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param i2c_mode: New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE: Enable Reload mode.
+ * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
+ * @param request: New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP: Generate stop condition
+ * (size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
+ * @retval None
+ */
+static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint16_t size, uint32_t i2c_mode,
+ uint32_t request)
+{
+ uint32_t clr_value, set_value;
+
+ clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
+ I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
+ (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
+
+ set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
+ (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
+ i2c_mode | request;
+
+ mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
+}
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
new file mode 100644
index 0000000..bc9a91a
--- /dev/null
+++ b/drivers/st/io/io_mmc.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_driver.h>
+#include <io_mmc.h>
+#include <io_storage.h>
+#include <mmc.h>
+#include <stm32_sdmmc2.h>
+#include <string.h>
+
+/* SDMMC device functions */
+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
+static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity);
+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int mmc_block_seek(io_entity_t *entity, int mode,
+ signed long long offset);
+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+ size_t *length_read);
+static int mmc_block_close(io_entity_t *entity);
+static int mmc_dev_close(io_dev_info_t *dev_info);
+static io_type_t device_type_mmc(void);
+
+static int64_t seek_offset;
+
+static const io_dev_connector_t mmc_dev_connector = {
+ .dev_open = mmc_dev_open
+};
+
+static const io_dev_funcs_t mmc_dev_funcs = {
+ .type = device_type_mmc,
+ .open = mmc_block_open,
+ .seek = mmc_block_seek,
+ .size = NULL,
+ .read = mmc_block_read,
+ .write = NULL,
+ .close = mmc_block_close,
+ .dev_init = mmc_dev_init,
+ .dev_close = mmc_dev_close,
+};
+
+static const io_dev_info_t mmc_dev_info = {
+ .funcs = &mmc_dev_funcs,
+ .info = 0,
+};
+
+/* Identify the device type as mmc device */
+static io_type_t device_type_mmc(void)
+{
+ return IO_TYPE_MMC;
+}
+
+/* Open a connection to the mmc device */
+static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
+{
+ assert(dev_info != NULL);
+ *dev_info = (io_dev_info_t *)&mmc_dev_info;
+
+ return 0;
+}
+
+static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+ return 0;
+}
+
+/* Close a connection to the mmc device */
+static int mmc_dev_close(io_dev_info_t *dev_info)
+{
+ return 0;
+}
+
+/* Open a file on the mmc device */
+static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity)
+{
+ seek_offset = 0;
+ return 0;
+}
+
+/* Seek to a particular file offset on the mmc device */
+static int mmc_block_seek(io_entity_t *entity, int mode,
+ signed long long offset)
+{
+ seek_offset = offset;
+ return 0;
+}
+
+/* Read data from a file on the mmc device */
+static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint8_t retries = 3U;
+
+ do {
+ retries--;
+ if (retries == 0U) {
+ return -EIO;
+ }
+
+ *length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
+ buffer, length);
+
+ } while (*length_read != length);
+
+ return 0;
+}
+
+/* Close a file on the mmc device */
+static int mmc_block_close(io_entity_t *entity)
+{
+ return 0;
+}
+
+/* Register the mmc driver with the IO abstraction */
+int register_io_dev_mmc(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con != NULL);
+
+ result = io_register_device(&mmc_dev_info);
+ if (result == 0) {
+ *dev_con = &mmc_dev_connector;
+ }
+
+ return result;
+}
diff --git a/drivers/st/io/io_programmer_st_usb.c b/drivers/st/io/io_programmer_st_usb.c
new file mode 100644
index 0000000..a0871f6
--- /dev/null
+++ b/drivers/st/io/io_programmer_st_usb.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_programmer.h>
+#include <io_programmer_st_usb.h>
+#include <io_stm32image.h>
+#include <io_storage.h>
+#include <platform_def.h>
+#include <stm32_iwdg.h>
+#include <stm32mp_auth.h>
+#include <stm32mp_dt.h>
+#include <string.h>
+#include <usb_ctx.h>
+#include <usb_st_dfu.h>
+
+static uint8_t first_usb_buffer[USB_DFU_MAX_XFER_SIZE + 1] __aligned(4);
+static usb_dfu_media_t usb_dfu_fops;
+static uint8_t checksum_is_wrong;
+static uint8_t usb_status;
+
+#define USB_STATE_READY 0
+#define USB_STATE_WRITTEN 1
+
+/* usb device functions */
+static int usb_dev_open(const uintptr_t init_params,
+ io_dev_info_t **dev_info);
+static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity);
+static int usb_dev_init(io_dev_info_t *dev_info,
+ const uintptr_t init_params);
+static int usb_partition_size(io_entity_t *entity, size_t *length);
+static int usb_block_seek(io_entity_t *entity, int mode,
+ signed long long offset);
+static int usb_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read);
+static int usb_block_close(io_entity_t *entity);
+static int usb_dev_close(io_dev_info_t *dev_info);
+static io_type_t device_type_usb(void);
+
+static const io_dev_connector_t usb_dev_connector = {
+ .dev_open = usb_dev_open
+};
+
+static const io_dev_funcs_t usb_dev_funcs = {
+ .type = device_type_usb,
+ .open = usb_block_open,
+ .seek = usb_block_seek,
+ .size = usb_partition_size,
+ .read = usb_block_read,
+ .write = NULL,
+ .close = usb_block_close,
+ .dev_init = usb_dev_init,
+ .dev_close = usb_dev_close,
+};
+
+static io_dev_info_t usb_dev_info = {
+ .funcs = &usb_dev_funcs,
+ .info = (uintptr_t)0,
+};
+
+/* Identify the device type as usb */
+static io_type_t device_type_usb(void)
+{
+ return IO_TYPE_USB;
+}
+
+/* Callback to notify that data has been written in memory
+ * ( set by USBD_DFU_SetDownloadAddr)
+ */
+static uint16_t usb_callback_write_done(uint32_t *written_in, uint32_t len)
+{
+ VERBOSE("%s Written_in 0x%lx len %i\n", __func__, (uintptr_t)written_in,
+ len);
+
+ /* Update SRAM state machine when block writing is finished */
+ usb_status = USB_STATE_WRITTEN;
+
+ return 0;
+}
+
+/* Call back to notify that a read memory is requested */
+static uint8_t *usb_callback_read(uint8_t *src, uint8_t *dest, uint32_t len)
+{
+ ERROR("%s read is not supported src 0x%lx dest 0x%lx len %i\n",
+ __func__, (uintptr_t)src, (uintptr_t)dest, len);
+
+ /* Return a valid address to avoid HardFault */
+ return (uint8_t *)(dest);
+}
+
+/* Get the status to know if written operation has been checked */
+static uint16_t usb_callback_get_status(void)
+{
+ uint16_t status;
+
+ /* According to SRAM state machine */
+ switch (usb_status) {
+ case USB_STATE_WRITTEN:
+ /* The SRAM bloc writing has been done, change state machine
+ * to set SRAM in SRAM_STATE_READY
+ */
+ usb_status = USB_STATE_READY;
+
+ /* Notice caller that SRAM block writing is finished */
+ status = DFU_MEDIA_STATE_WRITTEN;
+
+ /* Checks checksum calculation result */
+ if (checksum_is_wrong == 1) {
+ status = DFU_MEDIA_STATE_ERROR;
+ checksum_is_wrong = 0;
+ }
+ break;
+
+ case USB_STATE_READY:
+ /* Notice caller that SRAM is ready to be written */
+ status = DFU_MEDIA_STATE_READY;
+ break;
+
+ default:
+ status = DFU_MEDIA_STATE_ERROR;
+ ERROR("USB unknown state\n");
+ break;
+ }
+ VERBOSE("usb_callback_GetStatus status : %i\n", status);
+ return status;
+}
+
+/* Open a connection to the usb device */
+static int usb_dev_open(const uintptr_t init_params,
+ io_dev_info_t **dev_info)
+{
+ usb_handle_t *usb_core_handle = (usb_handle_t *)init_params;
+
+ assert(dev_info);
+ *dev_info = &usb_dev_info;
+
+ usb_dfu_fops.write_done = usb_callback_write_done;
+ usb_dfu_fops.read = usb_callback_read;
+ usb_dfu_fops.get_status = usb_callback_get_status;
+ usb_status = USB_STATE_READY;
+ checksum_is_wrong = 0;
+
+ usb_core_handle->user_data = &usb_dfu_fops;
+
+ usb_dev_info.info = (uintptr_t)usb_core_handle;
+
+ return 0;
+}
+
+static int usb_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+ return 0;
+}
+
+/* Close a connection to the usb device */
+static int usb_dev_close(io_dev_info_t *dev_info)
+{
+ return 0;
+}
+
+/* Open a file on the usb device */
+static int usb_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity)
+{
+ int result;
+ uint32_t length = 0;
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)first_usb_buffer;
+
+ const struct stm32image_part_info *partition_spec =
+ (struct stm32image_part_info *)spec;
+
+ /* Use PHASE_FSBL1 like init value*/
+ if (current_phase.phase_id == PHASE_FSBL1) {
+ assert(partition_spec);
+ assert(entity);
+
+ current_phase.current_packet = 0;
+
+ if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) {
+ /* read flash layout first for U-boot */
+ current_phase.phase_id = PHASE_FLASHLAYOUT;
+ current_phase.keep_header = 1;
+
+ usb_dfu_set_phase_id(PHASE_FLASHLAYOUT);
+ usb_dfu_set_download_addr((uintptr_t)
+ &first_usb_buffer[0]);
+
+ header->magic = 0;
+
+ while (((header->magic !=
+ BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
+ usb_dfu_get_current_req() == DFU_DNLOAD)) {
+ usb_core_handle_it((usb_handle_t *)
+ usb_dev_info.info);
+ }
+ result = usb_block_read(NULL,
+ FLASHLAYOUT_BASE,
+ 0,
+ &length);
+ if (result != 0) {
+ return result;
+ }
+
+ flush_dcache_range((unsigned long)FLASHLAYOUT_BASE,
+ header->image_length +
+ sizeof(boot_api_image_header_t));
+
+ current_phase.current_packet = 0;
+ current_phase.keep_header = 0;
+ current_phase.phase_id = PHASE_SSBL;
+ current_phase.max_size = dt_get_ddr_size();
+ }
+ entity->info = (uintptr_t)&current_phase;
+ result = 0;
+ } else {
+ WARN("A UART device is already active. Close first.\n");
+ result = -EIO;
+ }
+
+ return result;
+}
+
+/* Return the size of a partition */
+static int usb_partition_size(io_entity_t *entity, size_t *length)
+{
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)first_usb_buffer;
+ int result = 0;
+
+ usb_dfu_set_phase_id(current_phase.phase_id);
+ usb_dfu_set_download_addr((uintptr_t)&first_usb_buffer[0]);
+
+ header->magic = 0;
+
+ while ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
+ (usb_dfu_get_current_req() == DFU_DNLOAD)) {
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+ }
+
+ if (header->image_length > current_phase.max_size)
+ result = -EIO;
+ else
+ *length = header->image_length;
+
+ INFO("%s: partition size : 0x%x\n", __func__,
+ header->image_length);
+
+ return result;
+}
+
+/* Seek to a particular file offset on the usb device */
+static int usb_block_seek(io_entity_t *entity, int mode,
+ signed long long offset)
+{
+ return 0;
+}
+
+/* Read data from a file on the usb device */
+static int usb_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint8_t *local_ptr = (uint8_t *)buffer;
+ int result = 0;
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)first_usb_buffer;
+
+ INFO("Start Download partition %i to address 0x%lx length %i\n",
+ current_phase.phase_id, buffer, length);
+
+ if (current_phase.keep_header) {
+ memcpy((uint8_t *)local_ptr,
+ (uint8_t *)&first_usb_buffer[0],
+ USB_DFU_MAX_XFER_SIZE);
+
+ usb_dfu_set_download_addr((uintptr_t)
+ &local_ptr[USB_DFU_MAX_XFER_SIZE]);
+ } else {
+ memcpy((uint8_t *)local_ptr,
+ (uint8_t *)
+ &first_usb_buffer[sizeof(boot_api_image_header_t)],
+ USB_DFU_MAX_XFER_SIZE -
+ sizeof(boot_api_image_header_t));
+
+ usb_dfu_set_download_addr((uintptr_t)
+ &local_ptr[USB_DFU_MAX_XFER_SIZE -
+ sizeof(boot_api_image_header_t)]);
+ }
+
+ while (!usb_dfu_download_is_completed()) {
+ /* Reload watchdog */
+ stm32_iwdg_refresh(IWDG2_INST);
+
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+ }
+
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+ usb_core_handle_it((usb_handle_t *)usb_dev_info.info);
+
+ if (current_phase.keep_header)
+ local_ptr += sizeof(boot_api_image_header_t);
+
+ /* Verify header and checksum payload */
+ result = check_header(header, (uintptr_t)local_ptr);
+ if (result) {
+ ERROR("Header check failed\n");
+ return result;
+ }
+
+#if defined(AUTHENTICATE_BL33)
+ if (current_phase.phase_id != PHASE_FLASHLAYOUT) {
+ result = check_authentication(header, (uintptr_t)local_ptr);
+ if (result != 0) {
+ ERROR("Authentication failed\n");
+ return result;
+ }
+ }
+#else
+ NOTICE("Authentication disabled: No signature check\n");
+#endif
+
+ /* Wait Detach in case of bl33 */
+ if (current_phase.phase_id == PHASE_SSBL) {
+ uint32_t timeout = IO_USB_TIMEOUT;
+ uint32_t detach_timeout = DETACH_TIMEOUT;
+
+ usb_dfu_set_phase_id(0x0);
+ usb_dfu_set_download_addr(UNDEFINE_DOWN_ADDR);
+ usb_dfu_request_detach();
+ while (timeout && detach_timeout) {
+ usb_core_handle_it((usb_handle_t *)
+ usb_dev_info.info);
+ if (!usb_dfu_detach_req())
+ detach_timeout--;
+ timeout--;
+ }
+ if (!timeout)
+ return -EIO;
+ /* STOP the USB Handler */
+ usb_core_stop((usb_handle_t *)usb_dev_info.info);
+ }
+
+ *length_read = length;
+
+ return 0;
+}
+
+/* Close a file on the usb device */
+static int usb_block_close(io_entity_t *entity)
+{
+ current_phase.phase_id = PHASE_FSBL1;
+
+ return 0;
+}
+
+/* Exported functions */
+
+/* Register the usb driver with the IO abstraction */
+int register_io_dev_usb(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con);
+
+ result = io_register_device(&usb_dev_info);
+ if (!result)
+ *dev_con = &usb_dev_connector;
+
+ return result;
+}
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
new file mode 100644
index 0000000..fde6269
--- /dev/null
+++ b/drivers/st/io/io_stm32image.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_driver.h>
+#include <io_stm32image.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp_auth.h>
+#include <stdint.h>
+#include <string.h>
+#include <utils.h>
+
+static uintptr_t backend_dev_handle;
+static uintptr_t backend_image_spec;
+static uint32_t *stm32_img;
+static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4);
+static struct stm32image_part_info *current_part;
+
+/* STM32 Image driver functions */
+static int stm32image_dev_open(const uintptr_t init_params,
+ io_dev_info_t **dev_info);
+static int stm32image_partition_open(io_dev_info_t *dev_info,
+ const uintptr_t spec, io_entity_t *entity);
+static int stm32image_partition_size(io_entity_t *entity, size_t *length);
+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read);
+static int stm32image_partition_close(io_entity_t *entity);
+static int stm32image_dev_init(io_dev_info_t *dev_info,
+ const uintptr_t init_params);
+static int stm32image_dev_close(io_dev_info_t *dev_info);
+
+/* Identify the device type as a virtual driver */
+static io_type_t device_type_stm32image(void)
+{
+ return IO_TYPE_STM32IMAGE;
+}
+
+static const io_dev_connector_t stm32image_dev_connector = {
+ .dev_open = stm32image_dev_open
+};
+
+static const io_dev_funcs_t stm32image_dev_funcs = {
+ .type = device_type_stm32image,
+ .open = stm32image_partition_open,
+ .size = stm32image_partition_size,
+ .read = stm32image_partition_read,
+ .close = stm32image_partition_close,
+ .dev_init = stm32image_dev_init,
+ .dev_close = stm32image_dev_close,
+};
+
+static io_dev_info_t stm32image_dev_info = {
+ .funcs = &stm32image_dev_funcs,
+ .info = (uintptr_t)0,
+};
+
+static struct stm32image_device_info stm32image_dev;
+
+static int get_part_idx_by_binary_type(uint32_t binary_type)
+{
+ int i;
+
+ for (i = 0; i < STM32_PART_NUM; i++) {
+ if (stm32image_dev.part_info[i].binary_type == binary_type) {
+ return i;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/* Open a connection to the STM32IMAGE device */
+static int stm32image_dev_open(const uintptr_t init_params,
+ io_dev_info_t **dev_info)
+{
+ int i;
+ struct stm32image_device_info *device_info =
+ (struct stm32image_device_info *)init_params;
+
+ assert(dev_info != NULL);
+ *dev_info = (io_dev_info_t *)&stm32image_dev_info;
+
+ stm32image_dev.device_size = device_info->device_size;
+ stm32image_dev.lba_size = device_info->lba_size;
+
+ for (i = 0; i < STM32_PART_NUM; i++) {
+ memcpy(stm32image_dev.part_info[i].name,
+ device_info->part_info[i].name, MAX_PART_NAME_SIZE);
+ stm32image_dev.part_info[i].binary_type =
+ device_info->part_info[i].binary_type;
+ stm32image_dev.part_info[i].part_offset =
+ device_info->part_info[i].part_offset;
+ stm32image_dev.part_info[i].bkp_offset =
+ device_info->part_info[i].bkp_offset;
+ }
+
+ return 0;
+}
+
+/* Do some basic package checks */
+static int stm32image_dev_init(io_dev_info_t *dev_info,
+ const uintptr_t init_params)
+{
+ int result;
+
+ if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) {
+ ERROR("STM32 Image io supports only one session\n");
+ return -ENOMEM;
+ }
+
+ /* Obtain a reference to the image by querying the platform layer */
+ result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle,
+ &backend_image_spec);
+ if (result != 0) {
+ ERROR("STM32 image error (%i)\n", result);
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/* Close a connection to the STM32 Image device */
+static int stm32image_dev_close(io_dev_info_t *dev_info)
+{
+ backend_dev_handle = 0U;
+ backend_image_spec = 0U;
+ stm32_img = NULL;
+
+ return 0;
+}
+
+/* Open a partition */
+static int stm32image_partition_open(io_dev_info_t *dev_info,
+ const uintptr_t spec, io_entity_t *entity)
+{
+ const struct stm32image_part_info *partition_spec;
+ int idx;
+
+ assert(entity != NULL);
+
+ partition_spec = (struct stm32image_part_info *)spec;
+ assert(partition_spec != NULL);
+
+ idx = get_part_idx_by_binary_type(partition_spec->binary_type);
+ if ((idx < 0) || (idx > STM32_PART_NUM)) {
+ ERROR("Wrong partition index (%d)\n", idx);
+ return -EINVAL;
+ }
+
+ current_part = &stm32image_dev.part_info[idx];
+ stm32_img = (uint32_t *)&current_part->part_offset;
+
+ return 0;
+}
+
+/* Return the size of a partition */
+static int stm32image_partition_size(io_entity_t *entity, size_t *length)
+{
+ int result;
+ uintptr_t backend_handle;
+ size_t bytes_read;
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)first_lba_buffer;
+
+ assert(entity != NULL);
+ assert(length != NULL);
+
+ /* Attempt to access the image */
+ result = io_open(backend_dev_handle, backend_image_spec,
+ &backend_handle);
+
+ if (result < 0) {
+ ERROR("%s: io_open (%i)\n", __func__, result);
+ return result;
+ }
+
+ /* Reset magic header value */
+ header->magic = 0;
+
+ while (header->magic == 0U) {
+ result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img);
+ if (result != 0) {
+ ERROR("%s: io_seek (%i)\n", __func__, result);
+ break;
+ }
+
+ result = io_read(backend_handle, (uintptr_t)header,
+ MAX_LBA_SIZE, (size_t *)&bytes_read);
+ if (result != 0) {
+ if (current_part->bkp_offset == 0U) {
+ ERROR("%s: io_read (%i)\n", __func__, result);
+ }
+ header->magic = 0;
+ }
+
+ if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
+ (header->binary_type != current_part->binary_type) ||
+ (header->image_length >= stm32image_dev.device_size)) {
+ VERBOSE("%s: partition %s not found at %x\n",
+ __func__, current_part->name, *stm32_img);
+
+ if (current_part->bkp_offset == 0U) {
+ result = -ENOMEM;
+ break;
+ }
+
+ /* Header not correct, check next offset for backup */
+ *stm32_img += current_part->bkp_offset;
+ if (*stm32_img > stm32image_dev.device_size) {
+ /* No backup found, end of device reached */
+ WARN("%s : partition %s not found\n",
+ __func__, current_part->name);
+ result = -ENOMEM;
+ break;
+ }
+ header->magic = 0;
+ }
+ }
+
+ io_close(backend_handle);
+
+ if (result != 0) {
+ return result;
+ }
+
+ if (header->image_length < stm32image_dev.lba_size) {
+ *length = stm32image_dev.lba_size;
+ } else {
+ *length = header->image_length;
+ }
+
+ INFO("STM32 Image size : %lu\n", (unsigned long)*length);
+
+ return 0;
+}
+
+/* Read data from a partition */
+static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ int result = 0;
+ uint8_t *local_buffer = (uint8_t *)buffer;
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)first_lba_buffer;
+
+ assert(entity != NULL);
+ assert(buffer != 0U);
+ assert(length_read != NULL);
+
+ *length_read = 0U;
+
+ while (*length_read == 0U) {
+ int offset;
+ int local_length;
+ uintptr_t backend_handle;
+
+ if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+ /* Check for backup as image is corrupted */
+ if (current_part->bkp_offset == 0U) {
+ result = -ENOMEM;
+ break;
+ }
+
+ *stm32_img += current_part->bkp_offset;
+ if (*stm32_img >= stm32image_dev.device_size) {
+ /* End of device reached */
+ result = -ENOMEM;
+ break;
+ }
+
+ local_buffer = (uint8_t *)buffer;
+
+ result = stm32image_partition_size(entity, &length);
+ if (result != 0) {
+ break;
+ }
+ }
+
+ /* Part of image already loaded with the header */
+ memcpy(local_buffer, (uint8_t *)first_lba_buffer +
+ sizeof(boot_api_image_header_t),
+ MAX_LBA_SIZE - sizeof(boot_api_image_header_t));
+ local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
+ offset = MAX_LBA_SIZE;
+
+ /* New image length to be read */
+ local_length = round_up(length -
+ ((MAX_LBA_SIZE) -
+ sizeof(boot_api_image_header_t)),
+ stm32image_dev.lba_size);
+
+ if ((header->load_address != 0U) &&
+ (header->load_address != buffer)) {
+ ERROR("Wrong load address\n");
+ panic();
+ }
+
+ result = io_open(backend_dev_handle, backend_image_spec,
+ &backend_handle);
+
+ if (result != 0) {
+ ERROR("%s: io_open (%i)\n", __func__, result);
+ break;
+ }
+
+ result = io_seek(backend_handle, IO_SEEK_SET,
+ *stm32_img + offset);
+
+ if (result != 0) {
+ ERROR("%s: io_seek (%i)\n", __func__, result);
+ *length_read = 0;
+ io_close(backend_handle);
+ break;
+ }
+
+ result = io_read(backend_handle, (uintptr_t)local_buffer,
+ local_length, length_read);
+
+ /* Adding part of size already read from header */
+ *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
+
+ if (result != 0) {
+ ERROR("%s: io_read (%i)\n", __func__, result);
+ *length_read = 0;
+ header->magic = 0;
+ continue;
+ }
+
+ result = check_header(header, buffer);
+ if (result != 0) {
+ ERROR("Header check failed\n");
+ *length_read = 0;
+ header->magic = 0;
+ }
+
+#ifdef AUTHENTICATE_BL33
+ result = check_authentication(header, buffer);
+ if (result != 0) {
+ ERROR("Authentication Failed\n");
+ return result;
+ }
+#else
+ NOTICE("Authentication disabled: No signature check\n");
+#endif
+
+ io_close(backend_handle);
+ }
+
+ return result;
+}
+
+/* Close a partition */
+static int stm32image_partition_close(io_entity_t *entity)
+{
+ current_part = NULL;
+
+ return 0;
+}
+
+/* Register the stm32image driver with the IO abstraction */
+int register_io_dev_stm32image(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con != NULL);
+
+ result = io_register_device(&stm32image_dev_info);
+ if (result == 0) {
+ *dev_con = &stm32image_dev_connector;
+ }
+
+ return result;
+}
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
new file mode 100644
index 0000000..6d91a9f
--- /dev/null
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <gicv2.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32_iwdg.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <string.h>
+#include <utils.h>
+
+/* IWDG Compatibility */
+#define IWDG_COMPAT "st,stm32mp1-iwdg"
+#define IWDG_TIMEOUT_MS U(100)
+
+/* IWDG registers offsets */
+#define IWDG_KR_OFFSET 0x00U
+#define IWDG_PR_OFFSET 0x04U
+#define IWDG_RLR_OFFSET 0x08U
+#define IWDG_SR_OFFSET 0x0CU
+#define IWDG_EWCR_OFFSET 0x14U
+
+/* Registers values */
+#define IWDG_KR_ACCESS_KEY 0x5555
+#define IWDG_KR_RELOAD_KEY 0xAAAA
+#define IWDG_KR_START_KEY 0xCCCC
+
+#define IWDG_PR_DIV_4 0x00
+#define IWDG_PR_DIV_256 0x06
+
+#define IWDG_RLR_MAX_VAL 0xFFF
+
+#define IWDG_SR_EWU BIT(3)
+
+#define IWDG_EWCR_EWIE BIT(15)
+#define IWDG_EWCR_EWIC BIT(14)
+#define IWDG_EWCR_EWIT_MASK GENMASK(11, 0)
+
+struct stm32_iwdg_instance {
+ uintptr_t base;
+ unsigned long clock;
+ uint8_t flags;
+ int num_irq;
+};
+
+static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE];
+
+static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset)
+{
+ int node;
+
+ node = dt_get_node(info, offset, IWDG_COMPAT);
+ if (node < 0) {
+ if (offset == -1) {
+ VERBOSE("%s: No IDWG found\n", __func__);
+ }
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return node;
+}
+
+#if defined(IMAGE_BL32)
+void __dead2 stm32_iwdg_it_handler(int id)
+{
+ unsigned int cpu = plat_my_core_pos();
+ struct stm32_iwdg_instance *iwdg;
+ unsigned int instance;
+
+ for (instance = 0; instance < IWDG_MAX_INSTANCE; instance++) {
+ if (stm32_iwdg[instance].num_irq == id) {
+ break;
+ }
+ }
+
+ if (instance == IWDG_MAX_INSTANCE) {
+ panic();
+ }
+
+ iwdg = &stm32_iwdg[instance];
+
+ VERBOSE("CPU %x IT Watchdog %d\n", cpu, instance + 1);
+
+ stm32_iwdg_refresh(instance);
+
+ stm32mp_clk_enable(iwdg->clock);
+
+ mmio_setbits_32(iwdg->base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIC);
+
+ stm32mp_clk_disable(iwdg->clock);
+
+ /* Ack interrupt as we do not return from next call */
+ gicv2_end_of_interrupt(id);
+
+ stm32mp_plat_reset(cpu);
+}
+
+static int stm32_iwdg_get_secure_timeout(int node)
+{
+ void *fdt;
+ const fdt32_t *cuint;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -1;
+ }
+
+ cuint = fdt_getprop(fdt, node, "secure-timeout-sec", NULL);
+ if (cuint == NULL) {
+ return -1;
+ }
+
+ return (int)fdt32_to_cpu(*cuint);
+}
+
+static int stm32_iwdg_conf_etimeout(int node, struct stm32_iwdg_instance *iwdg)
+{
+ int id_lsi;
+ int dt_secure_timeout = stm32_iwdg_get_secure_timeout(node);
+ uint32_t reload, status;
+ unsigned int timeout = IWDG_TIMEOUT_MS;
+ unsigned long long reload_ll;
+
+ if (dt_secure_timeout < 0) {
+ return 0;
+ }
+
+ if (dt_secure_timeout == 0) {
+ return -EINVAL;
+ }
+
+ id_lsi = fdt_get_clock_id_by_name(node, "lsi");
+ if (id_lsi < 0) {
+ return -EINVAL;
+ }
+
+ /* Prescaler fix to 256 */
+ reload_ll = (unsigned long long)dt_secure_timeout *
+ stm32mp_clk_get_rate(id_lsi);
+ reload = ((uint32_t)(reload_ll >> 8) - 1U) & IWDG_EWCR_EWIT_MASK;
+
+ stm32mp_clk_enable(iwdg->clock);
+
+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_START_KEY);
+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY);
+ mmio_write_32(iwdg->base + IWDG_PR_OFFSET, IWDG_PR_DIV_256);
+ mmio_write_32(iwdg->base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIE | reload);
+
+ do {
+ status = mmio_read_32(iwdg->base + IWDG_SR_OFFSET) &
+ IWDG_SR_EWU;
+ timeout--;
+ mdelay(1);
+ } while ((status != 0U) && (timeout != 0U));
+
+ iwdg->num_irq = stm32_gic_enable_spi(node, NULL);
+ if (iwdg->num_irq < 0) {
+ panic();
+ }
+
+ stm32mp_clk_disable(iwdg->clock);
+
+ return (timeout == 0U) ? -ETIMEDOUT : 0;
+}
+#endif
+
+void stm32_iwdg_refresh(uint32_t instance)
+{
+ struct stm32_iwdg_instance *iwdg = &stm32_iwdg[instance];
+
+ assert(iwdg);
+
+ stm32mp_clk_enable(iwdg->clock);
+
+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
+
+ stm32mp_clk_disable(iwdg->clock);
+}
+
+int stm32_iwdg_init(void)
+{
+ int node = -1;
+ int __unused res;
+ struct dt_node_info dt_info;
+ void *fdt;
+ uint32_t __unused count = 0;
+ uint32_t idx;
+ uint32_t __unused otp_value;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ for (node = stm32_iwdg_get_dt_node(&dt_info, node);
+ node != -FDT_ERR_NOTFOUND;
+ node = stm32_iwdg_get_dt_node(&dt_info, node)) {
+ struct stm32_iwdg_instance *iwdg;
+ uint32_t hw_init;
+
+ idx = stm32_iwdg_get_instance(dt_info.base);
+ iwdg = &stm32_iwdg[idx];
+ iwdg->base = dt_info.base;
+ iwdg->clock = (unsigned long)dt_info.clock;
+
+ /* DT can specify low power cases */
+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) !=
+ NULL) {
+ iwdg->flags |= IWDG_ENABLE_ON_STOP;
+ }
+
+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) !=
+ NULL) {
+ iwdg->flags |= IWDG_ENABLE_ON_STANDBY;
+ }
+
+ /* Explicit list of supported bit flags */
+ hw_init = stm32_iwdg_get_otp_config(iwdg->base);
+
+ if ((hw_init & IWDG_HW_ENABLED) != 0) {
+ if (dt_info.status == DT_DISABLED) {
+ ERROR("OTP enabled but iwdg%d DT-disabled\n",
+ idx + 1);
+ panic();
+ }
+ iwdg->flags |= IWDG_HW_ENABLED;
+ }
+
+ if (dt_info.status == DT_DISABLED) {
+ zeromem((void *)iwdg,
+ sizeof(struct stm32_iwdg_instance));
+ goto next;
+ }
+
+ if ((hw_init & IWDG_ENABLE_ON_STOP) != 0) {
+ iwdg->flags |= IWDG_ENABLE_ON_STOP;
+ }
+
+ if ((hw_init & IWDG_ENABLE_ON_STANDBY) != 0) {
+ iwdg->flags |= IWDG_ENABLE_ON_STANDBY;
+ }
+
+ VERBOSE("IWDG%u found, %ssecure\n", idx + 1,
+ ((dt_info.status & DT_NON_SECURE) != 0) ?
+ "non " : "");
+
+ if ((dt_info.status & DT_NON_SECURE) != 0) {
+ stm32mp_register_non_secure_periph_iomem(iwdg->base);
+ } else {
+ stm32mp_register_secure_periph_iomem(iwdg->base);
+ }
+
+ stm32mp_clk_enable(iwdg->clock);
+ stm32mp_clk_disable(iwdg->clock);
+
+#if defined(IMAGE_BL32)
+ res = stm32_iwdg_conf_etimeout(node, iwdg);
+ if (res != 0) {
+ ERROR("IWDG%x early timeout config failed (%d)\n",
+ idx + 1, res);
+ return res;
+ }
+#endif
+#if defined(IMAGE_BL2)
+ if (stm32_iwdg_shadow_update(iwdg->base, iwdg->flags) !=
+ BSEC_OK) {
+ return -1;
+ }
+#endif
+
+next:
+ count++;
+ }
+
+ VERBOSE("%u IWDG instance%s found\n", count, count > 1 ? "s" : "");
+
+ return 0;
+}
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
new file mode 100644
index 0000000..620087e
--- /dev/null
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmc.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32_sdmmc2.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_reset.h>
+#include <string.h>
+#include <utils.h>
+
+/* Registers offsets */
+#define SDMMC_POWER 0x00U
+#define SDMMC_CLKCR 0x04U
+#define SDMMC_ARGR 0x08U
+#define SDMMC_CMDR 0x0CU
+#define SDMMC_RESPCMDR 0x10U
+#define SDMMC_RESP1R 0x14U
+#define SDMMC_RESP2R 0x18U
+#define SDMMC_RESP3R 0x1CU
+#define SDMMC_RESP4R 0x20U
+#define SDMMC_DTIMER 0x24U
+#define SDMMC_DLENR 0x28U
+#define SDMMC_DCTRLR 0x2CU
+#define SDMMC_DCNTR 0x30U
+#define SDMMC_STAR 0x34U
+#define SDMMC_ICR 0x38U
+#define SDMMC_MASKR 0x3CU
+#define SDMMC_ACKTIMER 0x40U
+#define SDMMC_IDMACTRLR 0x50U
+#define SDMMC_IDMABSIZER 0x54U
+#define SDMMC_IDMABASE0R 0x58U
+#define SDMMC_IDMABASE1R 0x5CU
+#define SDMMC_FIFOR 0x80U
+
+/* SDMMC power control register */
+#define SDMMC_POWER_PWRCTRL GENMASK(1, 0)
+#define SDMMC_POWER_DIRPOL BIT(4)
+
+/* SDMMC clock control register */
+#define SDMMC_CLKCR_WIDBUS_4 BIT(14)
+#define SDMMC_CLKCR_WIDBUS_8 BIT(15)
+#define SDMMC_CLKCR_NEGEDGE BIT(16)
+#define SDMMC_CLKCR_HWFC_EN BIT(17)
+#define SDMMC_CLKCR_SELCLKRX_0 BIT(20)
+
+/* SDMMC command register */
+#define SDMMC_CMDR_CMDTRANS BIT(6)
+#define SDMMC_CMDR_CMDSTOP BIT(7)
+#define SDMMC_CMDR_WAITRESP GENMASK(9, 8)
+#define SDMMC_CMDR_WAITRESP_SHORT BIT(8)
+#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9)
+#define SDMMC_CMDR_CPSMEN BIT(12)
+
+/* SDMMC data control register */
+#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_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)
+#define SDMMC_STAR_DCRCFAIL BIT(1)
+#define SDMMC_STAR_CTIMEOUT BIT(2)
+#define SDMMC_STAR_DTIMEOUT BIT(3)
+#define SDMMC_STAR_TXUNDERR BIT(4)
+#define SDMMC_STAR_RXOVERR BIT(5)
+#define SDMMC_STAR_CMDREND BIT(6)
+#define SDMMC_STAR_CMDSENT BIT(7)
+#define SDMMC_STAR_DATAEND BIT(8)
+#define SDMMC_STAR_DBCKEND BIT(10)
+#define SDMMC_STAR_DPSMACT BIT(12)
+#define SDMMC_STAR_RXFIFOHF BIT(15)
+#define SDMMC_STAR_RXFIFOE BIT(19)
+#define SDMMC_STAR_IDMATE BIT(27)
+#define SDMMC_STAR_IDMABTC BIT(28)
+
+/* SDMMC DMA control register */
+#define SDMMC_IDMACTRLR_IDMAEN BIT(0)
+
+#define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \
+ SDMMC_STAR_DCRCFAIL | \
+ SDMMC_STAR_CTIMEOUT | \
+ SDMMC_STAR_DTIMEOUT | \
+ SDMMC_STAR_TXUNDERR | \
+ SDMMC_STAR_RXOVERR | \
+ SDMMC_STAR_CMDREND | \
+ SDMMC_STAR_CMDSENT | \
+ SDMMC_STAR_DATAEND | \
+ SDMMC_STAR_DBCKEND | \
+ SDMMC_STAR_IDMATE | \
+ SDMMC_STAR_IDMABTC)
+
+#define TIMEOUT_10_MS ms2tick(10)
+#define TIMEOUT_1_S s2tick(1)
+
+#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
+
+static void stm32_sdmmc2_init(void);
+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd);
+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd);
+static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width);
+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size);
+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size);
+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size);
+
+static const struct mmc_ops stm32_sdmmc2_ops = {
+ .init = stm32_sdmmc2_init,
+ .send_cmd = stm32_sdmmc2_send_cmd,
+ .set_ios = stm32_sdmmc2_set_ios,
+ .prepare = stm32_sdmmc2_prepare,
+ .read = stm32_sdmmc2_read,
+ .write = stm32_sdmmc2_write,
+};
+
+static struct stm32_sdmmc2_params sdmmc2_params;
+
+#pragma weak plat_sdmmc2_use_dma
+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
+{
+ return false;
+}
+
+static void dump_registers(void)
+{
+ uintptr_t base = sdmmc2_params.reg_base;
+
+ INFO("SDMMC_POWER = 0x%x\n", mmio_read_32(base + SDMMC_POWER));
+ INFO("SDMMC_CLKCR = 0x%x\n", mmio_read_32(base + SDMMC_CLKCR));
+ INFO("SDMMC_ARGR = 0x%x\n", mmio_read_32(base + SDMMC_ARGR));
+ INFO("SDMMC_CMDR = 0x%x\n", mmio_read_32(base + SDMMC_CMDR));
+ INFO("SDMMC_RESPCMDR = 0x%x\n", mmio_read_32(base + SDMMC_RESPCMDR));
+ INFO("SDMMC_RESP1R = 0x%x\n", mmio_read_32(base + SDMMC_RESP1R));
+ INFO("SDMMC_RESP2R = 0x%x\n", mmio_read_32(base + SDMMC_RESP2R));
+ INFO("SDMMC_RESP3R = 0x%x\n", mmio_read_32(base + SDMMC_RESP3R));
+ INFO("SDMMC_RESP4R = 0x%x\n", mmio_read_32(base + SDMMC_RESP4R));
+ INFO("SDMMC_DTIMER = 0x%x\n", mmio_read_32(base + SDMMC_DTIMER));
+ INFO("SDMMC_DLENR = 0x%x\n", mmio_read_32(base + SDMMC_DLENR));
+ INFO("SDMMC_DCTRLR = 0x%x\n", mmio_read_32(base + SDMMC_DCTRLR));
+ INFO("SDMMC_DCNTR = 0x%x\n", mmio_read_32(base + SDMMC_DCNTR));
+ INFO("SDMMC_MASKR = 0x%x\n", mmio_read_32(base + SDMMC_MASKR));
+ INFO("SDMMC_ACKTIMER = 0x%x\n", mmio_read_32(base + SDMMC_ACKTIMER));
+}
+
+static void stm32_sdmmc2_init(void)
+{
+ uint32_t clock_div;
+ uintptr_t base = sdmmc2_params.reg_base;
+
+ clock_div = div_round_up(sdmmc2_params.clk_rate,
+ STM32MP_MMC_INIT_FREQ * 2);
+
+ mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
+ sdmmc2_params.negedge |
+ sdmmc2_params.pin_ckin);
+
+ mmio_write_32(base + SDMMC_POWER,
+ SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol);
+
+ mdelay(1);
+}
+
+static int stm32_sdmmc2_stop_transfer(void)
+{
+ struct mmc_cmd cmd_stop;
+
+ zeromem(&cmd_stop, sizeof(struct mmc_cmd));
+
+ cmd_stop.cmd_idx = MMC_CMD(12);
+ cmd_stop.resp_type = MMC_RESPONSE_R1B;
+
+ return stm32_sdmmc2_send_cmd(&cmd_stop);
+}
+
+static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd)
+{
+ uint64_t start;
+ uint32_t flags_cmd, status;
+ uint32_t flags_data = 0;
+ int err = 0;
+ uintptr_t base = sdmmc2_params.reg_base;
+ unsigned int cmd_reg, arg_reg;
+
+ if (cmd == NULL) {
+ return -EINVAL;
+ }
+
+ flags_cmd = SDMMC_STAR_CTIMEOUT;
+ arg_reg = cmd->cmd_arg;
+
+ if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) {
+ mmio_write_32(base + SDMMC_CMDR, 0);
+ }
+
+ cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN;
+
+ if (cmd->resp_type == 0U) {
+ flags_cmd |= SDMMC_STAR_CMDSENT;
+ }
+
+ if ((cmd->resp_type & MMC_RSP_48) != 0U) {
+ if ((cmd->resp_type & MMC_RSP_136) != 0U) {
+ flags_cmd |= SDMMC_STAR_CMDREND;
+ cmd_reg |= SDMMC_CMDR_WAITRESP;
+ } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) {
+ flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL;
+ cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT;
+ } else {
+ flags_cmd |= SDMMC_STAR_CMDREND;
+ cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC;
+ }
+ }
+
+ switch (cmd->cmd_idx) {
+ case MMC_CMD(1):
+ arg_reg |= OCR_POWERUP;
+ break;
+ case MMC_CMD(8):
+ if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
+ cmd_reg |= SDMMC_CMDR_CMDTRANS;
+ }
+ break;
+ case MMC_CMD(12):
+ cmd_reg |= SDMMC_CMDR_CMDSTOP;
+ break;
+ case MMC_CMD(17):
+ case MMC_CMD(18):
+ cmd_reg |= SDMMC_CMDR_CMDTRANS;
+ if (sdmmc2_params.use_dma) {
+ flags_data |= SDMMC_STAR_DCRCFAIL |
+ SDMMC_STAR_DTIMEOUT |
+ SDMMC_STAR_DATAEND |
+ SDMMC_STAR_RXOVERR |
+ SDMMC_STAR_IDMATE;
+ }
+ break;
+ case MMC_ACMD(41):
+ arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4;
+ break;
+ case MMC_ACMD(51):
+ cmd_reg |= SDMMC_CMDR_CMDTRANS;
+ if (sdmmc2_params.use_dma) {
+ flags_data |= SDMMC_STAR_DCRCFAIL |
+ SDMMC_STAR_DTIMEOUT |
+ SDMMC_STAR_DATAEND |
+ SDMMC_STAR_RXOVERR |
+ SDMMC_STAR_IDMATE |
+ SDMMC_STAR_DBCKEND;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
+ mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+ }
+
+ mmio_write_32(base + SDMMC_ARGR, arg_reg);
+
+ mmio_write_32(base + SDMMC_CMDR, cmd_reg);
+
+ status = mmio_read_32(base + SDMMC_STAR);
+
+ start = timeout_start();
+
+ while ((status & flags_cmd) == 0U) {
+ if (timeout_elapsed(start, TIMEOUT_10_MS)) {
+ err = -ETIMEDOUT;
+ ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
+ __func__, cmd->cmd_idx, status);
+ goto err_exit;
+ }
+
+ status = mmio_read_32(base + SDMMC_STAR);
+ }
+
+ if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) {
+ if ((status & SDMMC_STAR_CTIMEOUT) != 0U) {
+ err = -ETIMEDOUT;
+ /*
+ * Those timeouts can occur, and framework will handle
+ * the retries. CMD8 is expected to return this timeout
+ * for eMMC
+ */
+ if (!((cmd->cmd_idx == MMC_CMD(1)) ||
+ (cmd->cmd_idx == MMC_CMD(13)) ||
+ ((cmd->cmd_idx == MMC_CMD(8)) &&
+ (cmd->resp_type == MMC_RESPONSE_R7)))) {
+ ERROR("%s: CTIMEOUT (cmd = %d,status = %x)\n",
+ __func__, cmd->cmd_idx, status);
+ }
+ } else {
+ err = -EIO;
+ ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n",
+ __func__, cmd->cmd_idx, status);
+ }
+
+ goto err_exit;
+ }
+
+ if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) {
+ if ((cmd->cmd_idx == MMC_CMD(9)) &&
+ ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) {
+ /* Need to invert response to match CSD structure */
+ cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R);
+ cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R);
+ cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R);
+ cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R);
+ } else {
+ cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R);
+ if ((cmd_reg & SDMMC_CMDR_WAITRESP) ==
+ SDMMC_CMDR_WAITRESP) {
+ cmd->resp_data[1] = mmio_read_32(base +
+ SDMMC_RESP2R);
+ cmd->resp_data[2] = mmio_read_32(base +
+ SDMMC_RESP3R);
+ cmd->resp_data[3] = mmio_read_32(base +
+ SDMMC_RESP4R);
+ }
+ }
+ }
+
+ if (flags_data == 0U) {
+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+ return 0;
+ }
+
+ status = mmio_read_32(base + SDMMC_STAR);
+
+ start = timeout_start();
+
+ while ((status & flags_data) == 0U) {
+ if (timeout_elapsed(start, TIMEOUT_10_MS)) {
+ ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n",
+ __func__, cmd->cmd_idx, status);
+ err = -ETIMEDOUT;
+ goto err_exit;
+ }
+
+ status = mmio_read_32(base + SDMMC_STAR);
+ };
+
+ if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL |
+ SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR |
+ SDMMC_STAR_IDMATE)) != 0U) {
+ ERROR("%s: Error flag (cmd = %d,status = %x)\n", __func__,
+ cmd->cmd_idx, status);
+ err = -EIO;
+ }
+
+err_exit:
+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+ mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS);
+
+ if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) {
+ int ret_stop = stm32_sdmmc2_stop_transfer();
+
+ if (ret_stop != 0) {
+ return ret_stop;
+ }
+ }
+
+ return err;
+}
+
+static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
+{
+ int8_t retry;
+ int err = 0;
+
+ assert(cmd != NULL);
+
+ for (retry = 0; retry <= 3; retry++) {
+ err = stm32_sdmmc2_send_cmd_req(cmd);
+ if (err == 0) {
+ return err;
+ }
+
+ if ((cmd->cmd_idx == MMC_CMD(1)) ||
+ (cmd->cmd_idx == MMC_CMD(13))) {
+ return 0; /* Retry managed by framework */
+ }
+
+ /* Command 8 is expected to fail for eMMC */
+ if (!(cmd->cmd_idx == MMC_CMD(8))) {
+ WARN(" CMD%d, Retry: %d, Error: %d\n",
+ cmd->cmd_idx, retry, err);
+ }
+
+ udelay(10);
+ }
+
+ return err;
+}
+
+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 clk_rate = sdmmc2_params.clk_rate;
+ uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq;
+
+ switch (width) {
+ case MMC_BUS_WIDTH_1:
+ break;
+ case MMC_BUS_WIDTH_4:
+ bus_cfg |= SDMMC_CLKCR_WIDBUS_4;
+ break;
+ case MMC_BUS_WIDTH_8:
+ bus_cfg |= SDMMC_CLKCR_WIDBUS_8;
+ break;
+ default:
+ panic();
+ break;
+ }
+
+ if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
+ if (max_bus_freq >= 52000000U) {
+ max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ;
+ } else {
+ max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ;
+ }
+ } else {
+ if (max_bus_freq >= 50000000U) {
+ max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ;
+ } else {
+ max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ;
+ }
+ }
+
+ clock_div = div_round_up(clk_rate, max_freq * 2);
+
+ mmio_write_32(base + SDMMC_CLKCR,
+ SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg |
+ sdmmc2_params.negedge |
+ sdmmc2_params.pin_ckin);
+
+ return 0;
+}
+
+static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
+{
+ struct mmc_cmd cmd;
+ int ret;
+ uintptr_t base = sdmmc2_params.reg_base;
+ uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR;
+
+ if (size == 8U) {
+ data_ctrl |= SDMMC_DBLOCKSIZE_8;
+ } else {
+ data_ctrl |= SDMMC_DBLOCKSIZE_512;
+ }
+
+ sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf);
+
+ if (sdmmc2_params.use_dma) {
+ inv_dcache_range(buf, size);
+ }
+
+ /* Prepare CMD 16*/
+ mmio_write_32(base + SDMMC_DTIMER, 0);
+
+ mmio_write_32(base + SDMMC_DLENR, 0);
+
+ mmio_write_32(base + SDMMC_DCTRLR, 0);
+
+ 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.resp_type = MMC_RESPONSE_R1;
+
+ ret = stm32_sdmmc2_send_cmd(&cmd);
+ if (ret != 0) {
+ ERROR("CMD16 failed\n");
+ return ret;
+ }
+
+ /* Prepare data command */
+ mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+
+ mmio_write_32(base + SDMMC_DLENR, size);
+
+ if (sdmmc2_params.use_dma) {
+ mmio_write_32(base + SDMMC_IDMACTRLR,
+ SDMMC_IDMACTRLR_IDMAEN);
+ mmio_write_32(base + SDMMC_IDMABASE0R, buf);
+
+ flush_dcache_range(buf, size);
+ }
+
+ mmio_clrsetbits_32(base + SDMMC_DCTRLR,
+ SDMMC_DCTRLR_CLEAR_MASK,
+ data_ctrl);
+
+ return 0;
+}
+
+static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size)
+{
+ uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL |
+ SDMMC_STAR_DTIMEOUT;
+ uint32_t flags = error_flags | SDMMC_STAR_DATAEND;
+ uint32_t status;
+ uint32_t *buffer;
+ uintptr_t base = sdmmc2_params.reg_base;
+ uintptr_t fifo_reg = base + SDMMC_FIFOR;
+ unsigned int start;
+ int ret;
+
+ /* Assert buf is 4 bytes aligned */
+ assert((buf & GENMASK(1, 0)) == 0U);
+
+ buffer = (uint32_t *)buf;
+
+ if (sdmmc2_params.use_dma) {
+ inv_dcache_range(buf, size);
+
+ return 0;
+ }
+
+ if (size <= MMC_BLOCK_SIZE) {
+ flags |= SDMMC_STAR_DBCKEND;
+ }
+
+ start = timeout_start();
+
+ do {
+ status = mmio_read_32(base + SDMMC_STAR);
+
+ if ((status & error_flags) != 0U) {
+ ERROR("%s: Read error (status = %x)\n", __func__,
+ status);
+ dump_registers();
+ mmio_write_32(base + SDMMC_DCTRLR,
+ SDMMC_DCTRLR_FIFORST);
+
+ mmio_write_32(base + SDMMC_ICR,
+ SDMMC_STATIC_FLAGS);
+
+ ret = stm32_sdmmc2_stop_transfer();
+ if (ret != 0) {
+ return ret;
+ }
+
+ return -EIO;
+ }
+
+ if (timeout_elapsed(start, TIMEOUT_1_S)) {
+ ERROR("%s: timeout 1s (status = %x)\n",
+ __func__, status);
+ dump_registers();
+ mmio_write_32(base + SDMMC_ICR,
+ SDMMC_STATIC_FLAGS);
+
+ ret = stm32_sdmmc2_stop_transfer();
+ if (ret != 0) {
+ return ret;
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ if (size < (8U * sizeof(uint32_t))) {
+ if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) &&
+ ((status & SDMMC_STAR_RXFIFOE) == 0U)) {
+ *buffer = mmio_read_32(fifo_reg);
+ buffer++;
+ }
+ } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) {
+ uint32_t count;
+
+ /* Read data from SDMMC Rx FIFO */
+ for (count = 0; count < 8U; count++) {
+ *buffer = mmio_read_32(fifo_reg);
+ buffer++;
+ }
+ }
+ } while ((status & flags) == 0U);
+
+ mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+ if ((status & SDMMC_STAR_DPSMACT) != 0U) {
+ WARN("%s: DPSMACT=1, send stop\n", __func__);
+ return stm32_sdmmc2_stop_transfer();
+ }
+
+ return 0;
+}
+
+static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size)
+{
+ return 0;
+}
+
+static int stm32_sdmmc2_dt_get_config(void)
+{
+ int sdmmc_node;
+ void *fdt = NULL;
+ const fdt32_t *cuint;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if (fdt == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT);
+
+ while (sdmmc_node != -FDT_ERR_NOTFOUND) {
+ cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) {
+ break;
+ }
+
+ sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node,
+ DT_SDMMC2_COMPAT);
+ }
+
+ if (sdmmc_node == -FDT_ERR_NOTFOUND) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if (fdt_get_status(sdmmc_node) == DT_DISABLED) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if (dt_set_pinctrl_config(sdmmc_node) != 0) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ cuint++;
+ sdmmc2_params.clock_id = fdt32_to_cpu(*cuint);
+
+ cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ cuint++;
+ sdmmc2_params.reset_id = fdt32_to_cpu(*cuint);
+
+ if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) {
+ sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0;
+ }
+
+ if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) {
+ sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL;
+ }
+
+ if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) {
+ sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE;
+ }
+
+ cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL);
+ if (cuint != NULL) {
+ switch (fdt32_to_cpu(*cuint)) {
+ case 4:
+ sdmmc2_params.bus_width = MMC_BUS_WIDTH_4;
+ break;
+
+ case 8:
+ sdmmc2_params.bus_width = MMC_BUS_WIDTH_8;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+unsigned long long stm32_sdmmc2_mmc_get_device_size(void)
+{
+ return sdmmc2_params.device_info->device_size;
+}
+
+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
+{
+ assert((params != NULL) &&
+ ((params->reg_base & MMC_BLOCK_MASK) == 0U) &&
+ ((params->bus_width == MMC_BUS_WIDTH_1) ||
+ (params->bus_width == MMC_BUS_WIDTH_4) ||
+ (params->bus_width == MMC_BUS_WIDTH_8)));
+
+ memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params));
+
+ if (stm32_sdmmc2_dt_get_config() != 0) {
+ ERROR("%s: DT error\n", __func__);
+ return -ENOMEM;
+ }
+
+ stm32mp_clk_enable(sdmmc2_params.clock_id);
+
+ stm32mp_reset_assert(sdmmc2_params.reset_id);
+ udelay(2);
+ stm32mp_reset_deassert(sdmmc2_params.reset_id);
+ mdelay(1);
+
+ sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
+
+ return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
+ sdmmc2_params.bus_width, sdmmc2_params.flags,
+ sdmmc2_params.device_info);
+}
diff --git a/drivers/st/nand/io_nand.c b/drivers/st/nand/io_nand.c
new file mode 100644
index 0000000..54ac8fb
--- /dev/null
+++ b/drivers/st/nand/io_nand.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_nand.h>
+#include <io_storage.h>
+#include <nand.h>
+#include <string.h>
+#include <utils_def.h>
+
+/* NAND device functions */
+static int nand_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
+static int nand_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity);
+static int nand_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int nand_block_seek(io_entity_t *entity, int mode,
+ signed long long offset);
+static int nand_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read);
+static int nand_block_close(io_entity_t *entity);
+static int nand_dev_close(io_dev_info_t *dev_info);
+static io_type_t device_type_nand(void);
+
+static NAND_HandleTypeDef *hnand;
+static uint64_t seek_offset;
+
+static const io_dev_connector_t nand_dev_connector = {
+ .dev_open = nand_dev_open
+};
+
+static const io_dev_funcs_t nand_dev_funcs = {
+ .type = device_type_nand,
+ .open = nand_block_open,
+ .seek = nand_block_seek,
+ .size = NULL,
+ .read = nand_block_read,
+ .write = NULL,
+ .close = nand_block_close,
+ .dev_init = nand_dev_init,
+ .dev_close = nand_dev_close,
+};
+
+static const io_dev_info_t nand_dev_info = {
+ .funcs = &nand_dev_funcs,
+ .info = (uintptr_t)0,
+};
+
+/* Identify the device type as memmap */
+static io_type_t device_type_nand(void)
+{
+ return IO_TYPE_NAND;
+}
+
+/* Open a connection to the nand device */
+static int nand_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
+{
+ uint32_t nb_page_per_block, page_size;
+
+ assert(dev_info);
+ *dev_info = (io_dev_info_t *)&nand_dev_info;
+
+ hnand = (NAND_HandleTypeDef *)init_params;
+
+ if (nand_initialize(hnand) != STD_OK)
+ return -EIO;
+
+ hnand->Info.page_size_shift = 0;
+
+ page_size = hnand->Info.PageSize;
+ if (!IS_POWER_OF_TWO(page_size))
+ return -EINVAL;
+
+ while (page_size >>= 1)
+ hnand->Info.page_size_shift++;
+
+ nb_page_per_block = hnand->Info.BlockSize;
+ if (!IS_POWER_OF_TWO(nb_page_per_block))
+ return -EINVAL;
+
+ /* Block size is (page_size * number of pages per blocks) */
+ hnand->Info.block_size_shift = hnand->Info.page_size_shift;
+ while (nb_page_per_block >>= 1)
+ hnand->Info.block_size_shift++;
+
+ return 0;
+}
+
+static int nand_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+ return 0;
+}
+
+/* Close a connection to the nand device */
+static int nand_dev_close(io_dev_info_t *dev_info)
+{
+ return 0;
+}
+
+/* Open a file on the nand device */
+static int nand_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity)
+{
+ seek_offset = 0;
+ return 0;
+}
+
+/* Seek to a particular file offset on the nand device */
+static int nand_block_seek(io_entity_t *entity, int mode,
+ signed long long offset)
+{
+ seek_offset = offset;
+ return 0;
+}
+
+/* Read data from a file on the nand device */
+static int nand_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint32_t block_size_shift = hnand->Info.block_size_shift;
+ uint32_t page_size_shift = hnand->Info.page_size_shift;
+ uint32_t buffer_index = 0;
+ uint32_t num_sectors_read = seek_offset / BCH_PAGE_SECTOR;
+ uint64_t number_sectors_to_read = length / BCH_PAGE_SECTOR;
+ uint64_t nand_address_block, nand_address_page;
+ NAND_AddressTypeDef nand_address;
+
+ *length_read = 0;
+
+ nand_address_block = seek_offset;
+ while (block_size_shift) {
+ nand_address_block >>= 1;
+ if (!nand_address_block)
+ break;
+ block_size_shift--;
+ }
+
+ nand_address.Block = (uint16_t)nand_address_block;
+
+ nand_address_page = seek_offset & ((1 << hnand->Info.block_size_shift)
+ - 1);
+ while (page_size_shift) {
+ nand_address_page >>= 1;
+ if (!nand_address_page)
+ break;
+ page_size_shift--;
+ }
+
+ nand_address.Page = (uint16_t)nand_address_page;
+
+ while (NAND_Check_Bad_Block(hnand, &nand_address) == BAD_BLOCK) {
+ nand_address.Block++;
+ if (nand_address.Block >= hnand->Info.BlockNb) {
+ ERROR("Cannot find valid block\n");
+ return -EIO;
+ }
+ }
+
+ if ((length % BCH_PAGE_SECTOR) != 0) {
+ /*
+ * yes, remainder required,
+ * adjust total number of sectors required
+ * one more page needed to read,
+ * data will not fill all page
+ */
+ number_sectors_to_read += 1;
+ }
+
+ /*
+ * Proceed here with reading/copying of
+ * (number_of_pages_remaining_to_read * BCH_PAGE_SECTOR)
+ * from NAND memory to SYSRAM download area
+ */
+ while (number_sectors_to_read != 0) {
+ uint32_t bch_sector_nb = num_sectors_read %
+ (hnand->Info.PageSize / BCH_PAGE_SECTOR);
+
+ if (NAND_Read_Logical_Page(hnand, &nand_address,
+ (uint8_t *)(buffer +
+ (buffer_index *
+ BCH_PAGE_SECTOR)),
+ bch_sector_nb) != STD_OK) {
+ VERBOSE("Page read failed or end of NAND reached\n");
+ return -EIO;
+ }
+
+ /* Increment read sectors number */
+ num_sectors_read++;
+ buffer_index++;
+
+ /* Decrement sectors to read */
+ number_sectors_to_read--;
+
+ /* Increment the NAND address */
+ NAND_Address_Inc(hnand, &nand_address, num_sectors_read);
+ }
+
+ *length_read = ((num_sectors_read - (seek_offset / BCH_PAGE_SECTOR)) *
+ BCH_PAGE_SECTOR);
+
+ return 0;
+}
+
+/* Close a file on the nand device */
+static int nand_block_close(io_entity_t *entity)
+{
+ return 0;
+}
+
+/* Exported functions */
+
+/* Register the nand driver with the IO abstraction */
+int register_io_dev_nand(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con);
+
+ result = io_register_device(&nand_dev_info);
+ if (!result)
+ *dev_con = &nand_dev_connector;
+
+ return result;
+}
diff --git a/drivers/st/nand/nand.c b/drivers/st/nand/nand.c
new file mode 100644
index 0000000..7f435cc
--- /dev/null
+++ b/drivers/st/nand/nand.c
@@ -0,0 +1,1548 @@
+/*
+ ******************************************************************************
+ * @file nand.c
+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project
+ * @version V0.1
+ * @date 28-April-2016
+ * @brief Nand FMC driver module for STM32MP1.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <limits.h>
+#include <nand.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <stm32mp_common.h>
+#include <utils_def.h>
+
+/* Other internal NAND driver definitions */
+#define CMD_SECTION ((uint32_t)(1 << 16)) /* A16 high */
+#define ADDR_SECTION ((uint32_t)(1 << 17)) /* A17 high */
+#define DATA_SECTION (0) /* A16 and A17 low */
+
+#define EIGHT_BIT_ACCESS 0x0
+#define SIXTEEN_BIT_ACCESS 0x1
+
+#define ONFI_SIG_VALUE 0x49464E4F /* "ONFI" */
+#define EXT_PAGE_SIG_VALUE 0x53505045 /* "EPPS" */
+
+/* NAND instance number */
+#define NAND_INSTANCE_NB 1
+/* Wait Time following NAND_RESET command sent (30us) */
+#define NAND_RST_TIMEOUT 30
+#define NAND_READY_WAIT_TIMEOUT_VAL_250MS_AT_64MHz 16000000
+
+/* NAND ECC Calculation wait timeout */
+#define NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS ms2tick(250)
+
+#define NAND_ECC_PAGE_SECTOR 512
+#define NAND_ECC_HAMMING1 1
+#define NAND_ECC_BCH4 4
+#define NAND_ECC_BCH8 8
+#define NAND_ECC_HAMMING1_BYTES_NB_8b 3
+#define NAND_ECC_BCH4_BYTES_NB_8b 7
+#define NAND_ECC_BCH8_BYTES_NB_8b 13
+#define NAND_ECC_HAMMING1_BYTES_NB_16b 4
+#define NAND_ECC_BCH4_BYTES_NB_16b 8
+#define NAND_ECC_BCH8_BYTES_NB_16b 14
+#define PARAM_PAGE_SIZE 256
+
+/* NAND memory status */
+#define NAND_BUSY ((uint32_t)0x00000000U)
+#define NAND_ERROR ((uint32_t)0x00000001U)
+#define NAND_READY ((uint32_t)0x00000040U)
+
+/* NAND ONFI commands */
+#define NAND_CMD_RESET ((uint8_t)0xFFU)
+#define NAND_CMD_READID ((uint8_t)0x90U)
+#define NAND_CMD_READID_SIG_ADDR ((uint8_t)0x20U)
+#define NAND_CMD_READ_PARAM_PAGE ((uint8_t)0xECU)
+#define NAND_CMD_READ_1ST ((uint8_t)0x00U)
+#define NAND_CMD_READ_2ND ((uint8_t)0x30U)
+#define NAND_CMD_STATUS ((uint8_t)0x70U)
+#define NAND_CMD_CHANGE_1ST ((uint8_t)0x05U)
+#define NAND_CMD_CHANGE_2ND ((uint8_t)0xE0U)
+
+/* CRC calculation */
+#define CRC_POLYNOM 0x8005
+#define CRC_INIT_VALUE 0x4F4E
+
+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;
+
+ tims->thiz = FMC_THIZ;
+ thiz = (tims->thiz + 1) * hclkp;
+
+ /*
+ * tWAIT > tRP
+ * 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;
+
+ /*
+ * tSETUP_MEM > tCS - tWAIT
+ * tSETUP_MEM > tALS - tWAIT
+ * tSETUP_MEM > tDS - (tWAIT - tHIZ)
+ */
+ tset_mem = hclkp;
+ 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))
+ 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);
+ tims->tset_mem = div_round_up(tset_mem, hclkp);
+ if (tims->tset_mem == 0)
+ tims->tset_mem = 1;
+
+ /*
+ * 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;
+ if (tset_mem < FMC_TREH_MIN &&
+ (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);
+ if ((tset_mem + twait < FMC_TWC_MIN) &&
+ (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;
+
+ /*
+ * tSETUP_ATT > tCS - tWAIT
+ * tSETUP_ATT > tCLS - tWAIT
+ * tSETUP_ATT > tALS - tWAIT
+ * tSETUP_ATT > tRHW - tHOLD_MEM
+ * tSETUP_ATT > tDS - (tWAIT - tHIZ)
+ */
+ tset_att = hclkp;
+ 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))
+ tset_att = FMC_TCLS_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;
+ if (twait > thiz && (twait - thiz < FMC_TDS_MIN) &&
+ (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;
+
+ /*
+ * tHOLD_ATT > tALH
+ * tHOLD_ATT > tCH
+ * tHOLD_ATT > tCLH
+ * tHOLD_ATT > tCOH
+ * tHOLD_ATT > tDH
+ * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM
+ * tHOLD_ATT > tADL - tSETUP_MEM
+ * tHOLD_ATT > tWH - tSETUP_MEM
+ * tHOLD_ATT > tWHR - tSETUP_MEM
+ * 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;
+ 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;
+ if (tset_mem < FMC_TADL_MIN &&
+ (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;
+ if (tset_mem < FMC_TWHR_MIN &&
+ (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);
+ if (tset_att + twait < FMC_TWC_MIN &&
+ (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;
+}
+
+/*****************************************************************************
+ *
+ * Function: Nand_Init
+ *
+ * Description: This function initializes the Nand FMC driver.
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand
+ * uint32_t bus_width
+ *
+ * Output parameters: none
+ *
+ * Return: None
+ *
+ *****************************************************************************/
+static void Nand_Init(NAND_HandleTypeDef *hNand, uint32_t bus_width,
+ uint32_t bch_algo)
+{
+ assert(hNand);
+
+ /*
+ * Initialize NAND control Interface
+ * Wait feature disabled, memory bank disabled, ECC logic disabled,
+ * BCH is selected, TCLR and TAR to max values, ECC sector size to 512B,
+ * BCH 8-bit is selected, enabled read access
+ *
+ * Be careful to not set ECCEN bit before Read Parameter Page command
+ * ECC logic must be enabled just before Read Logical Page
+ * Note: with PWAITEN feature, NAND controller temporizes next accesses,
+ * so no need to wait for ready/not busy after each command
+ */
+
+ /*
+ * Parameters should be given by boot_context
+ * Try to retrieve them with Nand_DetectAndInit
+ */
+ if (!hNand->Info.PageSize) {
+ hNand->Instance->PCReg |= FMC_PCR_ECCALG | /* Select BCH */
+ FMC_PCR_ECCSS_0 | /* ECCSS: Sector Size=512 bytes */
+ FMC_PCR_BCHECC |
+ FMC_PCR_PWAITEN;
+
+ hNand->Instance->PCReg &= ~FMC_PCR_PBKEN &
+ ~FMC_PCR_WE &
+ ~FMC_PCR_ECCSS_1 & /* ECCSS: Sector Size=512 bytes */
+ ~FMC_PCR_ECCSS_2; /* ECCSS: Sector Size=512 bytes */
+
+ if (bus_width == SIXTEEN_BIT_ACCESS) {
+ hNand->Instance->PCReg |= FMC_PCR_PWID_0;
+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_1;
+ } else {
+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_0;
+ hNand->Instance->PCReg &= ~FMC_PCR_PWID_1;
+ }
+
+ if (bch_algo == NAND_ECC_BCH4) {
+ /* BCH selected */
+ hNand->Instance->PCReg |= FMC_PCR_ECCALG;
+ /* BCH4 selected */
+ hNand->Instance->PCReg &= ~FMC_PCR_BCHECC;
+ } else if (bch_algo == NAND_ECC_BCH8) {
+ /* BCH selected */
+ hNand->Instance->PCReg |= FMC_PCR_ECCALG;
+ /* BCH8 selected */
+ hNand->Instance->PCReg |= FMC_PCR_BCHECC;
+ } else {
+ /* Hamming code selected */
+ hNand->Instance->PCReg &= ~FMC_PCR_ECCALG;
+ }
+ }
+
+ nand_calc_timing(hNand);
+
+ /* Set tclr/tar timings */
+ hNand->Instance->PCReg &=
+ ~FMC_PCR_TCLR_0 & /* tCLR: forced to value 0 */
+ ~FMC_PCR_TCLR_1 & /* tCLR: forced to value 0 */
+ ~FMC_PCR_TCLR_2 & /* tCLR: forced to value 0 */
+ ~FMC_PCR_TCLR_3 & /* tCLR: forced to value 0 */
+ ~FMC_PCR_TAR_0 & /* tAR: forced to value 0 */
+ ~FMC_PCR_TAR_1 & /* tAR: forced to value 0 */
+ ~FMC_PCR_TAR_2 & /* tAR: forced to value 0 */
+ ~FMC_PCR_TAR_3; /* tAR: forced to value 0 */
+
+ hNand->Instance->PCReg |= FMC_PCR_TCLR(hNand->Info.timings.tclr);
+ hNand->Instance->PCReg |= FMC_PCR_TAR(hNand->Info.timings.tar);
+
+ /* Set tset/twait/thold/thiz timings in common bank */
+ hNand->Instance->PMEM = FMC_PMEM_MEMSET(hNand->Info.timings.tset_mem);
+ hNand->Instance->PMEM |= FMC_PMEM_MEMWAIT(hNand->Info.timings.twait);
+ hNand->Instance->PMEM |=
+ FMC_PMEM_MEMHOLD(hNand->Info.timings.thold_mem);
+ hNand->Instance->PMEM |= FMC_PMEM_MEMHIZ(hNand->Info.timings.thiz);
+
+ /* Set tset/twait/thold/thiz timings in attribut bank */
+ hNand->Instance->PATT = FMC_PATT_ATTSET(hNand->Info.timings.tset_att);
+ hNand->Instance->PATT |= FMC_PATT_ATTWAIT(hNand->Info.timings.twait);
+ hNand->Instance->PATT |=
+ FMC_PATT_ATTHOLD(hNand->Info.timings.thold_att);
+ hNand->Instance->PATT |= FMC_PATT_ATTHIZ(hNand->Info.timings.thiz);
+
+ /* Enable the NAND device */
+ hNand->Instance->PCReg |= FMC_PCR_PBKEN;
+
+ /* Enable FMC Controller IP */
+ hNand->Instance->BCR1 |= FMC_BCR1_FMCEN;
+}
+
+/*
+ * @brief NAND memory read status
+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval NAND status
+ */
+static uint32_t NAND_ReadStatus(NAND_HandleTypeDef *hNand)
+{
+ uint32_t data;
+ uintptr_t deviceComMemAddr;
+ uintptr_t deviceAttrMemAddr;
+
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE;
+
+ /* Send Read status operation command */
+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_STATUS;
+
+ /* Read status register data */
+ data = *(__IO uint8_t *)deviceComMemAddr;
+
+ /* Return the status */
+ if ((data & NAND_ERROR) == NAND_ERROR)
+ return NAND_ERROR;
+ else if ((data & NAND_READY) == NAND_READY)
+ return NAND_READY;
+
+ return NAND_BUSY;
+}
+
+/*****************************************************************************
+ *
+ * Function: NAND_WaitReadyWithTimeout
+ *
+ * Description: This function wait with timeout of 250 ms until
+ * NAND Ready bit is set.
+ * Nand detection and initialization.
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand
+ *
+ * Return: value 0 is no timeout occurred, value 1 if 250 ms
+ * wait timeout elapsed while waiting for NAND Ready
+ * flag to raise.
+ *
+ *****************************************************************************/
+static uint32_t NAND_WaitReadyWithTimeout(NAND_HandleTypeDef *hNand)
+{
+ uint32_t timerValInit = 0;
+ uint32_t timeoutDetected = 0;
+
+ /* Is Nand handle NULL ? */
+ assert(hNand);
+
+ /* Get timer current value at start of loop */
+ timerValInit = (uint32_t)read_cntpct_el0();
+
+ /* Wait NAND Ready by a read status command until response or */
+ /* NAND Ready timeout elapses */
+ /* timeout = 250ms @ 64 MHz of gentimer */
+ while ((NAND_ReadStatus(hNand) != NAND_READY) &&
+ (timeoutDetected == 0)) {
+ /* Check if timeout occurred */
+ if (((uint32_t)read_cntpct_el0() - timerValInit) >=
+ NAND_READY_WAIT_TIMEOUT_VAL_250MS_AT_64MHz)
+ timeoutDetected = 1;
+ }
+
+ return(timeoutDetected);
+}
+
+/*****************************************************************************
+ *
+ * Function: Nand_Reset
+ *
+ * Description: Resets NAND Flash memory.
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand
+ *
+ * Output parameters: none
+ *
+ * Return: Std_ReturnType
+ *
+ *****************************************************************************/
+static Std_ReturnType Nand_Reset(NAND_HandleTypeDef *hNand)
+{
+ Std_ReturnType retVal = STD_NOT_OK;
+ uintptr_t deviceAddress;
+ uint32_t timeoutDetected = 0;
+
+ /* Is Nand handle NULL ? */
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceAddress = FLASH_COMMON_MEM_BASE;
+
+ /* Send NAND reset command */
+ /* Writes the command value in command section */
+ *(uint8_t *)(deviceAddress | CMD_SECTION) = NAND_CMD_RESET;
+
+ /* Wait the fixed 30 us time : after the NAND Reset command sent */
+ /* 30us @ 64 MHz of gentimer */
+ udelay(NAND_RST_TIMEOUT);
+
+ /* Wait NANDReady with timeout 250 ms */
+ timeoutDetected = NAND_WaitReadyWithTimeout(hNand);
+
+ /* If no timeout occurred : the NAND Reset phase was successful */
+ if (timeoutDetected == 0)
+ /* Set good status on exit */
+ retVal = STD_OK;
+
+ return retVal;
+}
+
+/*****************************************************************************
+ *
+ * Function: Nand_ReadIDCode
+ *
+ * Description: This function reads the NAND ID code
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand: NAND handle
+ * NAND_IDTypeDef * pNAND_ID: NAND ID structure
+ *
+ * Output parameters: none
+ *
+ * Return: None
+ *
+ *****************************************************************************/
+static void Nand_ReadIDCode(NAND_HandleTypeDef *hNand, NAND_IDTypeDef *pNAND_ID)
+{
+ uint32_t data;
+ uintptr_t deviceComMemAddr;
+ uintptr_t deviceAttrMemAddr;
+
+ assert(hNand);
+
+ /* Identify the device addresses */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE;
+
+ /* Send Read ID command sequence */
+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) = NAND_CMD_READID;
+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00;
+
+ udelay(NAND_RST_TIMEOUT);
+
+ /* Read the electronic signature from NAND flash */
+ data = *(__IO uint16_t *)deviceComMemAddr;
+
+ /* Return the data read */
+ pNAND_ID->Maker_Id = (uint8_t)(data);
+ pNAND_ID->Device_Id = (uint8_t)(data >> 8);
+}
+
+/**
+ * @brief NAND check CRC16
+ * @param crc: initial CRC value
+ * @param data_in: pointer to buffer
+ * @param data_len: length of data
+ * @retval CRC 16 bits
+ */
+static uint16_t NAND_CheckCrc16(uint16_t crc, uint8_t *data_in,
+ uint32_t data_len)
+{
+ /* Algorithm from ONFI standard */
+
+ uint32_t i, j, bit;
+
+ for (i = 0; i < data_len; i++) {
+ uint8_t curParam = *data_in++;
+
+ for (j = 0x80; j != 0; j >>= 1) {
+ bit = crc & 0x8000;
+ crc <<= 1;
+
+ if (curParam & j)
+ bit ^= 0x8000;
+
+ if (bit)
+ crc ^= CRC_POLYNOM;
+ }
+ crc &= 0xFFFF;
+ }
+
+ return crc;
+}
+
+/*****************************************************************************
+ *
+ * Function: Nand_ReadParameterPage
+ *
+ * Description: This function reads the NAND parameter page
+ * (command 0xEC)
+ * The Read Parameter Page command retrieves
+ * the data structure that describes
+ * the targets organization, features, timings
+ * and other behavioral parameters.
+ * There may also be additional information
+ * provided in an extended parameter page.
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand
+ *
+ * Output parameters: none
+ *
+ * Return: Std_ReturnType
+ *
+ *****************************************************************************/
+static Std_ReturnType Nand_ReadParameterPage(NAND_HandleTypeDef *hNand)
+{
+ uint32_t index;
+ uint8_t buffer[PARAM_PAGE_SIZE];
+ uintptr_t deviceComMemAddr;
+ uintptr_t deviceAttrMemAddr;
+ int i;
+ uint16_t crc16;
+
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE;
+
+ /* Send ONFI Parameter Page Read sequence */
+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) = NAND_CMD_READ_PARAM_PAGE;
+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00;
+
+ udelay(NAND_RST_TIMEOUT);
+
+ /*
+ * Read Parameter Page
+ * Note: There are three consecutive redondant copies
+ * of parameter page
+ */
+ for (i = 0; i < 3; i++) {
+ /* Read parameter page from NAND flash */
+ /* Get data */
+ for (index = 0; index < PARAM_PAGE_SIZE; index++)
+ buffer[index] = *(uint8_t *)deviceComMemAddr;
+
+ /*
+ * Bytes 0-4: Parameter page signature
+ * This field contains the parameter page signature.
+ * When two or more bytes of the signature are valid,
+ * then it denotes that a valid copy
+ * of the parameter page is present
+ */
+ hNand->Info.Signature = (buffer[3] << 24) | (buffer[2] << 16) |
+ (buffer[1] << 8) | buffer[0];
+ crc16 = (buffer[254] | buffer[255] << 8);
+
+ if ((hNand->Info.Signature == ONFI_SIG_VALUE) &&
+ (NAND_CheckCrc16(CRC_INIT_VALUE, buffer,
+ PARAM_PAGE_SIZE - 2) == crc16))
+ break;
+ }
+
+ if (i == 3) {
+ /* Could not find ONFI parameter page */
+ INFO("%s: No Onfi Parameter Page\n", __func__);
+ return STD_NOT_OK;
+ }
+
+ /* Byte 6, bit 0: data bus width (8 or 16) */
+ hNand->Info.BusWidth = buffer[6] & 0x1;
+
+ /* Bytes 80-83: Page size */
+ hNand->Info.PageSize = (buffer[83] << 24) | (buffer[82] << 16) |
+ (buffer[81] << 8) | buffer[80];
+
+ /* Bytes 92-95 : Block size in number of pages */
+ hNand->Info.BlockSize = (buffer[95] << 24) | (buffer[94] << 16) |
+ (buffer[93] << 8) | buffer[92];
+
+ /* Byte 96-99: Number of blocks per logical unit */
+ hNand->Info.BlockNb = (buffer[99] << 24) | (buffer[98] << 16) |
+ (buffer[97] << 8) | buffer[96];
+
+ /*
+ * Byte 112: Number of bits ECC correctability
+ * This field indicates the number of bits that the host
+ * should be able to correct per 512 bytes of data
+ */
+ if (buffer[112] != 0xFF) {
+ hNand->Info.ECCcorrectability = buffer[112];
+ } else if ((buffer[4] != 1) && (buffer[4] != 2) &&
+ buffer[6] & (1 << 7)) {
+ /* NAND ONFI, version > 2.1, with extended parameter page */
+ uint32_t ext_page_size = ((buffer[13] << 8) | buffer[12]);
+ uint32_t ext_page_offset = buffer[14] * PARAM_PAGE_SIZE;
+ uint32_t ecc_block_offset = 32;
+
+ /* Send ONFI Parameter Page Read sequence */
+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_PARAM_PAGE;
+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00;
+
+ /* Skip ONFI parameter pages to read Extended parameter page */
+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_1ST;
+
+ *(uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(ext_page_offset);
+
+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(ext_page_offset);
+
+ *(uint8_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_2ND;
+
+ udelay(NAND_RST_TIMEOUT);
+
+ /* Copy Extended parameter page */
+ for (index = 0; index < PARAM_PAGE_SIZE; index++)
+ buffer[index] = *(uint8_t *)deviceComMemAddr;
+
+ if (((buffer[5] << 24) | (buffer[4] << 16) |
+ (buffer[3] << 8) | buffer[2]) != EXT_PAGE_SIG_VALUE) {
+ WARN("Extended parameter page signature is wrong\n");
+ return STD_NOT_OK;
+ }
+
+ /*
+ * Extended parameter page can fit in buffer
+ * we can try to calculate its CRC
+ */
+ if (ext_page_size <= PARAM_PAGE_SIZE) {
+ crc16 = (buffer[1] << 8) | buffer[0];
+
+ if (NAND_CheckCrc16(CRC_INIT_VALUE, buffer,
+ ext_page_size) != crc16) {
+ WARN("Extended page CRC failed\n");
+ return STD_NOT_OK;
+ }
+ }
+
+ /*
+ * Check the 8 sections of extended parameter page
+ * for an extended ECC information block (type = 2)
+ */
+ for (i = 0; i < 8; i++) {
+ if (buffer[16 + 2 * i] == 2)
+ break;
+
+ ecc_block_offset += buffer[17 + 2 * i];
+ }
+
+ if (i == 8) {
+ WARN("ECC extended block could not be found\n");
+ return STD_NOT_OK;
+ }
+
+ if (ext_page_size <= PARAM_PAGE_SIZE) {
+ /*
+ * ECC correctcatbility is the first byte
+ * of the ECC block
+ */
+ hNand->Info.ECCcorrectability =
+ buffer[ecc_block_offset];
+ } else {
+ /* Send ONFI Parameter Page Read sequence */
+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_PARAM_PAGE;
+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) = 0x00;
+
+ /*
+ * Skip ONFI parameter pages to read
+ * Extended parameter page
+ */
+ *(uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_1ST;
+ *(uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(ext_page_offset +
+ ecc_block_offset);
+
+ *(uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(ext_page_offset +
+ ecc_block_offset);
+
+ *(uint8_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_2ND;
+
+ udelay(NAND_RST_TIMEOUT);
+
+ hNand->Info.ECCcorrectability =
+ *(uint8_t *)deviceComMemAddr;
+ }
+ } else {
+ WARN("ECC correctability could not be found\n");
+ return STD_NOT_OK;
+ }
+
+ return STD_OK;
+}
+
+/*****************************************************************************
+ *
+ * Function: Nand_DetectAndInit
+ *
+ * Description: This function initializes the Nand FMC driver.
+ * Nand detection and initialization.
+ *
+ * Input parameters: NAND_HandleTypeDef * hNand
+ *
+ * Output parameters: none
+ *
+ * Return: Std_ReturnType
+ *
+ *****************************************************************************/
+static Std_ReturnType Nand_DetectAndInit(NAND_HandleTypeDef *hNand)
+{
+ NAND_IDTypeDef pNAND_ID;
+ uint32_t nand_param_in_otp, result;
+
+ assert(hNand);
+
+ /* Remark : ReadID and ReadParameterPage are commands on 8-bit */
+
+ /* ReadID code */
+ Nand_ReadIDCode(hNand, &pNAND_ID);
+
+ /* Check if NAND parameters are stored in OTP */
+ result = bsec_shadow_read_otp(&nand_param_in_otp, NAND_OTP);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: NAND_OTP Error %i\n", result);
+ return STD_NOT_OK;
+ }
+
+ if (nand_param_in_otp & NAND_PARAM_STORED_IN_OTP) {
+ /*
+ * NAND parameter shall be read from OTP
+ */
+ hNand->Info.BusWidth = (nand_param_in_otp & NAND_WIDTH_MASK) >>
+ NAND_WIDTH_OFFSET;
+
+ switch ((nand_param_in_otp & NAND_PAGE_SIZE_MASK) >>
+ NAND_PAGE_SIZE_OFFSET) {
+ case NAND_PAGE_SIZE_2K:
+ hNand->Info.PageSize = 2048;
+ break;
+
+ case NAND_PAGE_SIZE_4K:
+ hNand->Info.PageSize = 4096;
+ break;
+
+ case NAND_PAGE_SIZE_8K:
+ hNand->Info.PageSize = 8192;
+ break;
+
+ default:
+ hNand->Info.PageSize = 0;
+ ERROR("Cannot read NAND page size\n");
+ return STD_NOT_OK;
+ }
+
+ switch ((nand_param_in_otp & NAND_BLOCK_SIZE_MASK) >>
+ NAND_BLOCK_SIZE_OFFSET) {
+ case NAND_BLOCK_SIZE_64_PAGES:
+ hNand->Info.BlockSize = 64;
+ break;
+
+ case NAND_BLOCK_SIZE_128_PAGES:
+ hNand->Info.BlockSize = 128;
+ break;
+
+ case NAND_BLOCK_SIZE_256_PAGES:
+ hNand->Info.BlockSize = 256;
+ break;
+
+ default:
+ hNand->Info.BlockSize = 0;
+ ERROR("Cannot read NAND block size\n");
+ return STD_NOT_OK;
+ }
+
+ hNand->Info.BlockNb = ((nand_param_in_otp &
+ NAND_BLOCK_NB_MASK) >>
+ NAND_BLOCK_NB_OFFSET) *
+ NAND_BLOCK_NB_UNIT;
+
+ switch ((nand_param_in_otp & NAND_ECC_BIT_NB_MASK) >>
+ NAND_ECC_BIT_NB_OFFSET) {
+ case NAND_ECC_BIT_NB_UNSET:
+ hNand->Info.ECCcorrectability = 0;
+ break;
+
+ case NAND_ECC_BIT_NB_1_BITS:
+ hNand->Info.ECCcorrectability = 1;
+ break;
+
+ case NAND_ECC_BIT_NB_4_BITS:
+ hNand->Info.ECCcorrectability = 4;
+ break;
+
+ case NAND_ECC_BIT_NB_8_BITS:
+ hNand->Info.ECCcorrectability = 8;
+ break;
+
+ default:
+ hNand->Info.ECCcorrectability = 0;
+ ERROR("Cannot read ECCbit number\n");
+ return STD_NOT_OK;
+ }
+ } else {
+ /*
+ * ONFI or 'ONFI compliant' NAND
+ * 'ONFI compliant' means that parameters used by bootrom are
+ * available in parameter table at same offsets as in a
+ * ONFI parameter table.
+ * NAND parameter shall be read from Parameter table.
+ */
+
+ uint32_t onfi_ecc;
+
+ /* Read Nand parameter page */
+ if (Nand_ReadParameterPage(hNand) != STD_OK) {
+ ERROR("%s: NAND not initialized\n", __func__);
+ return STD_NOT_OK;
+ }
+
+ onfi_ecc = hNand->Info.ECCcorrectability;
+
+ /*
+ * For ONFI nand, ECC number of bits may be overridden by a
+ * value from OTP configuration.
+ */
+ switch ((nand_param_in_otp & NAND_ECC_BIT_NB_MASK) >>
+ NAND_ECC_BIT_NB_OFFSET) {
+ case NAND_ECC_BIT_NB_UNSET:
+ hNand->Info.ECCcorrectability = 0;
+ break;
+
+ case NAND_ECC_BIT_NB_1_BITS:
+ hNand->Info.ECCcorrectability = 1;
+ break;
+
+ case NAND_ECC_BIT_NB_4_BITS:
+ hNand->Info.ECCcorrectability = 4;
+ break;
+
+ case NAND_ECC_BIT_NB_8_BITS:
+ hNand->Info.ECCcorrectability = 8;
+ break;
+
+ default:
+ hNand->Info.ECCcorrectability = 0;
+ break;
+ }
+
+ /*
+ * if OTP info is wrong, fall back to parameter read in ONFI
+ * parameter page
+ */
+ if (hNand->Info.ECCcorrectability == 0)
+ hNand->Info.ECCcorrectability = onfi_ecc;
+ }
+
+ Nand_Init(hNand, hNand->Info.BusWidth, hNand->Info.ECCcorrectability);
+
+ /* Now NAND Flash is detected and initialized */
+ return STD_OK;
+}
+
+/**
+ * @brief NAND read page command sequence
+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param colAddr: column address
+ * @param rowAddr: row address
+ * @retval Std_ReturnType
+ */
+static void NAND_Read_Page_Cmd(NAND_HandleTypeDef *hNand, uint32_t colAddr,
+ uint32_t rowAddr)
+{
+ uintptr_t deviceComMemAddr;
+ uintptr_t deviceAttrMemAddr;
+
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE;
+
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_1ST;
+
+ /* C1 */
+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(colAddr);
+ /* C2 */
+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(colAddr);
+ /* R1 */
+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(rowAddr);
+ /* R2 */
+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(rowAddr);
+
+ /* R3 */
+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_3RD_CYCLE(rowAddr);
+
+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_2ND;
+ } else {
+ /* NAND 16bit */
+ *(__IO uint16_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_1ST;
+
+ /* C1 */
+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(colAddr);
+ /* C2 */
+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(colAddr);
+ /* R1 */
+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(rowAddr);
+ /* R2 */
+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(rowAddr);
+
+ /* R3 */
+ *(__IO uint16_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_3RD_CYCLE(rowAddr);
+
+ *(__IO uint16_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_READ_2ND;
+ }
+}
+
+/*****************************************************************************
+ *
+ * Function: _bit_count
+ *
+ * Description: Return the number of bits set to one in a 32bit word
+ *
+ * Input parameters: v 32 bit word
+ *
+ * Return: number of bits set to one in v.
+ *
+ *****************************************************************************/
+static uint32_t _bit_count(uint32_t v)
+{
+ uint32_t c = 0;
+
+ for (uint32_t i = 0; i < CHAR_BIT * sizeof(typeof(v)); i++)
+ if (v & (BIT(i)))
+ c++;
+
+ return c;
+}
+
+/*****************************************************************************
+ *
+ * Function: NAND_Hamming_Correction
+ *
+ * Description: Consider Hamming correction code, and apply correction
+ * if needed and possible.
+ *
+ * Input parameters: Buffer : pointer to buffer containing data read.
+ * EccBuffer : pointer to buffer containing ecc code read
+ * from out of band area.
+ * EccCalculated : ECC calculated by FMC during reading of
+ * data.
+ *
+ * Return: 0 no error detected
+ * 1 one error detected and correted
+ * > 1 unrecoverable error
+ * -1 ecc error
+ *
+ *****************************************************************************/
+static int NAND_Hamming_Correction(uint8_t *Buffer, uint8_t *EccBuffer,
+ uint32_t EccCalculated)
+{
+ uint8_t xor_ecc_ones;
+ uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b;
+ union {
+ uint32_t val;
+ uint8_t bytes[4];
+ } xor_ecc;
+
+ /* Page size--------ECC_Code Size
+ * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF)
+ * 512---------------24 bits (ECC_CODE & 0x00FFFFFF)
+ * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF)
+ * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF)
+ * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF)
+ * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF)
+ */
+
+ /* For Page size 512, ECC_Code size 24 bits */
+ xor_ecc_1b = (EccCalculated & 0x000000FF) ^ EccBuffer[0];
+ xor_ecc_2b = ((EccCalculated & 0x0000FF00) >> 8) ^ EccBuffer[1];
+ xor_ecc_3b = ((EccCalculated & 0x00FF0000) >> 16) ^ EccBuffer[2];
+
+ xor_ecc.val = 0L;
+ xor_ecc.bytes[2] = xor_ecc_3b;
+ xor_ecc.bytes[1] = xor_ecc_2b;
+ xor_ecc.bytes[0] = xor_ecc_1b;
+
+ if (xor_ecc.val == 0)
+ return 0; /* No Error */
+
+ xor_ecc_ones = _bit_count(xor_ecc.val);
+ if (xor_ecc_ones < 23) {
+ if (xor_ecc_ones == 12) {
+ uint16_t bit_address, byte_address;
+
+ /* Correctable ERROR */
+ bit_address = ((xor_ecc_1b >> 1) & 0x01) |
+ ((xor_ecc_1b >> 2) & 0x02) |
+ ((xor_ecc_1b >> 3) & 0x04);
+
+ byte_address = ((xor_ecc_1b >> 7) & 0x01) |
+ ((xor_ecc_2b) & 0x02) |
+ ((xor_ecc_2b >> 1) & 0x04) |
+ ((xor_ecc_2b >> 2) & 0x08) |
+ ((xor_ecc_2b >> 3) & 0x10) |
+ ((xor_ecc_3b << 4) & 0x20) |
+ ((xor_ecc_3b << 3) & 0x40) |
+ ((xor_ecc_3b << 2) & 0x80) |
+ ((xor_ecc_3b << 1) & 0x100);
+
+ /* Correct bit error in the data */
+ Buffer[byte_address] = (Buffer[byte_address]) ^
+ ((uint8_t)(1 << bit_address));
+ INFO("Hamming: 1 ECC error corrected\n");
+ return 1;
+ }
+
+ /* Non Correctable ERROR */
+ ERROR("%s: Uncorrectable ECC Errors\n", __func__);
+ return 2;
+ }
+
+ /* ECC ERROR */
+ ERROR("%s: Hamming correction error\n", __func__);
+ return -1;
+}
+
+/*****************************************************************************
+ *
+ * Function: NAND_Read_Logical_Page
+ *
+ * Description: Read 512B sector from NAND memory page
+ *
+ * Input parameters: hNand: pointer to a NAND_HandleTypeDef structure
+ * that contains the configuration information
+ * for NAND module.
+ * Address : pointer to NAND address structure
+ * Buffer : pointer to destination read buffer
+ * bch_sector_nb : 512B sector number in the page
+ *
+ *
+ * Return: Std_ReturnType
+ *
+ *****************************************************************************/
+Std_ReturnType NAND_Read_Logical_Page(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address,
+ uint8_t *Buffer, uint32_t bch_sector_nb)
+{
+ uintptr_t deviceComMemAddr;
+ uintptr_t deviceAttrMemAddr;
+ uint32_t size = 0;
+ uint32_t index, bloc_nb, nb_pages_per_block, offset;
+ uint32_t ecc_size = 0;
+ uint32_t rowAddr = 0, colAddr = 0;
+ uint8_t EccBuffer[NAND_ECC_BCH8_BYTES_NB_16b];
+ uint32_t heccr = 0;
+
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+ deviceAttrMemAddr = FLASH_ATTRIB_MEM_BASE;
+
+ bloc_nb = Address->Block;
+ nb_pages_per_block = hNand->Info.BlockSize;
+
+ /* Page and block to be read */
+ rowAddr = (bloc_nb * nb_pages_per_block) + Address->Page;
+
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ /* Byte or word in page to be read */
+ colAddr = bch_sector_nb * NAND_ECC_PAGE_SECTOR;
+
+ size = NAND_ECC_PAGE_SECTOR;
+ } else {
+ /* If NAND 16bit */
+ /* Byte or word in page to be read */
+ colAddr = (bch_sector_nb * NAND_ECC_PAGE_SECTOR) / 2;
+
+ size = NAND_ECC_PAGE_SECTOR / 2;
+ }
+
+ /* Reset ECC enabling */
+ hNand->Instance->PCReg &= ~FMC_PCR_ECCEN;
+ hNand->Instance->PCReg &= ~FMC_PCR_WE;
+ hNand->Instance->PCReg |= FMC_PCR_ECCEN;
+
+ /* Clear status */
+ hNand->Instance->BCHICR = 0x1F;
+
+ /* Send read page command sequence */
+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr);
+
+ /* Get data into destination buffer */
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ uint8_t *Buffer8b = (uint8_t *)Buffer;
+
+ for (index = 0; index < size; index++)
+ *Buffer8b++ = *(uint8_t *)deviceComMemAddr;
+ } else {
+ /* If NAND 16bit */
+ uint16_t *Buffer16b = (uint16_t *)Buffer;
+
+ for (index = 0; index < size; index++)
+ *Buffer16b++ = *(uint16_t *)deviceComMemAddr;
+ }
+
+ if (hNand->Info.ECCcorrectability == NAND_ECC_HAMMING1) {
+ /* During read of data , syndrome is calculated */
+ /* Wait until decoding error is ready */
+ uint32_t timerValInit = read_cntpct_el0();
+
+ while ((hNand->Instance->SR & FMC_SR_NWRF) != FMC_SR_NWRF) {
+ if ((read_cntpct_el0() - timerValInit) >
+ NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS) {
+ ERROR("%s: syndrome calculation timeout\n",
+ __func__);
+ return STD_NOT_OK;
+ }
+ }
+
+ heccr = hNand->Instance->HECCR;
+ }
+
+ /* Read now corresponding ECC bytes (7 or 13) in spare area */
+ /* Page and block to be read */
+
+ if (hNand->Info.ECCcorrectability == NAND_ECC_BCH4) {
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS)
+ ecc_size = NAND_ECC_BCH4_BYTES_NB_8b;
+ else
+ ecc_size = NAND_ECC_BCH4_BYTES_NB_16b;
+ } else if (hNand->Info.ECCcorrectability == NAND_ECC_BCH8) {
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS)
+ ecc_size = NAND_ECC_BCH8_BYTES_NB_8b;
+ else
+ ecc_size = NAND_ECC_BCH8_BYTES_NB_16b;
+ } else {
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS)
+ ecc_size = NAND_ECC_HAMMING1_BYTES_NB_8b;
+ else
+ ecc_size = NAND_ECC_HAMMING1_BYTES_NB_16b;
+ }
+
+ offset = 2;
+
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ /* Byte or word in page to be read */
+ /* See SRS mapping */
+ colAddr = hNand->Info.PageSize + offset +
+ (bch_sector_nb * ecc_size);
+ } else {
+ /* If NAND 16bit */
+ /* Byte or word in page to be read */
+ /* See SRS mapping */
+ colAddr = (hNand->Info.PageSize + offset +
+ (bch_sector_nb * ecc_size)) / 2;
+ }
+
+ /* Send change read column command */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ *(__IO uint8_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_1ST;
+
+ /* C1 */
+ *(__IO uint8_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(colAddr);
+ /* C2 */
+ *(__IO uint8_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(colAddr);
+
+ *(__IO uint8_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_2ND;
+ } else {
+ *(__IO uint16_t *)(deviceComMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_1ST;
+
+ /* C1 */
+ *(__IO uint16_t *)(deviceComMemAddr | ADDR_SECTION) =
+ ADDR_1ST_CYCLE(colAddr);
+ /* C2 */
+ *(__IO uint16_t *)(deviceAttrMemAddr | ADDR_SECTION) =
+ ADDR_2ND_CYCLE(colAddr);
+
+ *(__IO uint16_t *)(deviceAttrMemAddr | CMD_SECTION) =
+ NAND_CMD_CHANGE_2ND;
+ }
+
+ /* Get data into destination EccBuffer */
+
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ uint8_t *pEccBuffer = EccBuffer;
+
+ for (index = 0; index < ecc_size; index++)
+ *(uint8_t *)pEccBuffer++ = *(uint8_t *)deviceComMemAddr;
+ } else {
+ /* If NAND 16bit */
+ uint16_t *pEccBuffer16b = (uint16_t *)(EccBuffer);
+
+ for (index = 0; index < ecc_size / 2; index++) {
+ *(uint16_t *)pEccBuffer16b++ =
+ *(uint16_t *)deviceComMemAddr;
+ }
+ }
+
+ if (hNand->Info.ECCcorrectability == NAND_ECC_HAMMING1) {
+ int nb_errors;
+
+ nb_errors = NAND_Hamming_Correction(Buffer, EccBuffer,
+ heccr);
+ if ((nb_errors != 0) && (nb_errors != 1))
+ return STD_NOT_OK;
+
+ } else /* BCH error correction */ {
+ uint32_t ecc_errors_nb;
+ uint32_t i;
+ uint32_t errorPosition[8];
+
+ /*
+ * During read of data and parity bits, syndrome is calculated,
+ * then error location is launched
+ * Wait until decoding error is ready
+ */
+ uint32_t timerValInit = (uint32_t)read_cntpct_el0();
+
+ while ((hNand->Instance->BCHISR & FMC_BCHISR_DERF) !=
+ FMC_BCHISR_DERF) {
+ if (((uint32_t)read_cntpct_el0() - timerValInit) >
+ NAND_ECC_CALCULATION_TIMEOUT_VAL_250MS)
+ return STD_NOT_OK;
+ }
+
+ /* Read decoding results */
+ /* Check if there were uncorrectable errors */
+ if (hNand->Instance->BCHISR & FMC_BCHISR_DUEF) {
+ VERBOSE("%s: Uncorrectable ECC Error\n", __func__);
+ return STD_NOT_OK;
+ }
+
+ /* Check if there were errors */
+ if (!(hNand->Instance->BCHISR & FMC_BCHISR_DEFF))
+ return STD_OK;
+
+ /* Read number of errors */
+ ecc_errors_nb = hNand->Instance->BCHSR & FMC_BCHSR_DEN;
+
+ VERBOSE("%s: ECC Errors detected: %d\n", __func__,
+ ecc_errors_nb);
+
+ /* Retrieve the error position corresponding to the error
+ * number
+ */
+ /* Error 1 position : FMC_BCHDSR1.EBP1 */
+ errorPosition[0] = hNand->Instance->BCHDSR1 & FMC_BCHDSR1_EBP1;
+ /* Error 2 position : FMC_BCHDSR1.EBP2 */
+ errorPosition[1] = (hNand->Instance->BCHDSR1 & FMC_BCHDSR1_EBP2)
+ >> FMC_EBP2_MASK;
+ /* Error 3 position : FMC_BCHDSR2.EBP1 */
+ errorPosition[2] = hNand->Instance->BCHDSR2 & FMC_BCHDSR2_EBP1;
+ /* Error 4 position : FMC_BCHDSR2.EBP2 */
+ errorPosition[3] = (hNand->Instance->BCHDSR2 & FMC_BCHDSR2_EBP2)
+ >> FMC_EBP2_MASK;
+ /* Error 5 position : FMC_BCHDSR3.EBP1 */
+ errorPosition[4] = hNand->Instance->BCHDSR3 & FMC_BCHDSR3_EBP1;
+ /* Error 6 position : FMC_BCHDSR3.EBP2 */
+ errorPosition[5] = (hNand->Instance->BCHDSR3 & FMC_BCHDSR3_EBP2)
+ >> FMC_EBP2_MASK;
+ /* Error 7 position : FMC_BCHDSR4.EBP1 */
+ errorPosition[6] = hNand->Instance->BCHDSR4 & FMC_BCHDSR4_EBP1;
+ /* Error 8 position : FMC_BCHDSR4.EBP2 */
+ errorPosition[7] = (hNand->Instance->BCHDSR4 & FMC_BCHDSR4_EBP2)
+ >> FMC_EBP2_MASK;
+
+ /* Error position indicates error bit number in binary */
+ /* Retrieve the mask of the wrong bit to correct */
+ for (i = 0; i < ecc_errors_nb; i++) {
+ VERBOSE("%s: ECC Error position: %d\n", __func__,
+ errorPosition[i]);
+ /* Correct only if error is in data area */
+ if (errorPosition[i] < 0x1000) {
+ /*
+ * Retrieve the mask of the wrong bit
+ * to correct
+ */
+ uint32_t bitMask = BIT(errorPosition[i] & 0x07);
+
+ /*
+ * Remove bit postion in the error position
+ * (to have byte to correct)
+ */
+ errorPosition[i] >>= 0x03;
+ VERBOSE("%s: ECC Error in data area\n",
+ __func__);
+
+ /* Fix the error : invert the wrong bit */
+ *(Buffer + errorPosition[i]) ^= bitMask;
+ } else {
+ VERBOSE("%s: ECC Error not in data area\n",
+ __func__);
+ }
+ }
+ }
+
+ return STD_OK;
+}
+
+/**
+ * @brief NAND check bad blck
+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * Address: pointer to NAND address structure
+ * @retval BAD_BLOCK or GOOD_BLOCK
+ */
+uint32_t NAND_Check_Bad_Block(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address)
+{
+ uintptr_t deviceComMemAddr = 0;
+ uint32_t bloc_nb = 0;
+ uint32_t nb_pages_per_block = 0;
+ uint32_t page_nb;
+ uint32_t block_status = BAD_BLOCK;
+ uint32_t rowAddr = 0, colAddr = 0;
+ uint8_t bbm_marker, bbm_marker_2;
+ uint16_t bbm_marker16b;
+
+ assert(hNand);
+
+ /* Identify the device address */
+ deviceComMemAddr = FLASH_COMMON_MEM_BASE;
+
+ /*
+ * Bad block indication is is the 2 first bytes of the 1st
+ * or 2nd page of the block (depends on manufacturer)
+ */
+
+ /*
+ * Read the 2 first bytes of the spare area
+ * of the 1st page of the block
+ */
+ bloc_nb = Address->Block;
+ nb_pages_per_block = hNand->Info.BlockSize;
+
+ /* Page and block to be read */
+ page_nb = 0;
+ rowAddr = (bloc_nb * nb_pages_per_block) + page_nb;
+
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ /* Byte or word in page to be read */
+ colAddr = hNand->Info.PageSize;
+ } else {
+ /* If NAND 16bit */
+ /* Byte or word in page to be read */
+ colAddr = hNand->Info.PageSize / 2;
+ }
+
+ /* Send read page command sequence */
+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr);
+
+ udelay(NAND_RST_TIMEOUT);
+
+ /* Get data into destination buffer */
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ bbm_marker = *(uint8_t *)deviceComMemAddr;
+ bbm_marker_2 = *(uint8_t *)deviceComMemAddr;
+
+ if ((bbm_marker != 0xFF) || (bbm_marker_2 != 0xFF))
+ block_status = BAD_BLOCK;
+ else
+ block_status = GOOD_BLOCK;
+
+ } else {
+ /* If NAND 16bit */
+ bbm_marker16b = *(uint16_t *)deviceComMemAddr;
+
+ if (bbm_marker16b != 0xFFFF)
+ block_status = BAD_BLOCK;
+ else
+ block_status = GOOD_BLOCK;
+ }
+
+ if (block_status == BAD_BLOCK)
+ return block_status;
+
+ /*
+ * Read the 2 first bytes of the spare area of the 2nd page
+ * of the block
+ * Page and block to be read
+ */
+ page_nb = 1;
+ rowAddr = (bloc_nb * nb_pages_per_block) + page_nb;
+
+ /* Send read page command sequence */
+ NAND_Read_Page_Cmd(hNand, colAddr, rowAddr);
+
+ udelay(NAND_RST_TIMEOUT);
+
+ /* Get data into destination buffer */
+ /* If NAND 8bit */
+ if (hNand->Info.BusWidth == EIGHT_BIT_ACCESS) {
+ bbm_marker = *(uint8_t *)deviceComMemAddr;
+ bbm_marker_2 = *(uint8_t *)deviceComMemAddr;
+
+ if ((bbm_marker == 0xFF) && (bbm_marker_2 == 0xFF))
+ block_status = GOOD_BLOCK;
+ else
+ block_status = BAD_BLOCK;
+ } else {
+ /* If NAND 16bit */
+ bbm_marker16b = *(uint16_t *)deviceComMemAddr;
+
+ if (bbm_marker16b == 0xFFFF)
+ block_status = GOOD_BLOCK;
+ else
+ block_status = BAD_BLOCK;
+ }
+
+ return block_status;
+}
+
+/**
+ * @brief Increment the NAND memory address
+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param Address: pointer to NAND address structure
+ * @retval Std_ReturnType
+ */
+Std_ReturnType NAND_Address_Inc(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address,
+ uint32_t numPagesRead)
+{
+ assert(hNand);
+
+ /* Increment page address */
+ if ((numPagesRead % (hNand->Info.PageSize / BCH_PAGE_SECTOR)) == 0)
+ Address->Page++;
+
+ /* Check NAND address is valid */
+ if (Address->Page == hNand->Info.BlockSize) {
+ Address->Page = 0;
+ /* Search for next valid block */
+ Address->Block++;
+ while (Address->Block < hNand->Info.BlockNb &&
+ NAND_Check_Bad_Block(hNand, Address) == BAD_BLOCK)
+ Address->Block++;
+
+ if (Address->Block == hNand->Info.BlockNb)
+ return STD_NOT_OK;
+ }
+
+ return STD_OK;
+}
+
+/**
+ * @brief Initialize driver only if needed:
+ * bootrom must have initialize NAND and bootcontext
+ * must contains correct value.
+ * @param hNand: pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval Std_ReturnType
+ */
+Std_ReturnType nand_initialize(NAND_HandleTypeDef *hnand)
+{
+ if (!hnand->Info.PageSize) {
+ INFO("Reconfigure NAND\n");
+ /* Not properly initialized by bootrom */
+ Nand_Init(hnand, EIGHT_BIT_ACCESS, NAND_ECC_BCH8);
+
+ if (Nand_Reset(hnand) != STD_OK) {
+ ERROR("nand: Reset error (IP base::0x%lx)\n",
+ (uintptr_t)hnand->Instance);
+ return STD_NOT_OK;
+ }
+
+ if (Nand_DetectAndInit(hnand) != STD_OK) {
+ ERROR("nand: DetectAndInit error (IP base:0x%lx)\n",
+ (uintptr_t)hnand->Instance);
+ return STD_NOT_OK;
+ }
+ } else {
+ /* Initialization done, just need to set correct timing */
+ Nand_Init(hnand, hnand->Info.BusWidth,
+ hnand->Info.ECCcorrectability);
+ }
+ return STD_OK;
+}
+
diff --git a/drivers/st/pmic/stm32_i2c.c b/drivers/st/pmic/stm32_i2c.c
deleted file mode 100644
index 0980139..0000000
--- a/drivers/st/pmic/stm32_i2c.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_helpers.h>
-#include <delay_timer.h>
-#include <errno.h>
-#include <mmio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stm32_i2c.h>
-
-/* STM32 I2C registers offsets */
-#define I2C_CR1 0x00U
-#define I2C_CR2 0x04U
-#define I2C_OAR1 0x08U
-#define I2C_OAR2 0x0CU
-#define I2C_TIMINGR 0x10U
-#define I2C_TIMEOUTR 0x14U
-#define I2C_ISR 0x18U
-#define I2C_ICR 0x1CU
-#define I2C_PECR 0x20U
-#define I2C_RXDR 0x24U
-#define I2C_TXDR 0x28U
-
-#define MAX_DELAY 0xFFFFFFFFU
-
-/* I2C TIMING clear register Mask */
-#define TIMING_CLEAR_MASK 0xF0FFFFFFU
-/* Timeout 25 ms */
-#define I2C_TIMEOUT_BUSY 25U
-
-#define MAX_NBYTE_SIZE 255U
-
-static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
- uint16_t dev_addr, uint16_t mem_addr,
- uint16_t mem_add_size, uint32_t timeout,
- uint32_t tick_start);
-static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t mem_addr, uint16_t mem_add_size,
- uint32_t timeout, uint32_t tick_start);
-
-/* Private functions to handle flags during polling transfer */
-static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
- uint8_t awaited_value, uint32_t timeout,
- uint32_t tick_start);
-static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start);
-static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start);
-static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start);
-
-/* Private function to flush TXDR register */
-static void i2c_flush_txdr(struct i2c_handle_s *hi2c);
-
-/* Private function to start, restart or stop a transfer */
-static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t size, uint32_t i2c_mode,
- uint32_t request);
-
-/*
- * @brief Initialize the I2C device.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @retval 0 if OK, negative value else
- */
-int stm32_i2c_init(struct i2c_handle_s *hi2c)
-{
- if (hi2c == NULL) {
- return -ENOENT;
- }
-
- if (hi2c->i2c_state == I2C_STATE_RESET) {
- hi2c->lock = 0;
- }
-
- hi2c->i2c_state = I2C_STATE_BUSY;
-
- /* Disable the selected I2C peripheral */
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
-
- /* Configure I2Cx: Frequency range */
- mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
- hi2c->i2c_init.timing & TIMING_CLEAR_MASK);
-
- /* Disable Own Address1 before set the Own Address1 configuration */
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
-
- /* Configure I2Cx: Own Address1 and ack own address1 mode */
- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
- I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1);
- } else { /* I2C_ADDRESSINGMODE_10BIT */
- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
- I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
- hi2c->i2c_init.own_address1);
- }
-
- /* Configure I2Cx: Addressing Master mode */
- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
- }
-
- /*
- * Enable the AUTOEND by default, and enable NACK
- * (should be disable only during Slave process)
- */
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
- I2C_CR2_AUTOEND | I2C_CR2_NACK);
-
- /* Disable Own Address2 before set the Own Address2 configuration */
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
-
- /* Configure I2Cx: Dual mode and Own Address2 */
- mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
- hi2c->i2c_init.dual_address_mode |
- hi2c->i2c_init.own_address2 |
- (hi2c->i2c_init.own_address2_masks << 8));
-
- /* Configure I2Cx: Generalcall and NoStretch mode */
- mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
- hi2c->i2c_init.general_call_mode |
- hi2c->i2c_init.no_stretch_mode);
-
- /* Enable the selected I2C peripheral */
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
-
- hi2c->i2c_err = I2C_ERROR_NONE;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- return 0;
-}
-
-/*
- * @brief Write an amount of data in blocking mode to a specific memory address
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param dev_addr: Target device address
- * @param mem_addr: Internal memory address
- * @param mem_add_size: size of internal memory address
- * @param p_data: Pointer to data buffer
- * @param size: Amount of data to be sent
- * @param timeout: timeout duration
- * @retval 0 if OK, negative value else
- */
-int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t mem_addr, uint16_t mem_add_size,
- uint8_t *p_data, uint16_t size, uint32_t timeout)
-{
- uint32_t tickstart;
-
- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
- return -EBUSY;
- }
-
- if ((p_data == NULL) || (size == 0U)) {
- return -EINVAL;
- }
-
- hi2c->lock = 1;
-
- tickstart = (uint32_t)read_cntpct_el0();
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
- tickstart) != 0) {
- return -EIO;
- }
-
- hi2c->i2c_state = I2C_STATE_BUSY_TX;
- hi2c->i2c_mode = I2C_MODE_MEM;
- hi2c->i2c_err = I2C_ERROR_NONE;
-
- hi2c->p_buff = p_data;
- hi2c->xfer_count = size;
-
- /* Send Slave Address and Memory Address */
- if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, mem_add_size,
- timeout, tickstart) != 0) {
- hi2c->lock = 0;
- return -EIO;
- }
-
- /*
- * Set NBYTES to write and reload
- * if hi2c->xfer_count > MAX_NBYTE_SIZE
- */
- if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
- hi2c->xfer_size = MAX_NBYTE_SIZE;
- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
- I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
- } else {
- hi2c->xfer_size = hi2c->xfer_count;
- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
- I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
- }
-
- do {
- if (i2c_wait_txis(hi2c, timeout, tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *hi2c->p_buff);
- hi2c->p_buff++;
- hi2c->xfer_count--;
- hi2c->xfer_size--;
-
- if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
- /* Wait until TCR flag is set */
- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
- hi2c->xfer_size = MAX_NBYTE_SIZE;
- i2c_transfer_config(hi2c, dev_addr,
- hi2c->xfer_size,
- I2C_RELOAD_MODE,
- I2C_NO_STARTSTOP);
- } else {
- hi2c->xfer_size = hi2c->xfer_count;
- i2c_transfer_config(hi2c, dev_addr,
- hi2c->xfer_size,
- I2C_AUTOEND_MODE,
- I2C_NO_STARTSTOP);
- }
- }
-
- } while (hi2c->xfer_count > 0U);
-
- /*
- * No need to Check TC flag, with AUTOEND mode the stop
- * is automatically generated.
- * Wait until STOPF flag is reset.
- */
- if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
-
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
-
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return 0;
-}
-
-/*
- * @brief Read an amount of data in blocking mode from a specific memory
- * address
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param dev_addr: Target device address
- * @param mem_addr: Internal memory address
- * @param mem_add_size: size of internal memory address
- * @param p_data: Pointer to data buffer
- * @param size: Amount of data to be sent
- * @param timeout: timeout duration
- * @retval 0 if OK, negative value else
- */
-int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t mem_addr, uint16_t mem_add_size,
- uint8_t *p_data, uint16_t size, uint32_t timeout)
-{
- uint32_t tickstart;
-
- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
- return -EBUSY;
- }
-
- if ((p_data == NULL) || (size == 0U)) {
- return -EINVAL;
- }
-
- hi2c->lock = 1;
-
- tickstart = (uint32_t)read_cntpct_el0();
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
- tickstart) != 0) {
- return -EIO;
- }
-
- hi2c->i2c_state = I2C_STATE_BUSY_RX;
- hi2c->i2c_mode = I2C_MODE_MEM;
- hi2c->i2c_err = I2C_ERROR_NONE;
-
- hi2c->p_buff = p_data;
- hi2c->xfer_count = size;
-
- /* Send Slave Address and Memory Address */
- if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, mem_add_size,
- timeout, tickstart) != 0) {
- hi2c->lock = 0;
- return -EIO;
- }
-
- /*
- * Send Slave Address.
- * Set NBYTES to write and reload if hi2c->xfer_count > MAX_NBYTE_SIZE
- * and generate RESTART.
- */
- if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
- hi2c->xfer_size = MAX_NBYTE_SIZE;
- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
- I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
- } else {
- hi2c->xfer_size = hi2c->xfer_count;
- i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
- I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
- }
-
- do {
- if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- *hi2c->p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
- hi2c->p_buff++;
- hi2c->xfer_size--;
- hi2c->xfer_count--;
-
- if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
- hi2c->xfer_size = MAX_NBYTE_SIZE;
- i2c_transfer_config(hi2c, dev_addr,
- hi2c->xfer_size,
- I2C_RELOAD_MODE,
- I2C_NO_STARTSTOP);
- } else {
- hi2c->xfer_size = hi2c->xfer_count;
- i2c_transfer_config(hi2c, dev_addr,
- hi2c->xfer_size,
- I2C_AUTOEND_MODE,
- I2C_NO_STARTSTOP);
- }
- }
- } while (hi2c->xfer_count > 0U);
-
- /*
- * No need to Check TC flag, with AUTOEND mode the stop
- * is automatically generated
- * Wait until STOPF flag is reset
- */
- if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
-
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
-
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return 0;
-}
-
-/*
- * @brief Checks if target device is ready for communication.
- * @note This function is used with Memory devices
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param dev_addr: Target device address
- * @param trials: Number of trials
- * @param timeout: timeout duration
- * @retval 0 if OK, negative value else
- */
-int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
- uint16_t dev_addr, uint32_t trials,
- uint32_t timeout)
-{
- uint32_t i2c_trials = 0U;
-
- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
- return -EBUSY;
- }
-
- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
- 0U) {
- return -EBUSY;
- }
-
- hi2c->lock = 1;
-
- hi2c->i2c_state = I2C_STATE_BUSY;
- hi2c->i2c_err = I2C_ERROR_NONE;
-
- do {
- uint32_t tickstart;
-
- /* Generate Start */
- if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
- (((uint32_t)dev_addr & I2C_CR2_SADD) |
- I2C_CR2_START | I2C_CR2_AUTOEND) &
- ~I2C_CR2_RD_WRN);
- } else {
- mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
- (((uint32_t)dev_addr & I2C_CR2_SADD) |
- I2C_CR2_START | I2C_CR2_ADD10) &
- ~I2C_CR2_RD_WRN);
- }
-
- /*
- * No need to Check TC flag, with AUTOEND mode the stop
- * is automatically generated
- * Wait until STOPF flag is set or a NACK flag is set
- */
- tickstart = (uint32_t)read_cntpct_el0();
- while (((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- (I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0U) &&
- (hi2c->i2c_state != I2C_STATE_TIMEOUT)) {
- if (timeout != MAX_DELAY) {
- if ((((uint32_t)read_cntpct_el0() - tickstart) >
- timeout) || (timeout == 0U)) {
- hi2c->i2c_state = I2C_STATE_READY;
-
- hi2c->i2c_err |=
- I2C_ERROR_TIMEOUT;
-
- hi2c->lock = 0;
-
- return -EIO;
- }
- }
- }
-
- /* Check if the NACKF flag has not been set */
- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- I2C_FLAG_AF) == 0U) {
- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
- I2C_FLAG_STOPF);
-
- hi2c->i2c_state = I2C_STATE_READY;
-
- hi2c->lock = 0;
-
- return 0;
- }
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
-
- if (i2c_trials == trials) {
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
- I2C_CR2_STOP);
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
- tickstart) != 0) {
- return -EIO;
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
- I2C_FLAG_STOPF);
- }
-
- i2c_trials++;
- } while (i2c_trials < trials);
-
- hi2c->i2c_state = I2C_STATE_READY;
-
- hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
-
- hi2c->lock = 0;
-
- return -EIO;
-}
-
-/*
- * @brief Master sends target device address followed by internal memory
- * address for write request.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param dev_addr: Target device address
- * @param mem_addr: Internal memory address
- * @param mem_add_size: size of internal memory address
- * @param timeout: timeout duration
- * @param tick_start Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
- uint16_t dev_addr, uint16_t mem_addr,
- uint16_t mem_add_size, uint32_t timeout,
- uint32_t tick_start)
-{
- i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
- I2C_GENERATE_START_WRITE);
-
- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
- /* Send Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)(mem_addr & 0x00FFU));
- } else {
- /* Send MSB of Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)((mem_addr & 0xFF00U) >> 8));
-
- /* Wait until TXIS flag is set */
- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- /* Send LSB of Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)(mem_addr & 0x00FFU));
- }
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, tick_start) !=
- 0) {
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * @brief Master sends target device address followed by internal memory
- * address for read request.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param dev_addr: Target device address
- * @param mem_addr: Internal memory address
- * @param mem_add_size: size of internal memory address
- * @param timeout: timeout duration
- * @param tick_start Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t mem_addr, uint16_t mem_add_size,
- uint32_t timeout, uint32_t tick_start)
-{
- i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
- I2C_GENERATE_START_WRITE);
-
- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
- /* Send Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)(mem_addr & 0x00FFU));
- } else {
- /* Send MSB of Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)((mem_addr & 0xFF00U) >> 8));
-
- /* Wait until TXIS flag is set */
- if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- /* Send LSB of Memory Address */
- mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
- (uint8_t)(mem_addr & 0x00FFU));
- }
-
- if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * @brief I2C Tx data register flush process.
- * @param hi2c: I2C handle.
- * @retval None
- */
-static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
-{
- /*
- * If a pending TXIS flag is set,
- * write a dummy data in TXDR to clear it.
- */
- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
- 0U) {
- mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
- }
-
- /* Flush TX register if not empty */
- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
- 0U) {
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
- I2C_FLAG_TXE);
- }
-}
-
-/*
- * @brief This function handles I2C Communication timeout.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param flag: Specifies the I2C flag to check.
- * @param awaited_value: The awaited bit value for the flag (0 or 1).
- * @param timeout: timeout duration
- * @param tick_start: Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
- uint8_t awaited_value, uint32_t timeout,
- uint32_t tick_start)
-{
- uint8_t flag_check;
-
- do {
- flag_check = ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- flag) == flag) ? 1U : 0U;
-
- if (timeout != MAX_DELAY) {
- if ((((uint32_t)read_cntpct_el0() - tick_start) >
- timeout) || (timeout == 0U)) {
- hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
- return -EIO;
- }
- }
- } while (flag_check == awaited_value);
-
- return 0;
-}
-
-/*
- * @brief This function handles I2C Communication timeout for specific usage
- * of TXIS flag.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param timeout: timeout duration
- * @param tick_start: Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start)
-{
- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- I2C_FLAG_TXIS) == 0U) {
- if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- if (timeout != MAX_DELAY) {
- if ((((uint32_t)read_cntpct_el0() - tick_start) >
- timeout) || (timeout == 0U)) {
- hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return -EIO;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * @brief This function handles I2C Communication timeout for specific
- * usage of STOP flag.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param timeout: timeout duration
- * @param tick_start: Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start)
-{
- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- I2C_FLAG_STOPF) == 0U) {
- if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
- return -EIO;
- }
-
- if ((((uint32_t)read_cntpct_el0() - tick_start) > timeout) ||
- (timeout == 0U)) {
- hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return -EIO;
- }
- }
-
- return 0;
-}
-
-/*
- * @brief This function handles Acknowledge failed detection during
- * an I2C Communication.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2C.
- * @param timeout: timeout duration
- * @param tick_start: Tick start value
- * @retval 0 if OK, negative value else
- */
-static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
- uint32_t tick_start)
-{
- if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
- return 0;
- }
-
- /*
- * Wait until STOP Flag is reset.
- * AutoEnd should be initiate after AF.
- */
- while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
- I2C_FLAG_STOPF) == 0U) {
- if (timeout != MAX_DELAY) {
- if ((((uint32_t)read_cntpct_el0() - tick_start) >
- timeout) || (timeout == 0U)) {
- hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return -EIO;
- }
- }
- }
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
-
- mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
-
- i2c_flush_txdr(hi2c);
-
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
-
- hi2c->i2c_err |= I2C_ERROR_AF;
- hi2c->i2c_state = I2C_STATE_READY;
- hi2c->i2c_mode = I2C_MODE_NONE;
-
- hi2c->lock = 0;
-
- return -EIO;
-}
-
-/*
- * @brief Handles I2Cx communication when starting transfer or during transfer
- * (TC or TCR flag are set).
- * @param hi2c: I2C handle.
- * @param dev_addr: Specifies the slave address to be programmed.
- * @param size: Specifies the number of bytes to be programmed.
- * This parameter must be a value between 0 and 255.
- * @param i2c_mode: New state of the I2C START condition generation.
- * This parameter can be one of the following values:
- * @arg @ref I2C_RELOAD_MODE: Enable Reload mode .
- * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
- * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
- * @param request: New state of the I2C START condition generation.
- * This parameter can be one of the following values:
- * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
- * @arg @ref I2C_GENERATE_STOP: Generate stop condition
- * (size should be set to 0).
- * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
- * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
- * @retval None
- */
-static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint16_t size, uint32_t i2c_mode,
- uint32_t request)
-{
- uint32_t clr_value, set_value;
-
- clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
- I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
- (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
-
- set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
- (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
- i2c_mode | request;
-
- mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
-}
-
-/*
- * @brief Configure I2C Analog noise filter.
- * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
- * the configuration information for the specified I2Cx peripheral
- * @param analog_filter: New state of the Analog filter.
- * @retval 0 if OK, negative value else
- */
-int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
- uint32_t analog_filter)
-{
- if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
- return -EBUSY;
- }
-
- hi2c->lock = 1;
-
- hi2c->i2c_state = I2C_STATE_BUSY;
-
- /* Disable the selected I2C peripheral */
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
-
- /* Reset I2Cx ANOFF bit */
- mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
-
- /* Set analog filter bit*/
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
-
- /* Enable the selected I2C peripheral */
- mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
-
- hi2c->i2c_state = I2C_STATE_READY;
-
- hi2c->lock = 0;
-
- return 0;
-}
diff --git a/drivers/st/pmic/stm32mp1_pmic.c b/drivers/st/pmic/stm32mp1_pmic.c
deleted file mode 100644
index 958de08..0000000
--- a/drivers/st/pmic/stm32mp1_pmic.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <debug.h>
-#include <delay_timer.h>
-#include <errno.h>
-#include <libfdt.h>
-#include <mmio.h>
-#include <mmio.h>
-#include <platform_def.h>
-#include <stdbool.h>
-#include <stm32_gpio.h>
-#include <stm32mp1_clk.h>
-#include <stm32mp1_dt.h>
-#include <stm32mp1_pmic.h>
-#include <stpmu1.h>
-#include <utils_def.h>
-
-/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
-#define I2C_TIMING 0x10D07DB5
-
-#define I2C_TIMEOUT 0xFFFFF
-
-#define MASK_RESET_BUCK3 BIT(2)
-
-#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
-#define STPMU1_LDO12356_OUTPUT_SHIFT 2
-#define STPMU1_LDO3_MODE (uint8_t)(BIT(7))
-#define STPMU1_LDO3_DDR_SEL 31U
-#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT)
-
-#define STPMU1_BUCK_OUTPUT_SHIFT 2
-#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT)
-
-#define STPMU1_DEFAULT_START_UP_DELAY_MS 1
-
-static struct i2c_handle_s i2c_handle;
-static uint32_t pmic_i2c_addr;
-
-static int dt_get_pmic_node(void *fdt)
-{
- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1");
-}
-
-bool dt_check_pmic(void)
-{
- int node;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return false;
- }
-
- node = dt_get_pmic_node(fdt);
- if (node < 0) {
- VERBOSE("%s: No PMIC node found in DT\n", __func__);
- return false;
- }
-
- return fdt_check_status(node);
-}
-
-static int dt_pmic_i2c_config(struct dt_node_info *i2c_info)
-{
- int pmic_node, i2c_node;
- void *fdt;
- const fdt32_t *cuint;
-
- if (fdt_get_address(&fdt) == 0) {
- return -ENOENT;
- }
-
- pmic_node = dt_get_pmic_node(fdt);
- if (pmic_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
- if (pmic_i2c_addr > UINT16_MAX) {
- return -EINVAL;
- }
-
- i2c_node = fdt_parent_offset(fdt, pmic_node);
- if (i2c_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- dt_fill_device_info(i2c_info, i2c_node);
- if (i2c_info->base == 0U) {
- return -FDT_ERR_NOTFOUND;
- }
-
- return dt_set_pinctrl_config(i2c_node);
-}
-
-int dt_pmic_enable_boot_on_regulators(void)
-{
- int pmic_node, regulators_node, regulator_node;
- void *fdt;
-
- if (fdt_get_address(&fdt) == 0) {
- return -ENOENT;
- }
-
- pmic_node = dt_get_pmic_node(fdt);
- if (pmic_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
-
- fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
- const fdt32_t *cuint;
- const char *node_name;
- uint16_t voltage;
-
- if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
- NULL) == NULL) {
- continue;
- }
-
- cuint = fdt_getprop(fdt, regulator_node,
- "regulator-min-microvolt", NULL);
- if (cuint == NULL) {
- continue;
- }
-
- /* DT uses microvolts, whereas driver awaits millivolts */
- voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
- node_name = fdt_get_name(fdt, regulator_node, NULL);
-
- if (stpmu1_is_regulator_enabled(node_name) == 0U) {
- int status;
-
- status = stpmu1_regulator_voltage_set(node_name,
- voltage);
- if (status != 0) {
- return status;
- }
-
- status = stpmu1_regulator_enable(node_name);
- if (status != 0) {
- return status;
- }
- }
- }
-
- return 0;
-}
-
-void initialize_pmic_i2c(void)
-{
- int ret;
- struct dt_node_info i2c_info;
-
- if (dt_pmic_i2c_config(&i2c_info) != 0) {
- ERROR("I2C configuration failed\n");
- panic();
- }
-
- if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) {
- ERROR("I2C clock enable failed\n");
- panic();
- }
-
- /* Initialize PMIC I2C */
- i2c_handle.i2c_base_addr = i2c_info.base;
- i2c_handle.i2c_init.timing = I2C_TIMING;
- i2c_handle.i2c_init.own_address1 = pmic_i2c_addr;
- i2c_handle.i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
- i2c_handle.i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
- i2c_handle.i2c_init.own_address2 = 0;
- i2c_handle.i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
- i2c_handle.i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
- i2c_handle.i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
-
- ret = stm32_i2c_init(&i2c_handle);
- if (ret != 0) {
- ERROR("Cannot initialize I2C %x (%d)\n",
- i2c_handle.i2c_base_addr, ret);
- panic();
- }
-
- ret = stm32_i2c_config_analog_filter(&i2c_handle,
- I2C_ANALOGFILTER_ENABLE);
- if (ret != 0) {
- ERROR("Cannot initialize I2C analog filter (%d)\n", ret);
- panic();
- }
-
- ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1,
- I2C_TIMEOUT);
- if (ret != 0) {
- ERROR("I2C device not ready (%d)\n", ret);
- panic();
- }
-
- stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
-}
-
-void initialize_pmic(void)
-{
- int status;
- uint8_t read_val;
-
- initialize_pmic_i2c();
-
- status = stpmu1_register_read(VERSION_STATUS_REG, &read_val);
- if (status != 0) {
- panic();
- }
-
- INFO("PMIC version = 0x%x\n", read_val);
-
- /* Keep VDD on during the reset cycle */
- status = stpmu1_register_update(MASK_RESET_BUCK_REG,
- MASK_RESET_BUCK3,
- MASK_RESET_BUCK3);
- if (status != 0) {
- panic();
- }
-}
-
-int pmic_ddr_power_init(enum ddr_type ddr_type)
-{
- bool buck3_at_1v8 = false;
- uint8_t read_val;
- int status;
-
- switch (ddr_type) {
- case STM32MP_DDR3:
- /* Set LDO3 to sync mode */
- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
-
- read_val &= ~STPMU1_LDO3_MODE;
- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
- read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
-
- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
- if (status != 0) {
- return status;
- }
-
- status = stpmu1_regulator_voltage_set("buck2", 1350);
- if (status != 0) {
- return status;
- }
-
- status = stpmu1_regulator_enable("buck2");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmu1_regulator_enable("vref_ddr");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmu1_regulator_enable("ldo3");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
- break;
-
- case STM32MP_LPDDR2:
- /*
- * Set LDO3 to 1.8V
- * Set LDO3 to bypass mode if BUCK3 = 1.8V
- * Set LDO3 to normal mode if BUCK3 != 1.8V
- */
- status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
-
- if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) {
- buck3_at_1v8 = true;
- }
-
- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
- if (status != 0) {
- return status;
- }
-
- read_val &= ~STPMU1_LDO3_MODE;
- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
- read_val |= STPMU1_LDO3_1800000;
- if (buck3_at_1v8) {
- read_val |= STPMU1_LDO3_MODE;
- }
-
- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
- if (status != 0) {
- return status;
- }
-
- status = stpmu1_regulator_voltage_set("buck2", 1200);
- if (status != 0) {
- return status;
- }
-
- status = stpmu1_regulator_enable("ldo3");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmu1_regulator_enable("buck2");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
-
- status = stpmu1_regulator_enable("vref_ddr");
- if (status != 0) {
- return status;
- }
-
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
- break;
-
- default:
- break;
- };
-
- return 0;
-}
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
new file mode 100644
index 0000000..c8d70db
--- /dev/null
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32_i2c.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_pmic.h>
+#include <stpmic1.h>
+#include <utils_def.h>
+
+#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
+#define STPMIC1_LDO12356_OUTPUT_SHIFT 2
+#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7))
+#define STPMIC1_LDO3_DDR_SEL 31U
+#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
+
+#define STPMIC1_BUCK_OUTPUT_SHIFT 2
+#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT)
+
+#define REGULATOR_MODE_STANDBY 8U
+
+#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
+
+static struct i2c_handle_s i2c_handle;
+static uint32_t pmic_i2c_addr;
+
+static int dt_get_pmic_node(void *fdt)
+{
+ return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
+}
+
+int dt_pmic_status(void)
+{
+ int node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ node = dt_get_pmic_node(fdt);
+ if (node <= 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return fdt_get_status(node);
+}
+
+static bool dt_pmic_is_secure(void)
+{
+ int status = dt_pmic_status();
+
+ return (status >= 0) &&
+ (status == DT_SECURE) &&
+ (i2c_handle.dt_status == DT_SECURE);
+}
+
+/*
+ * Get PMIC and its I2C bus configuration from the device tree.
+ * Return 0 on success, negative on error, 1 if no PMIC node is defined.
+ */
+static int dt_pmic_i2c_config(struct dt_node_info *i2c_info,
+ struct stm32_i2c_init_s *init)
+{
+ int pmic_node, i2c_node;
+ void *fdt;
+ const fdt32_t *cuint;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ pmic_node = dt_get_pmic_node(fdt);
+ if (pmic_node < 0) {
+ return 1;
+ }
+
+ cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
+ if (pmic_i2c_addr > UINT16_MAX) {
+ return -EINVAL;
+ }
+
+ i2c_node = fdt_parent_offset(fdt, pmic_node);
+ if (i2c_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ dt_fill_device_info(i2c_info, i2c_node);
+ if (i2c_info->base == 0U) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init);
+}
+
+int dt_pmic_configure_boot_on_regulators(void)
+{
+ int pmic_node, regulators_node, regulator_node;
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ pmic_node = dt_get_pmic_node(fdt);
+ if (pmic_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
+
+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
+ const fdt32_t *cuint;
+ const char *node_name = fdt_get_name(fdt, regulator_node, NULL);
+ uint16_t voltage;
+ int status;
+
+#if defined(IMAGE_BL2)
+ if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on",
+ NULL) == NULL) &&
+ (fdt_getprop(fdt, regulator_node, "regulator-always-on",
+ NULL) == NULL)) {
+#else
+ if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
+ NULL) == NULL) {
+#endif
+ continue;
+ }
+
+ if (fdt_getprop(fdt, regulator_node, "regulator-pull-down",
+ NULL) != NULL) {
+ int status;
+
+ status = stpmic1_regulator_pull_down_set(node_name);
+ if (status != 0) {
+ return status;
+ }
+ }
+
+ if (fdt_getprop(fdt, regulator_node, "st,mask-reset",
+ NULL) != NULL) {
+ int status;
+
+ status = stpmic1_regulator_mask_reset_set(node_name);
+ if (status != 0) {
+ return status;
+ }
+ }
+
+ cuint = fdt_getprop(fdt, regulator_node,
+ "regulator-min-microvolt", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ /* DT uses microvolts, whereas driver awaits millivolts */
+ voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
+
+ status = stpmic1_regulator_voltage_set(node_name, voltage);
+ if (status != 0) {
+ return status;
+ }
+
+ if (stpmic1_is_regulator_enabled(node_name) == 0U) {
+ status = stpmic1_regulator_enable(node_name);
+ if (status != 0) {
+ return status;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int dt_pmic_set_lp_config(const char *node_name)
+{
+ int pmic_node, regulators_node, regulator_node;
+ int status;
+ void *fdt;
+
+ if (node_name == NULL) {
+ return 0;
+ }
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ pmic_node = dt_get_pmic_node(fdt);
+ if (pmic_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ status = stpmic1_powerctrl_on();
+ if (status != 0) {
+ return status;
+ };
+
+ regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
+
+ fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
+ const fdt32_t *cuint;
+ const char *reg_name;
+ int regulator_state_node;
+
+ /*
+ * First, copy active configuration (Control register) to
+ * PWRCTRL Control register, even if regulator_state_node
+ * does not exist.
+ */
+ reg_name = fdt_get_name(fdt, regulator_node, NULL);
+ status = stpmic1_lp_copy_reg(reg_name);
+ if (status != 0) {
+ return status;
+ }
+
+ /* Then apply configs from regulator_state_node */
+ regulator_state_node = fdt_subnode_offset(fdt,
+ regulator_node,
+ node_name);
+ if (regulator_state_node <= 0) {
+ continue;
+ }
+
+ if (fdt_getprop(fdt, regulator_state_node,
+ "regulator-on-in-suspend", NULL) != NULL) {
+ status = stpmic1_lp_reg_on_off(reg_name, 1);
+ if (status != 0) {
+ return status;
+ }
+ }
+
+ if (fdt_getprop(fdt, regulator_state_node,
+ "regulator-off-in-suspend", NULL) != NULL) {
+ status = stpmic1_lp_reg_on_off(reg_name, 0);
+ if (status != 0) {
+ return status;
+ }
+ }
+
+ cuint = fdt_getprop(fdt, regulator_state_node,
+ "regulator-suspend-microvolt", NULL);
+ if (cuint != NULL) {
+ uint16_t voltage = (uint16_t)(fdt32_to_cpu(*cuint) /
+ 1000U);
+
+ status = stpmic1_lp_set_voltage(reg_name, voltage);
+ if (status != 0) {
+ return status;
+ }
+ }
+
+ cuint = fdt_getprop(fdt, regulator_state_node,
+ "regulator-mode", NULL);
+ if (cuint != NULL) {
+ if (fdt32_to_cpu(*cuint) == REGULATOR_MODE_STANDBY) {
+ status = stpmic1_lp_set_mode(reg_name, 1);
+ if (status != 0) {
+ return status;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * initialize_pmic_i2c - Initialize I2C for the PMIC control
+ *
+ * Return true if PMIC is available, false if not found, panics on errors
+ */
+bool initialize_pmic_i2c(void)
+{
+ int ret;
+ struct dt_node_info i2c_info;
+ struct i2c_handle_s *i2c = &i2c_handle;
+ struct stm32_i2c_init_s i2c_init;
+
+ ret = dt_pmic_i2c_config(&i2c_info, &i2c_init);
+ if (ret < 0) {
+ ERROR("I2C configuration failed %d\n", ret);
+ panic();
+ }
+ if (ret != 0) {
+ return false;
+ }
+
+ /* Initialize PMIC I2C */
+ i2c->i2c_base_addr = i2c_info.base;
+ i2c->dt_status = i2c_info.status;
+ i2c->clock = i2c_info.clock;
+ i2c_init.own_address1 = pmic_i2c_addr;
+ i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
+ i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
+ i2c_init.own_address2 = 0;
+ i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
+ i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
+ i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
+ i2c_init.analog_filter = 1;
+ i2c_init.digital_filter_coef = 0;
+
+ ret = stm32_i2c_init(i2c, &i2c_init);
+ if (ret != 0) {
+ ERROR("Cannot initialize I2C %x (%d)\n",
+ i2c->i2c_base_addr, ret);
+ panic();
+ }
+
+ if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1,
+ I2C_TIMEOUT_BUSY_MS)) {
+ ERROR("I2C device not ready\n");
+ panic();
+ }
+
+ stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr);
+
+ return true;
+}
+
+#if STM32MP1_DEBUG_ENABLE
+int pmic_keep_debug_unit(void)
+{
+ unsigned int i;
+ static const char * const regus[] = {
+ "buck1",
+ "buck3",
+ };
+
+ for (i = 0; i < ARRAY_SIZE(regus); i++) {
+ int res;
+
+ WARN("Mask %s\n", regus[i]);
+ res = stpmic1_regulator_mask_reset_set(regus[i]);
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static void register_non_secure_pmic(void)
+{
+ if (i2c_handle.i2c_base_addr == 0U) {
+ return;
+ }
+
+ stm32mp_register_non_secure_periph_iomem(i2c_handle.i2c_base_addr);
+
+ if (stm32mp1_rcc_is_secure()) {
+ stm32mp1_register_clock_parents_secure(i2c_handle.clock);
+ }
+}
+
+static void register_secure_pmic(void)
+{
+ stm32mp_register_secure_periph_iomem(i2c_handle.i2c_base_addr);
+}
+
+void initialize_pmic(void)
+{
+ unsigned long pmic_version;
+
+ if (!initialize_pmic_i2c()) {
+ VERBOSE("No PMIC\n");
+ register_non_secure_pmic();
+ return;
+ }
+
+ if (stpmic1_get_version(&pmic_version) != 0) {
+ ERROR("Failed to access PMIC\n");
+ panic();
+ }
+
+ INFO("PMIC version = 0x%02lx\n", pmic_version);
+ stpmic1_dump_regulators();
+
+ if (dt_pmic_is_secure()) {
+ register_secure_pmic();
+ } else {
+ VERBOSE("PMIC is not secure-only hence assumed non secure\n");
+ register_non_secure_pmic();
+ }
+
+#if defined(IMAGE_BL2)
+ if (dt_pmic_configure_boot_on_regulators() != 0) {
+ panic();
+ };
+#endif
+}
+
+int pmic_ddr_power_init(enum ddr_type ddr_type)
+{
+ bool buck3_at_1v8 = false;
+ uint8_t read_val;
+ int status;
+
+ switch (ddr_type) {
+ case STM32MP_DDR3:
+ /* Set LDO3 to sync mode */
+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
+ if (status != 0) {
+ return status;
+ }
+
+ read_val &= ~STPMIC1_LDO3_MODE;
+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
+ read_val |= STPMIC1_LDO3_DDR_SEL <<
+ STPMIC1_LDO12356_OUTPUT_SHIFT;
+
+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+ if (status != 0) {
+ return status;
+ }
+
+ status = stpmic1_regulator_voltage_set("buck2", 1350);
+ if (status != 0) {
+ return status;
+ }
+
+ status = stpmic1_regulator_enable("buck2");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+ status = stpmic1_regulator_enable("vref_ddr");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+ status = stpmic1_regulator_enable("ldo3");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+ break;
+
+ case STM32MP_LPDDR2:
+ case STM32MP_LPDDR3:
+ /*
+ * Set LDO3 to 1.8V
+ * Set LDO3 to bypass mode if BUCK3 = 1.8V
+ * Set LDO3 to normal mode if BUCK3 != 1.8V
+ */
+ status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
+ if (status != 0) {
+ return status;
+ }
+
+ if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
+ buck3_at_1v8 = true;
+ }
+
+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
+ if (status != 0) {
+ return status;
+ }
+
+ read_val &= ~STPMIC1_LDO3_MODE;
+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
+ read_val |= STPMIC1_LDO3_1800000;
+ if (buck3_at_1v8) {
+ read_val |= STPMIC1_LDO3_MODE;
+ }
+
+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
+ if (status != 0) {
+ return status;
+ }
+
+ status = stpmic1_regulator_voltage_set("buck2", 1200);
+ if (status != 0) {
+ return status;
+ }
+
+ status = stpmic1_regulator_enable("ldo3");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+ status = stpmic1_regulator_enable("buck2");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+ status = stpmic1_regulator_enable("vref_ddr");
+ if (status != 0) {
+ return status;
+ }
+
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+ break;
+
+ default:
+ break;
+ };
+
+ return 0;
+}
diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c
new file mode 100644
index 0000000..2bd2b60
--- /dev/null
+++ b/drivers/st/pmic/stpmic1.c
@@ -0,0 +1,817 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform.h>
+#include <stpmic1.h>
+#include <string.h>
+
+#define I2C_TIMEOUT_MS 25
+
+struct regul_struct {
+ const char *dt_node_name;
+ const uint16_t *voltage_table;
+ uint8_t voltage_table_size;
+ uint8_t control_reg;
+ uint8_t low_power_reg;
+ uint8_t pull_down_reg;
+ uint8_t pull_down;
+ uint8_t mask_reset_reg;
+ uint8_t mask_reset;
+};
+
+static struct i2c_handle_s *pmic_i2c_handle;
+static uint16_t pmic_i2c_addr;
+
+/* Voltage tables in mV */
+static const uint16_t buck1_voltage_table[] = {
+ 725,
+ 725,
+ 725,
+ 725,
+ 725,
+ 725,
+ 750,
+ 775,
+ 800,
+ 825,
+ 850,
+ 875,
+ 900,
+ 925,
+ 950,
+ 975,
+ 1000,
+ 1025,
+ 1050,
+ 1075,
+ 1100,
+ 1125,
+ 1150,
+ 1175,
+ 1200,
+ 1225,
+ 1250,
+ 1275,
+ 1300,
+ 1325,
+ 1350,
+ 1375,
+ 1400,
+ 1425,
+ 1450,
+ 1475,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+ 1500,
+};
+
+static const uint16_t buck2_voltage_table[] = {
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1050,
+ 1050,
+ 1100,
+ 1100,
+ 1150,
+ 1150,
+ 1200,
+ 1200,
+ 1250,
+ 1250,
+ 1300,
+ 1300,
+ 1350,
+ 1350,
+ 1400,
+ 1400,
+ 1450,
+ 1450,
+ 1500,
+};
+
+static const uint16_t buck3_voltage_table[] = {
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1000,
+ 1100,
+ 1100,
+ 1100,
+ 1100,
+ 1200,
+ 1200,
+ 1200,
+ 1200,
+ 1300,
+ 1300,
+ 1300,
+ 1300,
+ 1400,
+ 1400,
+ 1400,
+ 1400,
+ 1500,
+ 1600,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+ 3400,
+};
+
+static const uint16_t buck4_voltage_table[] = {
+ 600,
+ 625,
+ 650,
+ 675,
+ 700,
+ 725,
+ 750,
+ 775,
+ 800,
+ 825,
+ 850,
+ 875,
+ 900,
+ 925,
+ 950,
+ 975,
+ 1000,
+ 1025,
+ 1050,
+ 1075,
+ 1100,
+ 1125,
+ 1150,
+ 1175,
+ 1200,
+ 1225,
+ 1250,
+ 1275,
+ 1300,
+ 1300,
+ 1350,
+ 1350,
+ 1400,
+ 1400,
+ 1450,
+ 1450,
+ 1500,
+ 1600,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+ 3400,
+ 3500,
+ 3600,
+ 3700,
+ 3800,
+ 3900,
+};
+
+static const uint16_t ldo1_voltage_table[] = {
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+};
+
+static const uint16_t ldo2_voltage_table[] = {
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+};
+
+static const uint16_t ldo3_voltage_table[] = {
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+ 3300,
+ 3300,
+ 3300,
+ 3300,
+ 3300,
+ 3300,
+ 500,
+ 0xFFFF, /* VREFDDR */
+};
+
+static const uint16_t ldo5_voltage_table[] = {
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+ 3400,
+ 3500,
+ 3600,
+ 3700,
+ 3800,
+ 3900,
+};
+
+static const uint16_t ldo6_voltage_table[] = {
+ 900,
+ 1000,
+ 1100,
+ 1200,
+ 1300,
+ 1400,
+ 1500,
+ 1600,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+};
+
+static const uint16_t ldo4_voltage_table[] = {
+ 3300,
+};
+
+static const uint16_t vref_ddr_voltage_table[] = {
+ 3300,
+};
+
+/* Table of Regulators in PMIC SoC */
+static const struct regul_struct regulators_table[] = {
+ {
+ .dt_node_name = "buck1",
+ .voltage_table = buck1_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
+ .control_reg = BUCK1_CONTROL_REG,
+ .low_power_reg = BUCK1_PWRCTRL_REG,
+ .pull_down_reg = BUCK_PULL_DOWN_REG,
+ .pull_down = BUCK1_PULL_DOWN_SHIFT,
+ .mask_reset_reg = MASK_RESET_BUCK_REG,
+ .mask_reset = BUCK1_MASK_RESET,
+ },
+ {
+ .dt_node_name = "buck2",
+ .voltage_table = buck2_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
+ .control_reg = BUCK2_CONTROL_REG,
+ .low_power_reg = BUCK2_PWRCTRL_REG,
+ .pull_down_reg = BUCK_PULL_DOWN_REG,
+ .pull_down = BUCK2_PULL_DOWN_SHIFT,
+ .mask_reset_reg = MASK_RESET_BUCK_REG,
+ .mask_reset = BUCK2_MASK_RESET,
+ },
+ {
+ .dt_node_name = "buck3",
+ .voltage_table = buck3_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
+ .control_reg = BUCK3_CONTROL_REG,
+ .low_power_reg = BUCK3_PWRCTRL_REG,
+ .pull_down_reg = BUCK_PULL_DOWN_REG,
+ .pull_down = BUCK3_PULL_DOWN_SHIFT,
+ .mask_reset_reg = MASK_RESET_BUCK_REG,
+ .mask_reset = BUCK3_MASK_RESET,
+ },
+ {
+ .dt_node_name = "buck4",
+ .voltage_table = buck4_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
+ .control_reg = BUCK4_CONTROL_REG,
+ .low_power_reg = BUCK4_PWRCTRL_REG,
+ .pull_down_reg = BUCK_PULL_DOWN_REG,
+ .pull_down = BUCK4_PULL_DOWN_SHIFT,
+ .mask_reset_reg = MASK_RESET_BUCK_REG,
+ .mask_reset = BUCK4_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo1",
+ .voltage_table = ldo1_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
+ .control_reg = LDO1_CONTROL_REG,
+ .low_power_reg = LDO1_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO1_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo2",
+ .voltage_table = ldo2_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
+ .control_reg = LDO2_CONTROL_REG,
+ .low_power_reg = LDO2_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO2_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo3",
+ .voltage_table = ldo3_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
+ .control_reg = LDO3_CONTROL_REG,
+ .low_power_reg = LDO3_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO3_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo4",
+ .voltage_table = ldo4_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
+ .control_reg = LDO4_CONTROL_REG,
+ .low_power_reg = LDO4_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO4_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo5",
+ .voltage_table = ldo5_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
+ .control_reg = LDO5_CONTROL_REG,
+ .low_power_reg = LDO5_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO5_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo6",
+ .voltage_table = ldo6_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
+ .control_reg = LDO6_CONTROL_REG,
+ .low_power_reg = LDO6_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO6_MASK_RESET,
+ },
+ {
+ .dt_node_name = "vref_ddr",
+ .voltage_table = vref_ddr_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
+ .control_reg = VREF_DDR_CONTROL_REG,
+ .low_power_reg = VREF_DDR_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = VREF_DDR_MASK_RESET,
+ },
+};
+
+#define MAX_REGUL ARRAY_SIZE(regulators_table)
+
+static const struct regul_struct *get_regulator_data(const char *name)
+{
+ uint8_t i;
+
+ for (i = 0 ; i < MAX_REGUL ; i++) {
+ if (strncmp(name, regulators_table[i].dt_node_name,
+ strlen(regulators_table[i].dt_node_name)) == 0) {
+ return &regulators_table[i];
+ }
+ }
+
+ /* Regulator not found */
+ panic();
+ return NULL;
+}
+
+static uint8_t voltage_to_index(const char *name, uint16_t millivolts)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+ uint8_t i;
+
+ for (i = 0 ; i < regul->voltage_table_size ; i++) {
+ if (regul->voltage_table[i] == millivolts) {
+ return i;
+ }
+ }
+
+ /* Voltage not found */
+ panic();
+
+ return 0;
+}
+
+int stpmic1_powerctrl_on(void)
+{
+ return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID,
+ PWRCTRL_PIN_VALID);
+}
+
+int stpmic1_switch_off(void)
+{
+ return stpmic1_register_update(MAIN_CONTROL_REG, 1,
+ SOFTWARE_SWITCH_OFF_ENABLED);
+}
+
+int stpmic1_regulator_enable(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0));
+}
+
+int stpmic1_regulator_disable(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->control_reg, 0, BIT(0));
+}
+
+uint8_t stpmic1_is_regulator_enabled(const char *name)
+{
+ uint8_t val;
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ if (stpmic1_register_read(regul->control_reg, &val) != 0) {
+ panic();
+ }
+
+ return (val & 0x1U);
+}
+
+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts)
+{
+ uint8_t voltage_index = voltage_to_index(name, millivolts);
+ const struct regul_struct *regul = get_regulator_data(name);
+ uint8_t mask;
+
+ /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
+ if (strncmp(name, "buck", 4) == 0) {
+ mask = BUCK_VOLTAGE_MASK;
+ } else if ((strncmp(name, "ldo", 3) == 0) &&
+ (strncmp(name, "ldo4", 4) != 0)) {
+ mask = LDO_VOLTAGE_MASK;
+ } else {
+ return 0;
+ }
+
+ return stpmic1_register_update(regul->control_reg,
+ voltage_index << LDO_BUCK_VOLTAGE_SHIFT,
+ mask);
+}
+
+int stpmic1_regulator_pull_down_set(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ if (regul->pull_down_reg != 0) {
+ return stpmic1_register_update(regul->pull_down_reg,
+ BIT(regul->pull_down),
+ LDO_BUCK_PULL_DOWN_MASK <<
+ regul->pull_down);
+ }
+
+ return 0;
+}
+
+int stpmic1_regulator_mask_reset_set(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->mask_reset_reg,
+ BIT(regul->mask_reset),
+ LDO_BUCK_RESET_MASK <<
+ regul->mask_reset);
+}
+
+/* Low-power functions */
+int stpmic1_lp_copy_reg(const char *name)
+{
+ uint8_t val;
+ int status;
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ status = stpmic1_register_read(regul->control_reg, &val);
+ if (status != 0) {
+ return status;
+ }
+
+ return stpmic1_register_write(regul->low_power_reg, val);
+}
+
+int stpmic1_lp_reg_on_off(const char *name, uint8_t enable)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->low_power_reg, enable,
+ LDO_BUCK_ENABLE_MASK);
+}
+
+int stpmic1_lp_set_mode(const char *name, uint8_t hplp)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->low_power_reg,
+ hplp << LDO_BUCK_HPLP_SHIFT,
+ LDO_BUCK_HPLP_ENABLE_MASK);
+}
+
+int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts)
+{
+ uint8_t voltage_index = voltage_to_index(name, millivolts);
+ const struct regul_struct *regul = get_regulator_data(name);
+ uint8_t mask;
+
+ /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
+ if (strncmp(name, "buck", 4) == 0) {
+ mask = BUCK_VOLTAGE_MASK;
+ } else if ((strncmp(name, "ldo", 3) == 0) &&
+ (strncmp(name, "ldo4", 4) != 0)) {
+ mask = LDO_VOLTAGE_MASK;
+ } else {
+ return 0;
+ }
+
+ return stpmic1_register_update(regul->low_power_reg, voltage_index << 2,
+ mask);
+}
+
+int stpmic1_regulator_voltage_get(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+ uint8_t value;
+ uint8_t mask;
+
+ /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
+ if (strncmp(name, "buck", 4) == 0) {
+ mask = BUCK_VOLTAGE_MASK;
+ } else if ((strncmp(name, "ldo", 3) == 0) &&
+ (strncmp(name, "ldo4", 4) != 0)) {
+ mask = LDO_VOLTAGE_MASK;
+ } else {
+ return 0;
+ }
+
+ if (stpmic1_register_read(regul->control_reg, &value))
+ return -1;
+
+ value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT;
+
+ if (value > regul->voltage_table_size)
+ return -1;
+
+ return (int)regul->voltage_table[value];
+}
+
+int stpmic1_register_read(uint8_t register_id, uint8_t *value)
+{
+ return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr,
+ (uint16_t)register_id,
+ I2C_MEMADD_SIZE_8BIT, value,
+ 1, I2C_TIMEOUT_MS);
+}
+
+int stpmic1_register_write(uint8_t register_id, uint8_t value)
+{
+ int status;
+
+ status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr,
+ (uint16_t)register_id,
+ I2C_MEMADD_SIZE_8BIT, &value,
+ 1, I2C_TIMEOUT_MS);
+
+#if ENABLE_ASSERTIONS
+ if (status != 0) {
+ return status;
+ }
+
+ if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
+ uint8_t readval;
+
+ status = stpmic1_register_read(register_id, &readval);
+ if (status != 0) {
+ return status;
+ }
+
+ if (readval != value) {
+ return -1;
+ }
+ }
+#endif
+
+ return status;
+}
+
+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
+{
+ int status;
+ uint8_t val;
+
+ status = stpmic1_register_read(register_id, &val);
+ if (status != 0) {
+ return status;
+ }
+
+ val = (val & ~mask) | (value & mask);
+
+ return stpmic1_register_write(register_id, val);
+}
+
+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
+{
+ pmic_i2c_handle = i2c_handle;
+ pmic_i2c_addr = i2c_addr;
+}
+
+void stpmic1_dump_regulators(void)
+{
+ uint32_t i;
+
+ for (i = 0U; i < MAX_REGUL; i++) {
+ const char *name __unused = regulators_table[i].dt_node_name;
+
+ VERBOSE("PMIC regul %s: %sable, %dmV",
+ name,
+ stpmic1_is_regulator_enabled(name) ? "en" : "dis",
+ stpmic1_regulator_voltage_get(name));
+ }
+}
+
+int stpmic1_get_version(unsigned long *version)
+{
+ int rc;
+ uint8_t read_val;
+
+ rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
+ if (rc) {
+ return -1;
+ }
+
+ *version = (unsigned long)read_val;
+
+ return 0;
+}
diff --git a/drivers/st/pmic/stpmu1.c b/drivers/st/pmic/stpmu1.c
deleted file mode 100644
index 5951899..0000000
--- a/drivers/st/pmic/stpmu1.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <debug.h>
-#include <platform.h>
-#include <stpmu1.h>
-#include <string.h>
-
-struct regul_struct {
- const char *dt_node_name;
- const uint16_t *voltage_table;
- uint8_t voltage_table_size;
- uint8_t control_reg;
- uint8_t low_power_reg;
-};
-
-static struct i2c_handle_s *stpmu_i2c_handle;
-static uint16_t stpmu_i2c_addr;
-
-/* Voltage tables in mV */
-static const uint16_t buck1_voltage_table[] = {
- 600,
- 625,
- 650,
- 675,
- 700,
- 725,
- 750,
- 775,
- 800,
- 825,
- 850,
- 875,
- 900,
- 925,
- 950,
- 975,
- 1000,
- 1025,
- 1050,
- 1075,
- 1100,
- 1125,
- 1150,
- 1175,
- 1200,
- 1225,
- 1250,
- 1275,
- 1300,
- 1325,
- 1350,
- 1350,
-};
-
-static const uint16_t buck2_voltage_table[] = {
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1050,
- 1050,
- 1100,
- 1100,
- 1150,
- 1150,
- 1200,
- 1200,
- 1250,
- 1250,
- 1300,
- 1300,
- 1350,
- 1350,
- 1400,
- 1400,
- 1450,
- 1450,
- 1500,
-};
-
-static const uint16_t buck3_voltage_table[] = {
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1000,
- 1100,
- 1100,
- 1100,
- 1100,
- 1200,
- 1200,
- 1200,
- 1200,
- 1300,
- 1300,
- 1300,
- 1300,
- 1400,
- 1400,
- 1400,
- 1400,
- 1500,
- 1600,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
- 3400,
-};
-
-static const uint16_t buck4_voltage_table[] = {
- 600,
- 625,
- 650,
- 675,
- 700,
- 725,
- 750,
- 775,
- 800,
- 825,
- 850,
- 875,
- 900,
- 925,
- 950,
- 975,
- 1000,
- 1025,
- 1050,
- 1075,
- 1100,
- 1125,
- 1150,
- 1175,
- 1200,
- 1225,
- 1250,
- 1275,
- 1300,
- 1300,
- 1350,
- 1350,
- 1400,
- 1400,
- 1450,
- 1450,
- 1500,
- 1600,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
- 3400,
- 3500,
- 3600,
- 3700,
- 3800,
- 3900,
-};
-
-static const uint16_t ldo1_voltage_table[] = {
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
-};
-
-static const uint16_t ldo2_voltage_table[] = {
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
-};
-
-static const uint16_t ldo3_voltage_table[] = {
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
- 3300,
- 3300,
- 3300,
- 3300,
- 3300,
- 3300,
- 0xFFFF, /* VREFDDR */
-};
-
-static const uint16_t ldo5_voltage_table[] = {
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
- 3400,
- 3500,
- 3600,
- 3700,
- 3800,
- 3900,
-};
-
-static const uint16_t ldo6_voltage_table[] = {
- 900,
- 1000,
- 1100,
- 1200,
- 1300,
- 1400,
- 1500,
- 1600,
- 1700,
- 1800,
- 1900,
- 2000,
- 2100,
- 2200,
- 2300,
- 2400,
- 2500,
- 2600,
- 2700,
- 2800,
- 2900,
- 3000,
- 3100,
- 3200,
- 3300,
-};
-
-static const uint16_t ldo4_voltage_table[] = {
- 3300,
-};
-
-static const uint16_t vref_ddr_voltage_table[] = {
- 3300,
-};
-
-/* Table of Regulators in PMIC SoC */
-static const struct regul_struct regulators_table[] = {
- {
- .dt_node_name = "buck1",
- .voltage_table = buck1_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
- .control_reg = BUCK1_CONTROL_REG,
- .low_power_reg = BUCK1_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck2",
- .voltage_table = buck2_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
- .control_reg = BUCK2_CONTROL_REG,
- .low_power_reg = BUCK2_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck3",
- .voltage_table = buck3_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
- .control_reg = BUCK3_CONTROL_REG,
- .low_power_reg = BUCK3_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck4",
- .voltage_table = buck4_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
- .control_reg = BUCK4_CONTROL_REG,
- .low_power_reg = BUCK4_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo1",
- .voltage_table = ldo1_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
- .control_reg = LDO1_CONTROL_REG,
- .low_power_reg = LDO1_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo2",
- .voltage_table = ldo2_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
- .control_reg = LDO2_CONTROL_REG,
- .low_power_reg = LDO2_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo3",
- .voltage_table = ldo3_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
- .control_reg = LDO3_CONTROL_REG,
- .low_power_reg = LDO3_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo4",
- .voltage_table = ldo4_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
- .control_reg = LDO4_CONTROL_REG,
- .low_power_reg = LDO4_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo5",
- .voltage_table = ldo5_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
- .control_reg = LDO5_CONTROL_REG,
- .low_power_reg = LDO5_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo6",
- .voltage_table = ldo6_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
- .control_reg = LDO6_CONTROL_REG,
- .low_power_reg = LDO6_PWRCTRL_REG,
- },
- {
- .dt_node_name = "vref_ddr",
- .voltage_table = vref_ddr_voltage_table,
- .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
- .control_reg = VREF_DDR_CONTROL_REG,
- .low_power_reg = VREF_DDR_PWRCTRL_REG,
- },
-};
-
-#define MAX_REGUL ARRAY_SIZE(regulators_table)
-
-static const struct regul_struct *stpmu1_get_regulator_data(const char *name)
-{
- uint8_t i;
-
- for (i = 0 ; i < MAX_REGUL ; i++) {
- if (strncmp(name, regulators_table[i].dt_node_name,
- strlen(regulators_table[i].dt_node_name)) == 0) {
- return &regulators_table[i];
- }
- }
-
- /* Regulator not found */
- panic();
- return NULL;
-}
-
-static uint8_t stpmu1_voltage_find_index(const char *name,
- uint16_t millivolts)
-{
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
- uint8_t i;
-
- for (i = 0 ; i < regul->voltage_table_size ; i++) {
- if (regul->voltage_table[i] == millivolts) {
- return i;
- }
- }
-
- /* Voltage not found */
- panic();
-
- return 0;
-}
-
-int stpmu1_switch_off(void)
-{
- return stpmu1_register_update(MAIN_CONTROL_REG, 1,
- SOFTWARE_SWITCH_OFF_ENABLED);
-}
-
-int stpmu1_regulator_enable(const char *name)
-{
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0));
-}
-
-int stpmu1_regulator_disable(const char *name)
-{
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, 0, BIT(0));
-}
-
-uint8_t stpmu1_is_regulator_enabled(const char *name)
-{
- uint8_t val;
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- if (stpmu1_register_read(regul->control_reg, &val) != 0) {
- panic();
- }
-
- return (val & 0x1U);
-}
-
-int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts)
-{
- uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts);
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, voltage_index << 2,
- 0xFC);
-}
-
-int stpmu1_register_read(uint8_t register_id, uint8_t *value)
-{
- return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr,
- (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT,
- value, 1, 100000);
-}
-
-int stpmu1_register_write(uint8_t register_id, uint8_t value)
-{
- int status;
-
- status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr,
- (uint16_t)register_id,
- I2C_MEMADD_SIZE_8BIT, &value, 1, 100000);
-
- if (status != 0) {
- return status;
- }
-
- if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
- uint8_t readval;
-
- status = stpmu1_register_read(register_id, &readval);
- if (status != 0) {
- return status;
- }
-
- if (readval != value) {
- return -1;
- }
- }
-
- return 0;
-}
-
-int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
-{
- int status;
- uint8_t val;
-
- status = stpmu1_register_read(register_id, &val);
- if (status != 0) {
- return status;
- }
-
- /* Clear bits to update */
- val &= ~mask;
-
- /* Update appropriate bits*/
- val |= (value & mask);
-
- /* Send new value on I2C Bus */
- return stpmu1_register_write(register_id, val);
-}
-
-void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
-{
- stpmu_i2c_handle = i2c_handle;
- stpmu_i2c_addr = i2c_addr;
-}
diff --git a/drivers/st/qspi/io_qspi.c b/drivers/st/qspi/io_qspi.c
new file mode 100644
index 0000000..b00b7d6
--- /dev/null
+++ b/drivers/st/qspi/io_qspi.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_qspi.h>
+#include <io_storage.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <string.h>
+
+#define QSPI_COMPAT "st,stm32f469-qspi"
+
+#define TIMEOUT_100_US us2tick(100)
+
+/* QSPI device functions */
+static int qspi_dev_open(const uintptr_t init_params,
+ io_dev_info_t **dev_info);
+static int qspi_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity);
+static int qspi_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int qspi_block_seek(io_entity_t *entity, int mode,
+ signed long long offset);
+static int qspi_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read);
+static int qspi_block_close(io_entity_t *entity);
+static int qspi_dev_close(io_dev_info_t *dev_info);
+static io_type_t device_type_qspi(void);
+
+static QSPI_HandleTypeDef *hsd;
+static uint64_t seek_offset;
+
+static struct dt_node_info qspi_node_info;
+static uintptr_t qspi_mm_base;
+static size_t qspi_mm_size;
+static bool qspi_memory_map;
+
+static const io_dev_connector_t qspi_dev_connector = {
+ .dev_open = qspi_dev_open
+};
+
+static const io_dev_funcs_t qspi_dev_funcs = {
+ .type = device_type_qspi,
+ .open = qspi_block_open,
+ .seek = qspi_block_seek,
+ .size = NULL,
+ .read = qspi_block_read,
+ .write = NULL,
+ .close = qspi_block_close,
+ .dev_init = qspi_dev_init,
+ .dev_close = qspi_dev_close,
+};
+
+static const io_dev_info_t qspi_dev_info = {
+ .funcs = &qspi_dev_funcs,
+ .info = (uintptr_t)0,
+};
+
+/* Identify the device type as memmap */
+static io_type_t device_type_qspi(void)
+{
+ return IO_TYPE_QSPI;
+}
+
+/* Open a connection to the qspi device */
+static int qspi_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
+{
+ int qspi_node;
+ int qspi_subnode = 0;
+ int ret;
+ uint32_t fsize;
+ uint32_t flash_max_freq = 0;
+ uint32_t div = 8U; /* Default clock divider */
+ uint32_t presc;
+ void *fdt;
+ const fdt32_t *cuint = NULL;
+
+ assert(dev_info);
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ hsd = (QSPI_HandleTypeDef *)init_params;
+
+ qspi_node = dt_get_node(&qspi_node_info, -1, QSPI_COMPAT);
+ assert(qspi_node_info.base == (uintptr_t)hsd->instance);
+
+ *dev_info = (io_dev_info_t *)&qspi_dev_info;
+
+ ret = fdt_get_reg_props_by_name(qspi_node, "qspi_mm", &qspi_mm_base,
+ &qspi_mm_size);
+ if (ret != 0) {
+ INFO("NOR: Indirect mode\n");
+ qspi_memory_map = false;
+
+ /*
+ * Indirect mode is already initialized by bootrom:
+ * no configuration to be done.
+ */
+ return 0;
+ }
+
+ /* Size of NOR is 2^(fsise + 1) */
+ fsize = ((__builtin_ctz(qspi_mm_size) - 1) << QSPI_DCR_FSIZE_SHIFT) &
+ QSPI_DCR_FSIZE_MASK;
+
+ /* switch to memory mapped mode */
+ INFO("NOR: Memory mapped mode\n");
+ qspi_memory_map = true;
+
+ fdt_for_each_subnode(qspi_subnode, fdt, qspi_node) {
+ cuint = fdt_getprop(fdt, qspi_subnode, "reg", NULL);
+
+ if ((cuint != NULL) && (fdt32_to_cpu(*cuint) == 0U)) {
+ /* Flash node found */
+ cuint = fdt_getprop(fdt, qspi_subnode,
+ "spi-max-frequency", NULL);
+ if (cuint != NULL) {
+ flash_max_freq = fdt32_to_cpu(*cuint);
+ }
+
+ break;
+ }
+ }
+
+ if (flash_max_freq != 0) {
+ div = div_round_up(stm32mp_clk_get_rate(qspi_node_info.clock),
+ flash_max_freq);
+ }
+
+ presc = div - 1U;
+
+ if (presc > UINT8_MAX) {
+ presc = UINT8_MAX;
+ }
+
+ presc <<= QSPI_CR_PRESCALER_SHIFT;
+
+ /* Check if QuadSPI was configured in dual flash mode */
+ if ((hsd->instance->CR & QSPI_CR_DFM) != 0U) {
+ hsd->instance->CR = QSPI_CR_EN | presc | QSPI_CR_DFM;
+ if (hsd->is_dual == 0U) {
+ WARN("Dual NOR configured in IP\n");
+ WARN(" but set as single in boot context\n");
+ WARN(" -> Try Dual NOR boot\n");
+ }
+ } else {
+ hsd->instance->CR = QSPI_CR_EN | presc;
+ if (hsd->is_dual != 0U) {
+ WARN("Single NOR configured in IP\n");
+ WARN(" but set as dual in boot context\n");
+ WARN(" -> Try Single NOR boot\n");
+ }
+ }
+
+ hsd->instance->DCR = fsize | QSPI_DCR_CSHT;
+ hsd->instance->CCR = QSPI_DFLT_READ_FLAGS | QSPI_CCR_FMODE_MM;
+
+ return 0;
+}
+
+static int qspi_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+ return 0;
+}
+
+/* Close a connection to the qspi device */
+static int qspi_dev_close(io_dev_info_t *dev_info)
+{
+ uint64_t start;
+
+ /* Send Abort command to end all transfers */
+ hsd->instance->CR |= QSPI_CR_ABORT;
+
+ start = timeout_start();
+ while ((hsd->instance->CR & QSPI_CR_ABORT) != 0U) {
+ if (timeout_elapsed(start, TIMEOUT_100_US)) {
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+/* Open a file on the qspi device */
+static int qspi_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity)
+{
+ seek_offset = 0;
+ return 0;
+}
+
+/* Seek to a particular file offset on the qspi device */
+static int qspi_block_seek(io_entity_t *entity, int mode,
+ signed long long offset)
+{
+ seek_offset = offset;
+ return 0;
+}
+
+/* Read blocks in indirect mode */
+static int qspi_block_read_indr(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint32_t local_length = (uint32_t)length;
+ uint8_t *data = (uint8_t *)buffer;
+ uint8_t *qspi_dr_u8;
+ uint64_t start;
+ int ret = 0;
+
+ assert(hsd);
+
+ qspi_dr_u8 = (uint8_t *)&hsd->instance->DR;
+
+ /* Clear all flags */
+ hsd->instance->FCR = QSPI_SR_TCF | QSPI_SR_FTF |
+ QSPI_FCR_CTOF | QSPI_FCR_CSMF;
+ hsd->instance->DLR = local_length - 1;
+ hsd->instance->CCR = QSPI_DFLT_READ_FLAGS | QSPI_CCR_FMODE;
+ hsd->instance->AR = seek_offset;
+
+ while (local_length != 0U) {
+ *data++ = *qspi_dr_u8;
+ local_length--;
+ }
+
+ *length_read = length;
+
+ start = timeout_start();
+ while ((hsd->instance->SR & QSPI_SR_BUSY) != 0U) {
+ if (timeout_elapsed(start, TIMEOUT_100_US)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int qspi_block_read_mm_part(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint64_t start;
+ int ret = 0;
+
+ assert(hsd);
+
+ memcpy((uint8_t *)buffer, (uint8_t *)qspi_mm_base + seek_offset,
+ length);
+
+ *length_read = length;
+
+ start = timeout_start();
+ while ((hsd->instance->SR & QSPI_SR_BUSY) != 0U) {
+ if (timeout_elapsed(start, TIMEOUT_100_US)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ /* Send abort to avoid prefetch issues */
+ hsd->instance->CR |= QSPI_CR_ABORT;
+
+ start = timeout_start();
+ while ((hsd->instance->CR & QSPI_CR_ABORT) != 0U) {
+ if (timeout_elapsed(start, TIMEOUT_100_US)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+/* Read blocks in memory map mode */
+static int qspi_block_read_mm(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ if (seek_offset + length + 1 >= qspi_mm_size) {
+ if (length > QSPI_NOR_LBA_SIZE) {
+ size_t length_read_mm, length_read_indr;
+
+ qspi_block_read_mm_part(entity, buffer,
+ length - QSPI_NOR_LBA_SIZE,
+ &length_read_mm);
+
+ seek_offset += length - QSPI_NOR_LBA_SIZE;
+
+ qspi_block_read_indr(entity, buffer + length -
+ QSPI_NOR_LBA_SIZE,
+ QSPI_NOR_LBA_SIZE,
+ &length_read_indr);
+
+ *length_read = length_read_mm + length_read_indr;
+ } else {
+ qspi_block_read_indr(entity, buffer, length,
+ length_read);
+ }
+ } else {
+ qspi_block_read_mm_part(entity, buffer, length, length_read);
+ }
+
+ return 0;
+
+}
+
+/* Read data from a file on the qspi device */
+static int qspi_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ if (qspi_memory_map) {
+ return qspi_block_read_mm(entity, buffer, length, length_read);
+ }
+
+ return qspi_block_read_indr(entity, buffer, length, length_read);
+}
+
+/* Close a file on the qspi device */
+static int qspi_block_close(io_entity_t *entity)
+{
+ return 0;
+}
+
+/* Exported functions */
+
+/* Register the qspi driver with the IO abstraction */
+int register_io_dev_qspi(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con);
+
+ result = io_register_device(&qspi_dev_info);
+ if (result == 0) {
+ *dev_con = &qspi_dev_connector;
+ }
+
+ return result;
+}
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index 106bbfe..2e19ef0 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -6,34 +6,66 @@
#include <bl_common.h>
#include <debug.h>
+#include <delay_timer.h>
#include <limits.h>
#include <mmio.h>
#include <platform_def.h>
-#include <stm32mp1_rcc.h>
-#include <stm32mp1_reset.h>
+#include <stm32mp_common.h>
+#include <stm32mp_reset.h>
#include <utils_def.h>
-#define RST_CLR_OFFSET 4U
+#define RST_CLR_OFFSET 4U
+#define RESET_TIMEOUT_1MS_IN_US 1000
+#define RESET_TIMEOUT_STEP_US 10
-void stm32mp1_reset_assert(uint32_t id)
+static uint32_t id2reg_offset(unsigned int reset_id)
{
- uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t);
- uint32_t bit = id % (uint32_t)__LONG_BIT;
+ return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t);
+}
+
+static uint8_t id2reg_bit_pos(unsigned int reset_id)
+{
+ return (uint8_t)(reset_id & GENMASK(4, 0));
+}
+
+void stm32mp_reset_assert(uint32_t id)
+{
+ uint32_t offset = id2reg_offset(id);
+ uint32_t bitmsk = BIT(id2reg_bit_pos(id));
+ int nb_tries = RESET_TIMEOUT_1MS_IN_US / RESET_TIMEOUT_STEP_US;
+ uintptr_t rcc_base = stm32mp_rcc_base();
- mmio_write_32(RCC_BASE + offset, BIT(bit));
- while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) {
- ;
+ mmio_write_32(rcc_base + offset, bitmsk);
+
+ while (((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) &&
+ (nb_tries != 0)) {
+ udelay(RESET_TIMEOUT_STEP_US);
+ nb_tries--;
+ }
+
+ if (nb_tries == 0) {
+ ERROR("Reset timeout\n");
+ panic();
}
}
-void stm32mp1_reset_deassert(uint32_t id)
+void stm32mp_reset_deassert(uint32_t id)
{
- uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) +
- RST_CLR_OFFSET;
- uint32_t bit = id % (uint32_t)__LONG_BIT;
+ uint32_t offset = id2reg_offset(id) + RST_CLR_OFFSET;
+ uint32_t bitmsk = BIT(id2reg_bit_pos(id));
+ int nb_tries = RESET_TIMEOUT_1MS_IN_US / RESET_TIMEOUT_STEP_US;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ mmio_write_32(rcc_base + offset, bitmsk);
+
+ while (((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) &&
+ (nb_tries != 0)) {
+ udelay(RESET_TIMEOUT_STEP_US);
+ nb_tries--;
+ }
- mmio_write_32(RCC_BASE + offset, BIT(bit));
- while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) {
- ;
+ if (nb_tries == 0) {
+ ERROR("Reset timeout\n");
+ panic();
}
}
diff --git a/drivers/st/rng/stm32_rng.c b/drivers/st/rng/stm32_rng.c
new file mode 100644
index 0000000..eec75b2
--- /dev/null
+++ b/drivers/st/rng/stm32_rng.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stm32_rng.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_reset.h>
+
+#define DT_RNG_COMPAT "st,stm32-rng"
+#define RNG_CR 0x00U
+#define RNG_SR 0x04U
+#define RNG_DR 0x08U
+
+#define RNG_CR_RNGEN BIT(2)
+#define RNG_CR_IE BIT(3)
+#define RNG_CR_CED BIT(5)
+
+#define RNG_SR_DRDY BIT(0)
+#define RNG_SR_CECS BIT(1)
+#define RNG_SR_SECS BIT(2)
+#define RNG_SR_CEIS BIT(5)
+#define RNG_SR_SEIS BIT(6)
+
+#define RNG_TIMEOUT_US 100000
+#define RNG_TIMEOUT_STEP_US 10
+
+struct stm32_rng_instance {
+ uintptr_t base;
+ unsigned long clock;
+};
+
+static struct stm32_rng_instance stm32_rng;
+
+/*
+ * stm32_rng_read - Read a number of random bytes from RNG
+ * out: pointer to the output buffer
+ * size: number of bytes to be read
+ * Return 0 on success, non-0 on failure
+ */
+int stm32_rng_read(uint8_t *out, uint32_t size)
+{
+ uint8_t *buf = out;
+ uint32_t len = size;
+ int nb_tries;
+ uint32_t data32;
+ int rc = 0;
+ int count;
+
+ if (stm32_rng.base == 0U) {
+ return -EPERM;
+ }
+
+ stm32mp_clk_enable(stm32_rng.clock);
+
+ if ((mmio_read_32(stm32_rng.base + RNG_CR) & RNG_CR_RNGEN) == 0U) {
+ mmio_write_32(stm32_rng.base + RNG_CR,
+ RNG_CR_RNGEN | RNG_CR_CED);
+ }
+
+ while (len != 0U) {
+ nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US;
+ do {
+ uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR);
+
+ if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
+ uint8_t i;
+
+ /* Recommended by the SoC reference manual */
+ mmio_clrbits_32(stm32_rng.base + RNG_SR,
+ RNG_SR_SEIS);
+ dmb();
+ for (i = 12; i != 0; i--) {
+ (void)mmio_read_32(stm32_rng.base +
+ RNG_DR);
+ }
+ dmb();
+
+ if ((mmio_read_32(stm32_rng.base + RNG_SR) &
+ RNG_SR_SEIS) != 0U) {
+ ERROR("RNG noise\n");
+ panic();
+ }
+ }
+
+ udelay(RNG_TIMEOUT_STEP_US);
+ nb_tries--;
+ if (nb_tries == 0) {
+ rc = -ETIMEDOUT;
+ goto bail;
+ }
+ } while ((mmio_read_32(stm32_rng.base + RNG_SR) &
+ RNG_SR_DRDY) == 0U);
+
+ count = 4;
+ while (len != 0U) {
+ data32 = mmio_read_32(stm32_rng.base + RNG_DR);
+ count--;
+
+ memcpy(buf, &data32, MIN(len, sizeof(uint32_t)));
+ buf += MIN(len, sizeof(uint32_t));
+ len -= MIN(len, sizeof(uint32_t));
+
+ if (count == 0) {
+ break;
+ }
+ }
+ }
+
+bail:
+ stm32mp_clk_disable(stm32_rng.clock);
+
+ if (rc != 0) {
+ memset(out, 0, buf - out);
+ }
+
+ return rc;
+}
+
+/*
+ * stm32_rng_init: Initialize rng from DT
+ * return 0 on success, negative value on failure
+ */
+int stm32_rng_init(void)
+{
+ void *fdt;
+ struct dt_node_info dt_rng;
+ int node;
+ uint8_t __unused test[43];
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT);
+ if (node < 0) {
+ return 0;
+ }
+
+ if ((dt_rng.status & DT_SECURE) == 0) {
+ return 0;
+ }
+
+ assert(dt_rng.base == RNG1_BASE);
+
+ stm32_rng.base = dt_rng.base;
+
+ if ((dt_rng.status & DT_NON_SECURE) == DT_NON_SECURE) {
+ stm32mp_register_non_secure_periph_iomem(stm32_rng.base);
+ } else {
+ stm32mp_register_secure_periph_iomem(stm32_rng.base);
+ }
+
+ if (dt_rng.clock < 0) {
+ panic();
+ }
+ stm32_rng.clock = (unsigned long)dt_rng.clock;
+
+ stm32mp_clk_enable(stm32_rng.clock);
+ stm32mp_clk_disable(stm32_rng.clock);
+
+ if (dt_rng.reset >= 0) {
+ stm32mp_reset_assert((unsigned long)dt_rng.reset);
+ udelay(20);
+ stm32mp_reset_deassert((unsigned long)dt_rng.reset);
+ }
+
+ VERBOSE("Init RNG done\n");
+
+#if STM32MP1_DEBUG_ENABLE
+ memset(test, 0xa5, sizeof(test));
+ if (stm32_rng_read(test, sizeof(test))) {
+ ERROR("RNG test\n");
+ panic();
+ }
+
+ VERBOSE("RNG test:\n");
+ VERBOSE_HEXDUMP8(test, sizeof(test));
+#endif
+
+ return 0;
+}
diff --git a/drivers/st/rtc/stm32_rtc.c b/drivers/st/rtc/stm32_rtc.c
new file mode 100644
index 0000000..017c46d
--- /dev/null
+++ b/drivers/st/rtc/stm32_rtc.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <spinlock.h>
+#include <stm32_rtc.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_dt.h>
+
+#define RTC_COMPAT "st,stm32mp1-rtc"
+
+#define RTC_TR_SU_MASK GENMASK(3, 0)
+#define RTC_TR_ST_MASK GENMASK(6, 4)
+#define RTC_TR_ST_SHIFT 4
+#define RTC_TR_MNU_MASK GENMASK(11, 8)
+#define RTC_TR_MNU_SHIFT 8
+#define RTC_TR_MNT_MASK GENMASK(14, 12)
+#define RTC_TR_MNT_SHIFT 12
+#define RTC_TR_HU_MASK GENMASK(19, 16)
+#define RTC_TR_HU_SHIFT 16
+#define RTC_TR_HT_MASK GENMASK(21, 20)
+#define RTC_TR_HT_SHIFT 20
+#define RTC_TR_PM BIT(22)
+
+#define RTC_DR_DU_MASK GENMASK(3, 0)
+#define RTC_DR_DT_MASK GENMASK(5, 4)
+#define RTC_DR_DT_SHIFT 4
+#define RTC_DR_MU_MASK GENMASK(11, 8)
+#define RTC_DR_MU_SHIFT 8
+#define RTC_DR_MT BIT(12)
+#define RTC_DR_MT_SHIFT 12
+#define RTC_DR_WDU_MASK GENMASK(15, 13)
+#define RTC_DR_WDU_SHIFT 13
+#define RTC_DR_YU_MASK GENMASK(19, 16)
+#define RTC_DR_YU_SHIFT 16
+#define RTC_DR_YT_MASK GENMASK(23, 20)
+#define RTC_DR_YT_SHIFT 20
+
+#define RTC_SSR_SS_MASK GENMASK(15, 0)
+
+#define RTC_ICSR_ALRAWF BIT(0)
+#define RTC_ICSR_RSF BIT(5)
+
+#define RTC_PRER_PREDIV_S_MASK GENMASK(14, 0)
+
+#define RTC_CR_BYPSHAD BIT(5)
+#define RTC_CR_BYPSHAD_SHIFT 5
+#define RTC_CR_ALRAE BIT(8)
+#define RTC_CR_ALRAIE BIT(12)
+#define RTC_CR_TAMPTS BIT(25)
+
+#define RTC_SMCR_TS_DPROT BIT(3)
+
+#define RTC_TSDR_DU_MASK GENMASK(3, 0)
+#define RTC_TSDR_DU_SHIFT 0
+#define RTC_TSDR_DT_MASK GENMASK(5, 4)
+#define RTC_TSDR_DT_SHIFT 4
+#define RTC_TSDR_MU_MASK GENMASK(11, 8)
+#define RTC_TSDR_MU_SHIFT 8
+
+#define RTC_ALRMAR_DU_SHIFT 24
+
+#define RTC_SR_TSF BIT(3)
+#define RTC_SR_TSOVF BIT(4)
+
+#define RTC_SCR_CTSF BIT(3)
+#define RTC_SCR_CTSOVF BIT(4)
+
+#define RTC_WPR_KEY1 0xCA
+#define RTC_WPR_KEY2 0x53
+#define RTC_WPR_KEY_LOCK 0xFF
+
+static struct dt_node_info rtc_dev;
+
+static struct spinlock lock;
+
+void stm32_rtc_regs_lock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Lock is currently required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_lock(&lock);
+ }
+}
+
+void stm32_rtc_regs_unlock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Unlock is required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_unlock(&lock);
+ }
+}
+
+static void stm32_rtc_write_unprotect(void)
+{
+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY1);
+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY2);
+}
+
+static void stm32_rtc_write_protect(void)
+{
+ mmio_write_32(rtc_dev.base + RTC_WPR, RTC_WPR_KEY_LOCK);
+}
+
+/*******************************************************************************
+ * This function gets the BYPSHAD bit value of the RTC_CR register.
+ * It will determine if we need to reset RTC_ISCR.RSF after each RTC calendar
+ * read, and also wait for RTC_ISCR.RSF=1 before next read.
+ * Returns true or false depending on the bit value.
+ ******************************************************************************/
+static bool stm32_rtc_get_bypshad(void)
+{
+ return ((mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_BYPSHAD) >>
+ RTC_CR_BYPSHAD_SHIFT) != 0U;
+}
+
+/*******************************************************************************
+ * This function reads the RTC calendar register values.
+ * If shadow registers are not bypassed, then a reset/poll is done.
+ ******************************************************************************/
+static void stm32_rtc_read_calendar(struct stm32_rtc_calendar *calendar)
+{
+ bool bypshad = stm32_rtc_get_bypshad();
+
+ if (!bypshad) {
+ mmio_clrbits_32((uint32_t)(rtc_dev.base + RTC_ICSR),
+ RTC_ICSR_RSF);
+ while ((mmio_read_32(rtc_dev.base + RTC_ICSR) & RTC_ICSR_RSF) !=
+ RTC_ICSR_RSF) {
+ ;
+ }
+ }
+
+ calendar->ssr = mmio_read_32(rtc_dev.base + RTC_SSR);
+ calendar->tr = mmio_read_32(rtc_dev.base + RTC_TR);
+ calendar->dr = mmio_read_32(rtc_dev.base + RTC_DR);
+}
+
+/*******************************************************************************
+ * This function fill the rtc_time structure based on rtc_calendar register.
+ ******************************************************************************/
+static void stm32_rtc_get_time(struct stm32_rtc_calendar *cal,
+ struct stm32_rtc_time *tm)
+{
+ assert(cal != NULL);
+ assert(tm != NULL);
+
+ tm->hour = (((cal->tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10U) +
+ ((cal->tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT);
+
+ if ((cal->tr & RTC_TR_PM) != 0U) {
+ tm->hour += 12U;
+ }
+
+ tm->min = (((cal->tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10U) +
+ ((cal->tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT);
+ tm->sec = (((cal->tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10U) +
+ (cal->tr & RTC_TR_SU_MASK);
+}
+
+/*******************************************************************************
+ * This function fill the rtc_time structure with the given date register.
+ ******************************************************************************/
+static void stm32_rtc_get_date(struct stm32_rtc_calendar *cal,
+ struct stm32_rtc_time *tm)
+{
+ assert(cal != NULL);
+ assert(tm != NULL);
+
+ tm->wday = (((cal->dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT));
+
+ tm->day = (((cal->dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10U) +
+ (cal->dr & RTC_DR_DU_MASK);
+
+ tm->month = (((cal->dr & RTC_DR_MT) >> RTC_DR_MT_SHIFT) * 10U) +
+ ((cal->dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT);
+
+ tm->year = (((cal->dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10U) +
+ ((cal->dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + 2000U;
+}
+
+/*******************************************************************************
+ * This function reads the RTC timestamp register values and update time
+ * structure with the corresponding value.
+ ******************************************************************************/
+static void stm32_rtc_read_timestamp(struct stm32_rtc_time *time)
+{
+ assert(time != NULL);
+
+ struct stm32_rtc_calendar cal_tamp;
+
+ cal_tamp.tr = mmio_read_32(rtc_dev.base + RTC_TSTR);
+ cal_tamp.dr = mmio_read_32(rtc_dev.base + RTC_TSDR);
+ stm32_rtc_get_time(&cal_tamp, time);
+ stm32_rtc_get_date(&cal_tamp, time);
+}
+
+/*******************************************************************************
+ * This function gets the RTC calendar register values.
+ * It takes into account the need of reading twice or not, depending on
+ * frequencies previously setted, and the bypass or not of the shadow
+ * registers. This service is exposed externally.
+ ******************************************************************************/
+void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar)
+{
+ bool read_twice = stm32mp1_rtc_get_read_twice();
+
+ stm32_rtc_regs_lock();
+ stm32mp_clk_enable(rtc_dev.clock);
+
+ stm32_rtc_read_calendar(calendar);
+
+ if (read_twice) {
+ uint32_t tr_save = calendar->tr;
+
+ stm32_rtc_read_calendar(calendar);
+
+ if (calendar->tr != tr_save) {
+ stm32_rtc_read_calendar(calendar);
+ }
+ }
+
+ stm32mp_clk_disable(rtc_dev.clock);
+ stm32_rtc_regs_unlock();
+}
+
+/*******************************************************************************
+ * This function computes the second fraction in milliseconds.
+ * The returned value is a uint32_t between 0 and 1000.
+ ******************************************************************************/
+static uint32_t stm32_rtc_get_second_fraction(struct stm32_rtc_calendar *cal)
+{
+ uint32_t prediv_s = mmio_read_32(rtc_dev.base + RTC_PRER) &
+ RTC_PRER_PREDIV_S_MASK;
+ uint32_t ss = cal->ssr & RTC_SSR_SS_MASK;
+
+ return ((prediv_s - ss) * 1000U) / (prediv_s + 1U);
+}
+
+/*******************************************************************************
+ * This function computes the fraction difference between two timestamps.
+ * Here again the returned value is in milliseconds.
+ ******************************************************************************/
+static unsigned long long stm32_rtc_diff_frac(struct stm32_rtc_calendar *cur,
+ struct stm32_rtc_calendar *ref)
+{
+ unsigned long long val_r;
+ unsigned long long val_c;
+
+ val_r = stm32_rtc_get_second_fraction(ref);
+ val_c = stm32_rtc_get_second_fraction(cur);
+
+ if (val_c >= val_r) {
+ return val_c - val_r;
+ } else {
+ return 1000U - val_r + val_c;
+ }
+}
+
+/*******************************************************************************
+ * This function computes the time difference between two timestamps.
+ * It includes seconds, minutes and hours.
+ * Here again the returned value is in milliseconds.
+ ******************************************************************************/
+static unsigned long long stm32_rtc_diff_time(struct stm32_rtc_time *current,
+ struct stm32_rtc_time *ref)
+{
+ signed long long diff_in_s;
+ signed long long curr_s;
+ signed long long ref_s;
+
+ curr_s = (signed long long)current->sec +
+ (((signed long long)current->min +
+ (((signed long long)current->hour * 60))) * 60);
+
+ ref_s = (signed long long)ref->sec +
+ (((signed long long)ref->min +
+ (((signed long long)ref->hour * 60))) * 60);
+
+ diff_in_s = curr_s - ref_s;
+ if (diff_in_s < 0) {
+ diff_in_s += 24 * 60 * 60;
+ }
+
+ return (unsigned long long)diff_in_s * 1000U;
+}
+
+/*******************************************************************************
+ * This function determines if the year is leap or not.
+ * Returned value is true or false.
+ ******************************************************************************/
+static bool stm32_is_a_leap_year(uint32_t year)
+{
+ return ((year % 4U) == 0U) &&
+ (((year % 100U) != 0U) || ((year % 400U) == 0U));
+}
+
+/*******************************************************************************
+ * This function computes the date difference between two timestamps.
+ * It includes days, months, years, with exceptions.
+ * Here again the returned value is in milliseconds.
+ ******************************************************************************/
+static unsigned long long stm32_rtc_diff_date(struct stm32_rtc_time *current,
+ struct stm32_rtc_time *ref)
+{
+ uint32_t diff_in_days = 0;
+ uint32_t m;
+ static const uint8_t month_len[NB_MONTHS] = {
+ 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31
+ };
+
+ /* Get the number of non-entire month days */
+ if (current->day >= ref->day) {
+ diff_in_days += current->day - ref->day;
+ } else {
+ diff_in_days += (uint32_t)month_len[ref->month - 1U] -
+ ref->day + current->day;
+ }
+
+ /* Get the number of entire months, and compute the related days */
+ if (current->month > (ref->month + 1U)) {
+ for (m = (ref->month + 1U); (m < current->month) &&
+ (m < 12U); m++) {
+ diff_in_days += (uint32_t)month_len[m - 1U];
+ }
+ }
+
+ if (current->month < (ref->month - 1U)) {
+ for (m = 1U; (m < current->month) && (m < 12U); m++) {
+ diff_in_days += (uint32_t)month_len[m - 1U];
+ }
+
+ for (m = (ref->month + 1U); m < 12U; m++) {
+ diff_in_days += (uint32_t)month_len[m - 1U];
+ }
+ }
+
+ /* Get complete years */
+ if (current->year > (ref->year + 1U)) {
+ diff_in_days += (current->year - ref->year - 1U) * 365U;
+ }
+
+ /* Particular cases: leap years (one day more) */
+ if (diff_in_days > 0U) {
+ if (current->year == ref->year) {
+ if (stm32_is_a_leap_year(current->year)) {
+ if ((ref->month <= 2U) &&
+ (current->month >= 3U) &&
+ (current->day <= 28U)) {
+ diff_in_days++;
+ }
+ }
+ } else {
+ uint32_t y;
+
+ /* Ref year is leap */
+ if ((stm32_is_a_leap_year(ref->year)) &&
+ (ref->month <= 2U) && (ref->day <= 28U)) {
+ diff_in_days++;
+ }
+
+ /* Current year is leap */
+ if ((stm32_is_a_leap_year(current->year)) &&
+ (current->month >= 3U)) {
+ diff_in_days++;
+ }
+
+ /* Interleaved years are leap */
+ for (y = ref->year + 1U; y < current->year; y++) {
+ if (stm32_is_a_leap_year(y)) {
+ diff_in_days++;
+ }
+ }
+ }
+ }
+
+ return (24ULL * 60U * 60U * 1000U) * (unsigned long long)diff_in_days;
+}
+
+/*******************************************************************************
+ * This function computes the date difference between two rtc value.
+ * Here again the returned value is in milliseconds.
+ ******************************************************************************/
+unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *cur,
+ struct stm32_rtc_calendar *ref)
+{
+ unsigned long long diff_in_ms = 0;
+ struct stm32_rtc_time curr_t;
+ struct stm32_rtc_time ref_t;
+
+ stm32mp_clk_enable(rtc_dev.clock);
+
+ stm32_rtc_get_date(cur, &curr_t);
+ stm32_rtc_get_date(ref, &ref_t);
+ stm32_rtc_get_time(cur, &curr_t);
+ stm32_rtc_get_time(ref, &ref_t);
+
+ diff_in_ms += stm32_rtc_diff_frac(cur, ref);
+ diff_in_ms += stm32_rtc_diff_time(&curr_t, &ref_t);
+ diff_in_ms += stm32_rtc_diff_date(&curr_t, &ref_t);
+
+ stm32mp_clk_disable(rtc_dev.clock);
+
+ return diff_in_ms;
+}
+
+/*******************************************************************************
+ * This function fill the RTC timestamp structure.
+ ******************************************************************************/
+void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts)
+{
+ stm32_rtc_regs_lock();
+ stm32mp_clk_enable(rtc_dev.clock);
+
+ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSF) != 0U) {
+ /* Print timestamp for tamper event */
+ stm32_rtc_read_timestamp(tamp_ts);
+ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSF);
+ if ((mmio_read_32(rtc_dev.base + RTC_SR) & RTC_SR_TSOVF) !=
+ 0U) {
+ /* Overflow detected */
+ mmio_setbits_32(rtc_dev.base + RTC_SCR, RTC_SCR_CTSOVF);
+ }
+ }
+
+ stm32mp_clk_disable(rtc_dev.clock);
+ stm32_rtc_regs_unlock();
+}
+
+/*******************************************************************************
+ * This function enable the timestamp bit for tamper and secure timestamp
+ * access.
+ ******************************************************************************/
+void stm32_rtc_set_tamper_timestamp(void)
+{
+ stm32_rtc_regs_lock();
+ stm32mp_clk_enable(rtc_dev.clock);
+
+ stm32_rtc_write_unprotect();
+
+ /* Enable tamper timestamper */
+ mmio_setbits_32(rtc_dev.base + RTC_CR, RTC_CR_TAMPTS);
+
+ /* Secure Timestamp bit */
+ mmio_clrbits_32(rtc_dev.base + RTC_SMCR, RTC_SMCR_TS_DPROT);
+
+ stm32_rtc_write_protect();
+
+ stm32mp_clk_disable(rtc_dev.clock);
+ stm32_rtc_regs_unlock();
+}
+
+/*******************************************************************************
+ * This function return state of tamper timestamp.
+ ******************************************************************************/
+bool stm32_rtc_is_timestamp_enable(void)
+{
+ bool ret;
+
+ stm32mp_clk_enable(rtc_dev.clock);
+
+ ret = (mmio_read_32(rtc_dev.base + RTC_CR) & RTC_CR_TAMPTS) != 0U;
+
+ stm32mp_clk_disable(rtc_dev.clock);
+
+ return ret;
+}
+
+/*******************************************************************************
+ * RTC initialisation function.
+ ******************************************************************************/
+int stm32_rtc_init(void)
+{
+ int node;
+
+ node = dt_get_node(&rtc_dev, -1, RTC_COMPAT);
+ if (node < 0) {
+ return node;
+ }
+
+ if (rtc_dev.status == DT_SECURE) {
+ stm32mp_register_secure_periph_iomem(rtc_dev.base);
+ } else {
+ stm32mp_register_non_secure_periph_iomem(rtc_dev.base);
+ }
+
+ return 0;
+}
diff --git a/drivers/st/tamper/stm32_tamp.c b/drivers/st/tamper/stm32_tamp.c
new file mode 100644
index 0000000..0bfa177
--- /dev/null
+++ b/drivers/st/tamper/stm32_tamp.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32_rng.h>
+#include <stm32_rtc.h>
+#include <stm32_tamp.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+
+#define DT_TAMP_COMPAT "st,stm32-tamp"
+/* STM32 Registers */
+#define STM32_TAMP_CR1 0x00U
+#define STM32_TAMP_CR2 0x04U
+#define STM32_TAMP_FLTCR 0x0CU
+#define STM32_TAMP_ATCR 0x10U
+#define STM32_TAMP_ATSEEDR 0x14U
+#define STM32_TAMP_ATOR 0x18U
+#define STM32_TAMP_SMCR 0x20U
+#define STM32_TAMP_IER 0x2CU
+#define STM32_TAMP_SR 0x30U
+#define STM32_TAMP_SCR 0x3CU
+#define STM32_TAMP_COUNTR 0x40U
+#define STM32_TAMP_OR 0x50U
+#define STM32_TAMP_HWCFGR2 0x3ECU
+#define STM32_TAMP_HWCFGR1 0x3F0U
+#define STM32_TAMP_VERR 0x3F4U
+#define STM32_TAMP_IPIDR 0x3F8U
+#define STM32_TAMP_SIDR 0x3FCU
+
+/* STM32_TAMP_FLTCR bit fields */
+#define STM32_TAMP_FLTCR_TAMPFREQ GENMASK(2, 0)
+#define STM32_TAMP_FLTCR_TAMPFLT GENMASK(4, 3)
+#define STM32_TAMP_FLTCR_TAMPPRCH GENMASK(6, 5)
+#define STM32_TAMP_FLTCR_TAMPPUDIS BIT(7)
+
+/* STM32_TAMP_ATCR bit fields */
+#define STM32_TAMP_ATCR_ATCKSEL GENMASK(18, 16)
+#define STM32_TAMP_ATCR_ATPER GENMASK(26, 24)
+#define STM32_TAMP_ATCR_ATOSHARE BIT(30)
+#define STM32_TAMP_ATCR_FLTEN BIT(31)
+
+/* STM32_TAMP_ATOR bit fields */
+#define STM32_TAMP_PRNG GENMASK(7, 0)
+#define STM32_TAMP_SEEDF BIT(14)
+#define STM32_TAMP_INITS BIT(15)
+
+/* STM32_TAMP_IER bit fields */
+#define STM32_TAMP_IER_TAMPXIE_ALL GENMASK(7, 0)
+#define STM32_TAMP_IER_ITAMPXIE_ALL GENMASK(31, 16)
+
+/* STM32_TAMP_SR bit fields */
+#define STM32_TAMP_SR_TAMPXF_MASK GENMASK(7, 0)
+#define STM32_TAMP_SR_ITAMPXF_MASK GENMASK(31, 16)
+
+/* STM32_TAMP_SMCR but fields */
+#define STM32_TAMP_SMCR_DPROT BIT(31)
+
+/* STM32_TAMP_CFGR bit fields */
+#define STM32_TAMP_OR_OUT3RMP BIT(0)
+
+/* STM32_TAMP_HWCFGR2 bit fields */
+#define STM32_TAMP_HWCFGR2_TZ GENMASK(11, 8)
+#define STM32_TAMP_HWCFGR2_OR GENMASK(7, 0)
+
+/* STM32_TAMP_HWCFGR1 bit fields */
+#define STM32_TAMP_HWCFGR1_BKPREG GENMASK(7, 0)
+#define STM32_TAMP_HWCFGR1_TAMPER GENMASK(11, 8)
+#define STM32_TAMP_HWCFGR1_ACTIVE GENMASK(15, 12)
+#define STM32_TAMP_HWCFGR1_INTERN GENMASK(31, 16)
+
+/* STM32_TAMP_VERR bit fields */
+#define STM32_TAMP_VERR_MINREV GENMASK(3, 0)
+#define STM32_TAMP_VERR_MAJREV GENMASK(7, 4)
+
+#define STM32_TAMP_MAX_INTERNAL 16U
+#define STM32_TAMP_MAX_EXTERNAL 8U
+
+struct stm32_tamp_instance {
+ uintptr_t base;
+ uint32_t clock;
+ uint32_t hwconf1;
+ uint32_t hwconf2;
+ uint16_t int_nbtamp;
+ uint8_t ext_nbtamp;
+ struct stm32_tamp_int *int_tamp;
+ struct stm32_tamp_ext *ext_tamp;
+};
+
+static struct stm32_tamp_instance stm32_tamp;
+
+static void stm32_tamp_set_secured(unsigned long base)
+{
+ mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT);
+}
+
+static void stm32_tamp_configure_or(unsigned long base, uint32_t out3)
+{
+ mmio_setbits_32(base + STM32_TAMP_OR, out3);
+}
+
+static int stm32_tamp_seed_init(unsigned long base)
+{
+ /* Need RNG access */
+ uint32_t timeout = 100;
+ uint8_t idx;
+
+ for (idx = 0; idx < 4U; idx++) {
+ uint32_t rnd;
+
+ if (stm32_rng_read((uint8_t *)&rnd, sizeof(uint32_t)) != 0) {
+ return -1;
+ }
+
+ VERBOSE("Seed init %u\n", rnd);
+ mmio_write_32(base + STM32_TAMP_ATSEEDR, rnd);
+ }
+
+ while (((mmio_read_32(base + STM32_TAMP_ATOR) &
+ STM32_TAMP_SEEDF) != 0U) &&
+ (timeout != 0U)) {
+ timeout--;
+ }
+
+ if (timeout == 0U) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void stm32_tamp_reset_register(unsigned long base)
+{
+ /* Disable all internal tamper */
+ mmio_write_32(base + STM32_TAMP_CR1, 0U);
+
+ /* Disable all external tamper */
+ mmio_write_32(base + STM32_TAMP_CR2, 0U);
+
+ /* Clean configuration registers */
+ mmio_write_32(base + STM32_TAMP_FLTCR, 0U);
+ mmio_write_32(base + STM32_TAMP_ATCR, 0U);
+ mmio_clrbits_32(base + STM32_TAMP_SMCR, STM32_TAMP_SMCR_DPROT);
+
+ /* Clean Tamper IT */
+ mmio_write_32(base + STM32_TAMP_IER, 0U);
+ mmio_write_32(base + STM32_TAMP_SCR, ~0U);
+
+ mmio_clrbits_32(base + STM32_TAMP_OR, STM32_TAMP_OR_OUT3RMP);
+}
+
+void stm32_tamp_write_mcounter(void)
+{
+ mmio_write_32(stm32_tamp.base + STM32_TAMP_COUNTR, 1U);
+}
+
+void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list,
+ uint16_t nb_tamper)
+{
+ uint16_t i;
+
+ assert(nb_tamper < STM32_TAMP_MAX_INTERNAL);
+
+ for (i = 0; i < nb_tamper; i++) {
+ int id = tamper_list[i].id;
+ uint32_t u_id;
+
+ if (id == -1) {
+ continue;
+ }
+
+ u_id = (uint32_t)id;
+
+ if ((stm32_tamp.hwconf1 & BIT(u_id + 16U)) != 0U) {
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1,
+ BIT(u_id + 16U));
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER,
+ BIT(u_id + 16U));
+ }
+ }
+
+ stm32_tamp.int_tamp = tamper_list;
+ stm32_tamp.int_nbtamp = nb_tamper;
+}
+
+void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list,
+ uint8_t nb_tamper, uint32_t passive_conf,
+ uint32_t active_conf)
+{
+ /* External configuration */
+ uint8_t i, active_tamp = 0;
+
+ assert(nb_tamper < STM32_TAMP_MAX_EXTERNAL);
+
+ /* Enable external Tamp */
+ for (i = 0; i < nb_tamper; i++) {
+ int id = ext_tamper_list[i].id;
+ uint32_t reg = 0, u_id;
+
+ if (id == -1) {
+ continue;
+ }
+
+ u_id = (uint32_t)id;
+
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR1,
+ BIT(u_id));
+
+ if (ext_tamper_list[i].mode == TAMP_TRIG_ON) {
+ reg |= BIT(u_id + 24U);
+ }
+
+ if (ext_tamper_list[i].mode == TAMP_ACTIVE) {
+ active_tamp |= BIT(u_id);
+ }
+
+ if (ext_tamper_list[i].erase != 0U) {
+ reg |= BIT(u_id);
+ }
+
+ if (ext_tamper_list[i].evt_mask != 0U) {
+ reg |= BIT(u_id + 16U);
+ } else {
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_IER,
+ BIT(u_id));
+ }
+
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_CR2, reg);
+ }
+
+ /* Filter mode register set */
+ mmio_write_32(stm32_tamp.base + STM32_TAMP_FLTCR, passive_conf);
+
+ /* Active mode configuration */
+ if (active_tamp != 0U) {
+ mmio_write_32(stm32_tamp.base + STM32_TAMP_ATCR,
+ active_conf | active_tamp);
+ if (stm32_tamp_seed_init(stm32_tamp.base) != 0) {
+ ERROR("Active tamper: SEED not initialized\n");
+ panic();
+ }
+ }
+
+ stm32_tamp.ext_tamp = ext_tamper_list;
+ stm32_tamp.ext_nbtamp = nb_tamper;
+}
+
+void stm32_tamp_it_handler(void)
+{
+ uint32_t it = mmio_read_32(stm32_tamp.base + STM32_TAMP_SR);
+ uint8_t tamp = 0;
+ struct stm32_rtc_time tamp_ts;
+ struct stm32_tamp_int *int_list = stm32_tamp.int_tamp;
+ struct stm32_tamp_ext *ext_list = stm32_tamp.ext_tamp;
+
+ if (stm32_rtc_is_timestamp_enable()) {
+ stm32_rtc_get_timestamp(&tamp_ts);
+ INFO("Tamper Event Occurred\n");
+ INFO("Date : %u/%u\n \t Time : %u:%u:%u\n",
+ tamp_ts.day, tamp_ts.month, tamp_ts.hour,
+ tamp_ts.min, tamp_ts.sec);
+ }
+
+ /* Internal tamper interrupt */
+ if ((it & STM32_TAMP_IER_ITAMPXIE_ALL) == 0U) {
+ goto tamp_ext;
+ }
+
+ while ((it != 0U) && (tamp < stm32_tamp.int_nbtamp)) {
+ uint32_t int_id = (uint32_t)int_list[tamp].id;
+
+ if ((it & BIT(int_id + 16U)) != 0U) {
+ if (int_list[tamp].it_handler != NULL) {
+ int_list[tamp].it_handler();
+ }
+
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR,
+ BIT(int_id + 16U));
+ it &= ~BIT(int_id + 16U);
+ }
+ tamp++;
+ }
+
+tamp_ext:
+ tamp = 0;
+ /* External tamper interrupt */
+ if ((it == 0U) || ((it & STM32_TAMP_IER_TAMPXIE_ALL) == 0U)) {
+ return;
+ }
+
+ while ((it != 0U) && (tamp < stm32_tamp.ext_nbtamp)) {
+ uint32_t ext_id = (uint32_t)ext_list[tamp].id;
+
+ if ((it & BIT(ext_id)) != 0U) {
+ if (ext_list[tamp].it_handler != NULL) {
+ ext_list[tamp].it_handler();
+ }
+
+ mmio_setbits_32(stm32_tamp.base + STM32_TAMP_SCR,
+ BIT(ext_id));
+ it &= ~BIT(ext_id);
+ }
+ tamp++;
+ }
+}
+
+int stm32_tamp_init(void)
+{
+ int node;
+ struct dt_node_info dt_tamp;
+ void *fdt;
+ uint32_t rev __unused;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -EPERM;
+ }
+
+ node = dt_get_node(&dt_tamp, -1, DT_TAMP_COMPAT);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ assert(dt_tamp.base != 0U);
+ assert(dt_tamp.clock != -1);
+
+ stm32_tamp.base = dt_tamp.base;
+ stm32_tamp.clock = (uint32_t)dt_tamp.clock;
+
+ /* Init Tamp clock */
+ stm32mp_clk_enable(stm32_tamp.clock);
+
+ /* Reset Tamp register without modifying backup registers conf */
+ stm32_tamp_reset_register(stm32_tamp.base);
+
+ /* Check if tamper are secured */
+ if (dt_tamp.status != DT_SECURE) {
+ return 0;
+ }
+
+ stm32_tamp.hwconf1 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR1);
+ stm32_tamp.hwconf2 = mmio_read_32(stm32_tamp.base + STM32_TAMP_HWCFGR2);
+
+ rev = mmio_read_32(stm32_tamp.base + STM32_TAMP_VERR);
+ VERBOSE("STM32 TAMPER V%u.%u\n", (rev & STM32_TAMP_VERR_MAJREV) >> 4,
+ rev & STM32_TAMP_VERR_MINREV);
+
+ if ((stm32_tamp.hwconf2 & STM32_TAMP_HWCFGR2_TZ) == 0U) {
+ ERROR("Tamper IP doesn't support trustzone");
+ return -EPERM;
+ }
+
+ stm32_tamp_set_secured(stm32_tamp.base);
+
+ if (fdt_getprop(fdt, node, "st,out3-pc13", NULL) != NULL) {
+ stm32_tamp_configure_or(stm32_tamp.base, 1);
+ }
+
+ if (stm32_gic_enable_spi(node, NULL) != 0) {
+ panic();
+ }
+
+ if (fdt_getprop(fdt, node, "wakeup-source", NULL) != NULL) {
+ mmio_setbits_32(EXTI_BASE + EXTI_TZENR1, EXTI_TZENR1_TZEN18);
+ mmio_setbits_32(EXTI_BASE + EXTI_C1IMR1, EXTI_IMR1_IM18);
+ }
+
+ return 1;
+}
diff --git a/drivers/st/timer/stm32_timer.c b/drivers/st/timer/stm32_timer.c
new file mode 100644
index 0000000..6d36e31
--- /dev/null
+++ b/drivers/st/timer/stm32_timer.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stm32_timer.h>
+#include <stm32mp_dt.h>
+
+#define TIM_CR1 0x00U /* Control Register 1 */
+#define TIM_CR2 0x04U /* Control Register 2 */
+#define TIM_SMCR 0x08U /* Slave mode control reg */
+#define TIM_DIER 0x0CU /* DMA/interrupt register */
+#define TIM_SR 0x10U /* Status register */
+#define TIM_EGR 0x14U /* Event Generation Reg */
+#define TIM_CCMR1 0x18U /* Capt/Comp 1 Mode Reg */
+#define TIM_CCMR2 0x1CU /* Capt/Comp 2 Mode Reg */
+#define TIM_CCER 0x20U /* Capt/Comp Enable Reg */
+#define TIM_CNT 0x24U /* Counter */
+#define TIM_PSC 0x28U /* Prescaler */
+#define TIM_ARR 0x2CU /* Auto-Reload Register */
+#define TIM_CCR1 0x34U /* Capt/Comp Register 1 */
+#define TIM_CCR2 0x38U /* Capt/Comp Register 2 */
+#define TIM_CCR3 0x3CU /* Capt/Comp Register 3 */
+#define TIM_CCR4 0x40U /* Capt/Comp Register 4 */
+#define TIM_BDTR 0x44U /* Break and Dead-Time Reg */
+#define TIM_DCR 0x48U /* DMA control register */
+#define TIM_DMAR 0x4CU /* DMA transfer register */
+#define TIM_AF1 0x60U /* Alt Function Reg 1 */
+#define TIM_AF2 0x64U /* Alt Function Reg 2 */
+#define TIM_TISEL 0x68U /* Input Selection */
+
+#define TIM_CR1_CEN BIT(0)
+#define TIM_SMCR_SMS GENMASK(2, 0) /* Slave mode selection */
+#define TIM_SMCR_TS GENMASK(6, 4) /* Trigger selection */
+#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */
+#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */
+#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */
+#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
+#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
+#define TIM_SR_UIF BIT(0) /* UIF interrupt flag */
+#define TIM_SR_CC1IF BIT(1) /* CC1 interrupt flag */
+#define TIM_TISEL_TI1SEL_MASK GENMASK(3, 0)
+#define TIM_SMCR_SMS_RESET 0x4U
+#define TIM_SMCR_TS_SHIFT 4U
+#define TIM_SMCR_TS_TI1FP1 0x5U
+
+#define TIM_COMPAT "st,stm32-timers"
+#define TIM_TIMEOUT_US 100000
+#define TIM_TIMEOUT_STEP_US 10
+#define TIM_PRESCAL_HSI 10U
+#define TIM_PRESCAL_CSI 7U
+
+struct stm32_timer_instance {
+ uintptr_t base;
+ unsigned long clk;
+ unsigned long freq;
+ uint8_t cal_input;
+};
+
+static struct stm32_timer_instance stm32_timer[TIM_MAX_INSTANCE];
+
+static int stm32_timer_get_dt_node(struct dt_node_info *info, int offset)
+{
+ int node;
+
+ node = dt_get_node(info, offset, TIM_COMPAT);
+ if (node < 0) {
+ if (offset == -1) {
+ WARN("%s: No TIMER found\n", __func__);
+ }
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return node;
+}
+
+static void stm32_timer_config(struct stm32_timer_instance *timer)
+{
+ stm32mp_clk_enable(timer->clk);
+
+ timer->freq = stm32mp_clk_timer_get_rate(timer->clk);
+
+ if ((mmio_read_32(timer->base + TIM_TISEL) & TIM_TISEL_TI1SEL_MASK) !=
+ timer->cal_input) {
+ mmio_clrsetbits_32(timer->base + TIM_CCMR1,
+ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC1S_TI2,
+ TIM_CCMR_CC1S_TI1);
+
+ mmio_clrbits_32(timer->base + TIM_CCER,
+ TIM_CCER_CC1P | TIM_CCER_CC1NP);
+
+ mmio_clrsetbits_32(timer->base + TIM_SMCR,
+ TIM_SMCR_TS | TIM_SMCR_SMS,
+ (TIM_SMCR_TS_TI1FP1 << TIM_SMCR_TS_SHIFT) |
+ TIM_SMCR_SMS_RESET);
+
+ mmio_write_32(timer->base + TIM_TISEL, timer->cal_input);
+ mmio_setbits_32(timer->base + TIM_CR1, TIM_CR1_CEN);
+ mmio_setbits_32(timer->base + TIM_CCER, TIM_CCER_CC1E);
+ }
+
+ stm32mp_clk_disable(timer->clk);
+}
+
+static uint32_t stm32_timer_start_capture(struct stm32_timer_instance *timer)
+{
+ uint32_t timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US;
+ uint32_t counter = 0U;
+ uint32_t old_counter = 0U;
+ int twice = 0;
+
+ stm32_timer_config(timer);
+
+ stm32mp_clk_enable(timer->clk);
+
+ mmio_write_32(timer->base + TIM_SR, 0U);
+ while (((mmio_read_32(timer->base + TIM_SR) &
+ TIM_SR_UIF) == 0U) && (timeout != 0U)) {
+ udelay(TIM_TIMEOUT_STEP_US);
+ timeout--;
+ }
+
+ if (timeout == 0U) {
+ goto out;
+ }
+
+ mmio_write_32(timer->base + TIM_SR, 0U);
+
+ while ((twice < 2) || (old_counter != counter)) {
+ timeout = TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US;
+
+ while (((mmio_read_32(timer->base + TIM_SR) &
+ TIM_SR_CC1IF) == 0U) && (timeout != 0U)) {
+ udelay(TIM_TIMEOUT_STEP_US);
+ timeout--;
+ }
+ if (timeout == 0U) {
+ goto out;
+ }
+
+ old_counter = counter;
+ counter = mmio_read_32(timer->base + TIM_CCR1);
+ twice++;
+ }
+
+out:
+ stm32mp_clk_disable(timer->clk);
+
+ if (timeout == 0U) {
+ return 0U;
+ }
+
+ return counter;
+}
+
+unsigned long stm32_timer_hsi_freq(void)
+{
+ struct stm32_timer_instance *timer = &stm32_timer[HSI_CAL];
+ unsigned long hsi_freq;
+ uint32_t counter;
+
+ if (timer->base == 0) {
+ return 0;
+ }
+
+ counter = stm32_timer_start_capture(timer);
+ VERBOSE("Counter value %i\n", counter);
+
+ if (counter == 0U) {
+ return 0;
+ }
+
+ hsi_freq = (timer->freq / counter) << TIM_PRESCAL_HSI;
+
+ return hsi_freq;
+}
+
+unsigned long stm32_timer_csi_freq(void)
+{
+ struct stm32_timer_instance *timer = &stm32_timer[CSI_CAL];
+ unsigned long csi_freq;
+ uint32_t counter;
+
+ if (timer->base == 0) {
+ return 0;
+ }
+
+ counter = stm32_timer_start_capture(timer);
+ VERBOSE("Counter value %i\n", counter);
+
+ if (counter == 0U) {
+ return 0;
+ }
+
+ csi_freq = (timer->freq / counter) << TIM_PRESCAL_CSI;
+
+ return csi_freq;
+}
+
+/*
+ * Get the timer frequence callback function for a target clock calibration
+ * @timer_freq_cb - Output callback function
+ * @type - Target clock calibration ID
+ */
+void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void),
+ enum timer_cal type)
+{
+ switch (type) {
+ case HSI_CAL:
+ if (stm32_timer[HSI_CAL].base != 0) {
+ *timer_freq_cb = stm32_timer_hsi_freq;
+ }
+ break;
+
+ case CSI_CAL:
+ if (stm32_timer[CSI_CAL].base != 0) {
+ *timer_freq_cb = stm32_timer_csi_freq;
+ }
+ break;
+
+ default:
+ panic();
+ }
+}
+
+/*
+ * Initialize timer from DT
+ * return 0 if disabled, 1 if enabled, else < 0
+ */
+int stm32_timer_init(void)
+{
+ void *fdt;
+ struct dt_node_info dt_timer;
+ int node = -1;
+ uint8_t nb_timer = 0;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -EPERM;
+ }
+
+ for (node = stm32_timer_get_dt_node(&dt_timer, node);
+ node != -FDT_ERR_NOTFOUND;
+ node = stm32_timer_get_dt_node(&dt_timer, node)) {
+
+ if (dt_timer.status == DT_SECURE) {
+ struct stm32_timer_instance *timer;
+ const fdt32_t *cuint;
+
+ nb_timer++;
+
+ cuint = fdt_getprop(fdt, node, "st,hsi-cal-input",
+ NULL);
+ if (cuint != NULL) {
+ timer = &stm32_timer[HSI_CAL];
+ timer->base = dt_timer.base;
+ timer->clk = dt_timer.clock;
+ timer->freq =
+ stm32mp_clk_timer_get_rate(timer->clk);
+ timer->cal_input =
+ (uint8_t)fdt32_to_cpu(*cuint);
+ stm32_timer_config(timer);
+ }
+
+ cuint = fdt_getprop(fdt, node, "st,csi_cal-input",
+ NULL);
+ if (cuint != NULL) {
+ timer = &stm32_timer[CSI_CAL];
+ timer->base = dt_timer.base;
+ timer->clk = dt_timer.clock;
+ timer->freq =
+ stm32mp_clk_timer_get_rate(timer->clk);
+ timer->cal_input =
+ (uint8_t)fdt32_to_cpu(*cuint);
+ stm32_timer_config(timer);
+ }
+ }
+ }
+
+ VERBOSE("%u TIMER instance%s found\n", nb_timer,
+ nb_timer > 1 ? "s" : "");
+
+ if (nb_timer == 0U) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return 0;
+}
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index 792703a..823e38b 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -4,30 +4,27 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
+#include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
+#include <stm32_console.h>
+#include <stm32_uart_regs.h>
#define USART_TIMEOUT 0x1000
-#define USART_CR1 0x00
-#define USART_CR1_UE 0x00000001
-#define USART_CR1_TE 0x00000008
-#define USART_CR1_FIFOEN 0x20000000
-
-#define USART_CR2 0x04
-#define USART_CR2_STOP 0x00003000
-
-#define USART_BRR 0x0C
+ /*
+ * "core" functions are low-level implementations that don't require
+ * writeable memory and are thus safe to call in BL1 crash context.
+ */
+ .globl console_stm32_core_init
+ .globl console_stm32_core_putc
+ .globl console_stm32_core_getc
+ .globl console_stm32_core_flush
-#define USART_ISR 0x1C
-#define USART_ISR_TC 0x00000040
-#define USART_ISR_TXE 0x00000080
-#define USART_ISR_TEACK 0x00200000
+ .globl console_stm32_putc
+ .globl console_stm32_flush
-#define USART_TDR 0x28
- .globl console_core_init
- .globl console_core_putc
- .globl console_core_getc
- .globl console_core_flush
/* -----------------------------------------------------------------
* int console_core_init(uintptr_t base_addr,
@@ -45,7 +42,7 @@
* Clobber list : r1, r2, r3
* -----------------------------------------------------------------
*/
-func console_core_init
+func console_stm32_core_init
/* Check the input base address */
cmp r0, #0
beq core_init_fail
@@ -88,21 +85,55 @@ teack_loop:
core_init_fail:
mov r0, #0
bx lr
-endfunc console_core_init
+endfunc console_stm32_core_init
- /* ---------------------------------------------------------------
+ .globl console_stm32_register
+
+ /* -------------------------------------------------------
+ * int console_stm32_register(uintptr_t baseaddr,
+ * uint32_t clock, uint32_t baud,
+ * struct console_stm32 *console);
+ * Function to initialize and register a new STM32
+ * console. Storage passed in for the console struct
+ * *must* be persistent (i.e. not from the stack).
+ * In: r0 - UART register base address
+ * r1 - UART clock in Hz
+ * r2 - Baud rate
+ * r3 - pointer to empty console_stm32 struct
+ * Out: return 1 on success, 0 on error
+ * Clobber list : r0, r1, r2
+ * -------------------------------------------------------
+ */
+func console_stm32_register
+ push {r4, lr}
+ mov r4, r3
+ cmp r4, #0
+ beq register_fail
+ str r0, [r4, #CONSOLE_T_STM32_BASE]
+
+ bl console_stm32_core_init
+ cmp r0, #0
+ beq register_fail
+
+ mov r0, r4
+ pop {r4, lr}
+ finish_console_register stm32 putc=1, getc=0, flush=1
+
+register_fail:
+ pop {r4, pc}
+endfunc console_stm32_register
+
+ /* --------------------------------------------------------
* int console_core_putc(int c, uintptr_t base_addr)
- *
- * Function to output a character over the console. It returns the
- * character printed on success or -1 on error.
- *
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
* In : r0 - character to be printed
* r1 - console base address
* Out : return -1 on error else return character.
- * Clobber list : r2
- * ---------------------------------------------------------------
+ * Clobber list : r2, r3
+ * --------------------------------------------------------
*/
-func console_core_putc
+func console_stm32_core_putc
/* Check the input parameter */
cmp r1, #0
beq putc_error
@@ -111,26 +142,38 @@ func console_core_putc
bne 2f
1:
/* Check Transmit Data Register Empty */
+ mov r3, #USART_TIMEOUT
txe_loop_1:
+ subs r3, r3, #1
+ beq putc_error
ldr r2, [r1, #USART_ISR]
tst r2, #USART_ISR_TXE
beq txe_loop_1
mov r2, #0xD
str r2, [r1, #USART_TDR]
/* Check transmit complete flag */
+ mov r3, #USART_TIMEOUT
tc_loop_1:
+ subs r3, r3, #1
+ beq putc_error
ldr r2, [r1, #USART_ISR]
tst r2, #USART_ISR_TC
beq tc_loop_1
2:
/* Check Transmit Data Register Empty */
+ mov r3, #USART_TIMEOUT
txe_loop_2:
+ subs r3, r3, #1
+ beq putc_error
ldr r2, [r1, #USART_ISR]
tst r2, #USART_ISR_TXE
beq txe_loop_2
str r0, [r1, #USART_TDR]
/* Check transmit complete flag */
+ mov r3, #USART_TIMEOUT
tc_loop_2:
+ subs r3, r3, #1
+ beq putc_error
ldr r2, [r1, #USART_ISR]
tst r2, #USART_ISR_TC
beq tc_loop_2
@@ -138,7 +181,26 @@ tc_loop_2:
putc_error:
mov r0, #-1
bx lr
-endfunc console_core_putc
+endfunc console_stm32_core_putc
+
+ /* ------------------------------------------------------------
+ * int console_stm32_putc(int c, struct console_stm32 *console)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In: r0 - character to be printed
+ * r1 - pointer to console_t structure
+ * Out : return -1 on error else return character.
+ * Clobber list: r2
+ * ------------------------------------------------------------
+ */
+func console_stm32_putc
+#if ENABLE_ASSERTIONS
+ cmp r1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r1, [r1, #CONSOLE_T_STM32_BASE]
+ b console_stm32_core_putc
+endfunc console_stm32_putc
/* -----------------------------------------------------------
* int console_core_getc(uintptr_t base_addr)
@@ -151,11 +213,11 @@ endfunc console_core_putc
* Clobber list : r0, r1
* -----------------------------------------------------------
*/
-func console_core_getc
+func console_stm32_core_getc
/* Not supported */
mov r0, #-1
bx lr
-endfunc console_core_getc
+endfunc console_stm32_core_getc
/* ---------------------------------------------------------------
* int console_core_flush(uintptr_t base_addr)
@@ -165,14 +227,17 @@ endfunc console_core_getc
*
* In : r0 - console base address
* Out : return -1 on error else return 0.
- * Clobber list : r0, r1
+ * Clobber list : r0, r1, r2
* ---------------------------------------------------------------
*/
-func console_core_flush
+func console_stm32_core_flush
cmp r0, #0
beq flush_error
/* Check Transmit Data Register Empty */
+ mov r2, #USART_TIMEOUT
txe_loop_3:
+ subs r2, r2, #1
+ beq flush_error
ldr r1, [r0, #USART_ISR]
tst r1, #USART_ISR_TXE
beq txe_loop_3
@@ -181,4 +246,22 @@ txe_loop_3:
flush_error:
mov r0, #-1
bx lr
-endfunc console_core_flush
+endfunc console_stm32_core_flush
+
+ /* ------------------------------------------------------
+ * int console_stm32_flush(struct console_stm32 *console)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : r0 - pointer to console_t structure
+ * Out : return -1 on error else return 0.
+ * Clobber list: r0, r1
+ * ------------------------------------------------------
+ */
+func console_stm32_flush
+#if ENABLE_ASSERTIONS
+ cmp r0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr r0, [r0, #CONSOLE_T_STM32_BASE]
+ b console_stm32_core_flush
+endfunc console_stm32_flush
diff --git a/drivers/st/uart/io_programmer_uart.c b/drivers/st/uart/io_programmer_uart.c
new file mode 100644
index 0000000..34a7cbb
--- /dev/null
+++ b/drivers/st/uart/io_programmer_uart.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <errno.h>
+#include <io_driver.h>
+#include <io_programmer.h>
+#include <io_stm32image.h>
+#include <io_storage.h>
+#include <io_uart.h>
+#include <platform_def.h>
+#include <stm32_iwdg.h>
+#include <stm32mp_auth.h>
+#include <stm32mp_dt.h>
+#include <string.h>
+
+/* USART bootloader protocol version V4.0*/
+#define USART_BL_VERSION 0x40
+
+#define UART_ISR_ERRORS (USART_ISR_ORE | USART_ISR_NE | \
+ USART_ISR_FE | USART_ISR_PE)
+
+/* array of supported command */
+static const uint8_t command_tab[] = {
+ GET_CMD_COMMAND,
+ GET_VER_COMMAND,
+ GET_ID_COMMAND,
+ PHASE_COMMAND,
+ START_COMMAND,
+ DOWNLOAD_COMMAND
+};
+
+static uint8_t header_buffer[512] __aligned(4);
+static int32_t header_length_read;
+
+/* UART device functions */
+static int uart_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info);
+static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity);
+static int uart_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read);
+static int uart_block_close(io_entity_t *entity);
+static int uart_dev_close(io_dev_info_t *dev_info);
+static int uart_block_len(io_entity_t *entity, size_t *length);
+static io_type_t device_type_uart(void);
+
+/* variables */
+static const io_dev_connector_t uart_dev_connector = {
+ .dev_open = uart_dev_open
+};
+
+static const io_dev_funcs_t uart_dev_funcs = {
+ .type = device_type_uart,
+ .open = uart_block_open,
+ .seek = NULL,
+ .size = uart_block_len,
+ .read = uart_block_read,
+ .write = NULL,
+ .close = uart_block_close,
+ .dev_init = uart_dev_init,
+ .dev_close = uart_dev_close,
+};
+
+static const io_dev_info_t uart_dev_info = {
+ .funcs = &uart_dev_funcs,
+ .info = (uintptr_t)0,
+};
+
+static UART_HandleTypeDef *uart_handle_programmer;
+
+/* Identify the device type as memmap */
+static io_type_t device_type_uart(void)
+{
+ return IO_TYPE_UART;
+}
+
+static int uart_write_byte(uint8_t byte)
+{
+ if (HAL_UART_GetState(uart_handle_programmer) == HAL_UART_STATE_RESET)
+ uart_handle_programmer->gState = HAL_UART_STATE_READY;
+ return HAL_UART_Transmit(uart_handle_programmer, (uint8_t *)&byte, 1,
+ PROGRAMMER_TIMEOUT);
+}
+
+static int uart_write_uint32(uint32_t value)
+{
+ if (HAL_UART_GetState(uart_handle_programmer) == HAL_UART_STATE_RESET)
+ uart_handle_programmer->gState = HAL_UART_STATE_READY;
+ return HAL_UART_Transmit(uart_handle_programmer, (uint8_t *)&value, 4,
+ PROGRAMMER_TIMEOUT);
+}
+
+static int uart_read_byte(uint8_t *byte)
+{
+ HAL_StatusTypeDef ret;
+
+ if (HAL_UART_GetState(uart_handle_programmer) == HAL_UART_STATE_RESET)
+ uart_handle_programmer->RxState = HAL_UART_STATE_READY;
+
+ ret = HAL_UART_Receive(uart_handle_programmer, byte, 1,
+ PROGRAMMER_TIMEOUT);
+
+ if (ret || (uart_handle_programmer->Instance->ISReg & UART_ISR_ERRORS))
+ return -EIO;
+
+ return 0;
+}
+
+static void uart_flush_rx_fifo(uint32_t timeout)
+{
+ uint8_t byte = 0;
+
+ /* Clear all errors */
+ __HAL_UART_CLEAR_FLAG(uart_handle_programmer, UART_ISR_ERRORS);
+
+ while ((__HAL_UART_GET_FLAG(uart_handle_programmer, UART_FLAG_RXNE) !=
+ RESET) && timeout) {
+ timeout--;
+ uart_read_byte(&byte);
+ }
+}
+
+/* Open a connection to the uart device */
+static int uart_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
+{
+ int result = 0;
+
+ assert(dev_info);
+ *dev_info = (io_dev_info_t *)&uart_dev_info;
+
+ uart_handle_programmer = (UART_HandleTypeDef *)init_params;
+
+ /* Init UART to enable FIFO mode */
+ if (HAL_UART_Init(uart_handle_programmer) != HAL_OK) {
+ return -EIO;
+ }
+
+ uart_flush_rx_fifo(PROGRAMMER_TIMEOUT);
+
+ uart_write_byte(NACK_BYTE);
+
+ return result;
+}
+
+static int uart_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+ return 0;
+}
+
+/* Close a connection to the uart device */
+static int uart_dev_close(io_dev_info_t *dev_info)
+{
+ return 0;
+}
+
+/* Return the size of a file on the uart device */
+static int uart_block_len(io_entity_t *entity, size_t *length)
+{
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)&header_buffer[0];
+
+ assert(entity);
+ assert(length);
+
+ header_length_read = 0;
+ header->magic = 0;
+
+ uart_block_read(entity, (uintptr_t)&header_buffer[0],
+ sizeof(boot_api_image_header_t),
+ (size_t *)&header_length_read);
+
+ if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB)
+ return -EIO;
+
+ if (header->image_length > current_phase.max_size)
+ return -EIO;
+
+ *length = header->image_length;
+
+ INFO("binary size 0x%x\n", header->image_length);
+
+ return 0;
+}
+
+/* Open a file on the uart device */
+static int uart_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+ io_entity_t *entity)
+{
+ int result = -EIO;
+ const struct stm32image_part_info *partition_spec =
+ (struct stm32image_part_info *)spec;
+ uint32_t length = 0;
+ uint32_t layout_length = 0;
+
+ /* Use PHASE_FSBL1 like init value*/
+ if (current_phase.phase_id == PHASE_FSBL1) {
+ assert(partition_spec);
+ assert(entity);
+
+ current_phase.current_packet = 0;
+
+ if (!strcmp(partition_spec->name, BL33_IMAGE_NAME)) {
+ /* read flashlayout first for U-boot */
+ current_phase.phase_id = PHASE_FLASHLAYOUT;
+ current_phase.max_size = FLASHLAYOUT_LIMIT;
+ current_phase.keep_header = 1;
+ uart_block_len(entity, &layout_length);
+ uart_block_read(entity, FLASHLAYOUT_BASE,
+ layout_length,
+ &length);
+
+ flush_dcache_range((unsigned long)FLASHLAYOUT_BASE,
+ layout_length +
+ sizeof(boot_api_image_header_t));
+
+ current_phase.current_packet = 0;
+ current_phase.phase_id = PHASE_SSBL;
+ current_phase.max_size = dt_get_ddr_size();
+ current_phase.keep_header = 0;
+ }
+ entity->info = (uintptr_t)&current_phase;
+ result = 0;
+ } else {
+ WARN("A UART device is already active. Close first.\n");
+ result = -EIO;
+ }
+ return result;
+}
+
+static int uart_receive_command(uint8_t *command)
+{
+ uint8_t byte = 0;
+ uint8_t xor = 0;
+ uint8_t counter = 0, found = 0;
+ int ret;
+
+ /* check command */
+ ret = uart_read_byte(&byte);
+ if (ret)
+ return ret;
+
+ for (counter = 0; counter < sizeof(command_tab); counter++) {
+ if (command_tab[counter] == byte) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ ret = uart_read_byte(&xor);
+ if (ret)
+ return ret;
+ if ((byte ^ xor) != 0xFF) {
+ WARN("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n",
+ byte, xor);
+ return -EPROTO;
+ }
+ } else {
+ if (byte != INIT_BYTE) {
+ WARN("UART: Command unknown (byte=0x%x)\n", byte);
+ return -EPROTO;
+ }
+ }
+
+ *command = byte;
+
+ return 0;
+}
+
+static int get_cmd_command(void)
+{
+ uint8_t counter = 0x0;
+
+ uart_write_byte(sizeof(command_tab));
+ uart_write_byte(USART_BL_VERSION);
+
+ for (counter = 0; counter < sizeof(command_tab); counter++)
+ uart_write_byte(command_tab[counter]);
+
+ return 0;
+}
+
+static int get_version_command(void)
+{
+ uart_write_byte(STM32_TF_VERSION);
+
+ return 0;
+}
+
+static int get_id_command(void)
+{
+ /* Send Device IDCode */
+ uart_write_byte(0x1);
+ uart_write_byte(DEVICE_ID_BYTE1);
+ uart_write_byte(DEVICE_ID_BYTE2);
+
+ return 0;
+}
+
+static int uart_send_phase(uint32_t address)
+{
+ uart_write_byte(0x05); /* length of data - 1 */
+ /* Send the ID of next partition */
+ uart_write_byte(current_phase.phase_id); /* partition ID */
+
+ uart_write_uint32(address); /* destination address */
+ uart_write_byte(0x00); /* length of extra data */
+
+ return 0;
+}
+
+static int uart_download_part(uint8_t *buffer, uint32_t *length_read)
+{
+ uint8_t byte = 0;
+ uint8_t xor = 0;
+ uint8_t operation = 0;
+ uint32_t packet_number = 0;
+ uint8_t packet_size = 0;
+ int i = 0;
+ volatile uint8_t *ptr = (uint8_t *)buffer;
+
+ /* get operation number */
+ if (uart_read_byte(&operation))
+ return -EIO;
+ xor = operation;
+
+ /* get packet Number */
+ for (i = 3, byte = 0; i > 0; i--) {
+ if (uart_read_byte(&byte))
+ return -EIO;
+ xor ^= byte;
+ packet_number = (packet_number << 8) | byte;
+ }
+
+ if (packet_number != current_phase.current_packet) {
+ WARN("UART: Bad packet number receive: %i\n", packet_number);
+ return -EPROTO;
+ }
+
+ /* checksum */
+ if (uart_read_byte(&byte))
+ return -EIO;
+
+ if (xor != byte) {
+ WARN("UART: Download Command header checksum fail: calculated xor: %i, received xor:%i\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ uart_write_byte(ACK_BYTE);
+
+ if (uart_read_byte(&packet_size))
+ return -EIO;
+
+ xor = packet_size;
+
+ for (i = packet_size; i >= 0; i--) {
+ /* Reload watchdog, once every 8 loops */
+ if (i % 8)
+ stm32_iwdg_refresh(IWDG2_INST);
+
+ if (uart_read_byte(&byte))
+ return -EIO;
+ *(volatile uint8_t *)ptr = byte;
+ xor ^= byte;
+ ptr++;
+ }
+
+ /* checksum */
+ if (uart_read_byte(&byte))
+ return -EIO;
+
+ if (xor != byte) {
+ WARN("UART: Download Command data checksum fail: calculated xor: 0x%x, received xor:0x%x\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ current_phase.current_packet++;
+ *length_read = (uint32_t)packet_size + 1;
+
+ return 0;
+}
+
+static int uart_start_cmd(boot_api_image_header_t *header, uintptr_t buffer)
+{
+ uint8_t byte = 0;
+ uint8_t xor = 0;
+ int i = 0;
+ uint32_t start_address = 0;
+ int result = 0;
+
+ /* get address */
+ for (i = 4; i > 0; i--) {
+ if (uart_read_byte(&byte))
+ return -EIO;
+ xor ^= byte;
+ start_address = (start_address << 8) | byte;
+ }
+
+ /* checksum */
+ if (uart_read_byte(&byte))
+ return -EIO;
+
+ if (xor != byte) {
+ WARN("UART: Start command checksum fail: calculated xor: %i, received xor:%i\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ switch (current_phase.phase_id) {
+ case PHASE_FLASHLAYOUT:
+ result = check_header(header, buffer +
+ sizeof(boot_api_image_header_t));
+ if (result)
+ return result;
+ break;
+
+ case PHASE_SSBL:
+ if (start_address != BL33_BASE) {
+ VERBOSE("BL33 address provided: 0x%x, using: 0x%x\n",
+ start_address, BL33_BASE);
+ }
+
+ result = check_header(header, buffer);
+ if (result)
+ return result;
+
+#ifdef AUTHENTICATE_BL33
+ result = check_authentication(header, buffer);
+ if (result != 0) {
+ return result;
+ }
+#else
+ NOTICE("Authentication disabled: No signature check\n");
+#endif
+ break;
+
+ default:
+ ERROR("Invalid phase ID : %i\n", current_phase.phase_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Read data from the uart device */
+static int uart_block_read(io_entity_t *entity, uintptr_t buffer,
+ size_t length, size_t *length_read)
+{
+ uint32_t read_length = 0;
+ uint32_t total_length = 0;
+ uint32_t ptr_offset = 0;
+ uint8_t command = 0;
+ uint8_t all_commands_done = 0;
+ boot_api_image_header_t *header =
+ (boot_api_image_header_t *)&header_buffer[0];
+
+ if (header_length_read && current_phase.keep_header) {
+ memcpy((uint8_t *)buffer, (uint8_t *)&header_buffer[0],
+ header_length_read);
+ ptr_offset += header_length_read;
+ } else if (header_length_read &&
+ ((header_length_read -
+ sizeof(boot_api_image_header_t)) > 0)) {
+ memcpy((uint8_t *)buffer,
+ (uint8_t *)
+ &header_buffer[sizeof(boot_api_image_header_t)],
+ header_length_read -
+ sizeof(boot_api_image_header_t));
+ ptr_offset += header_length_read -
+ sizeof(boot_api_image_header_t);
+ }
+
+ while (!all_commands_done) {
+ int result;
+
+ /* Reload watchdog */
+ stm32_iwdg_refresh(IWDG2_INST);
+
+ result = uart_receive_command(&command);
+ if (result) {
+ if (result == -EIO) {
+ WARN("UART: device error on command receive\n");
+ }
+
+ mdelay(2);
+
+ uart_flush_rx_fifo(PROGRAMMER_TIMEOUT);
+ uart_write_byte(NACK_BYTE);
+ continue;
+ }
+
+ /* Send ack */
+ uart_write_byte(ACK_BYTE);
+
+ switch (command) {
+ case INIT_BYTE:
+ /* Nothing to do */
+ continue;
+ case GET_CMD_COMMAND:
+ result = get_cmd_command();
+ break;
+
+ case GET_VER_COMMAND:
+ result = get_version_command();
+ break;
+
+ case GET_ID_COMMAND:
+ result = get_id_command();
+ break;
+
+ case PHASE_COMMAND:
+ result = uart_send_phase((uint32_t)buffer);
+ break;
+
+ case DOWNLOAD_COMMAND:
+ result = uart_download_part((uint8_t *)(buffer +
+ ptr_offset),
+ &read_length);
+ if (!result) {
+ ptr_offset += read_length;
+ total_length += read_length;
+ if ((total_length >= length) &&
+ !header_length_read) {
+ /* read header only go out*/
+ all_commands_done = 1;
+ }
+ }
+
+ break;
+
+ case START_COMMAND:
+ result = uart_start_cmd(header, buffer);
+ if (!result)
+ all_commands_done = 1;
+
+ break;
+
+ default:
+ /* Not supported command */
+ WARN("UART: Unknown command\n");
+ uart_flush_rx_fifo(PROGRAMMER_TIMEOUT);
+ uart_write_byte(NACK_BYTE);
+ continue;
+ }
+ if (!result) {
+ /* Send ack */
+ uart_write_byte(ACK_BYTE);
+ } else if (result == -EPROTO) {
+ uart_flush_rx_fifo(0xFFFF);
+ uart_write_byte(NACK_BYTE);
+ } else {
+ uart_flush_rx_fifo(PROGRAMMER_TIMEOUT);
+ uart_write_byte(NACK_BYTE);
+ continue;
+ }
+ }
+
+ *length_read = total_length;
+
+ INFO("Read block in buffer 0x%lx size 0x%x phase ID %i\n",
+ buffer, length, current_phase.phase_id);
+
+ return 0;
+}
+
+/* Close a file on the uart device */
+static int uart_block_close(io_entity_t *entity)
+{
+ current_phase.phase_id = PHASE_FSBL1;
+
+ return 0;
+}
+
+/* Exported functions */
+
+/* Register the uart driver with the IO abstraction */
+int register_io_dev_uart(const io_dev_connector_t **dev_con)
+{
+ int result;
+
+ assert(dev_con);
+
+ result = io_register_device(&uart_dev_info);
+ if (!result)
+ *dev_con = &uart_dev_connector;
+
+ return result;
+}
diff --git a/drivers/st/uart/stm32mp1xx_hal_uart.c b/drivers/st/uart/stm32mp1xx_hal_uart.c
new file mode 100644
index 0000000..c8e5860
--- /dev/null
+++ b/drivers/st/uart/stm32mp1xx_hal_uart.c
@@ -0,0 +1,799 @@
+/**
+ ******************************************************************************
+ * @file stm32mp1xx_hal_uart.c
+ * @author MCD Application Team
+ * @version $VERSION$
+ * @date $DATE$
+ * @brief UART HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ *
+ *
+ * @verbatim
+ * ===============================================================================
+ * ##### How to use this driver #####
+ * ===============================================================================
+ * [..]
+ * The UART HAL driver can be used as follows:
+ *
+ * (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).
+ * (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
+ * (++) Enable the USARTx interface clock.
+ * (++) UART pins configuration:
+ * (+++) Enable the clock for the UART GPIOs.
+ * (+++) Configure these UART pins as alternate function pull-up.
+ * (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
+ * and HAL_UART_Receive_IT() APIs):
+ * (+++) Configure the USARTx interrupt priority.
+ * (+++) Enable the NVIC USART IRQ handle.
+ * (++) UART interrupts handling:
+ * -@@- The specific UART interrupts (Transmission complete interrupt,
+ * RXNE interrupt and Error Interrupts) are managed using the macros
+ * __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit and receive processes.
+ * (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
+ * and HAL_UART_Receive_DMA() APIs):
+ * (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ * (+++) Enable the DMAx interface clock.
+ * (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ * (+++) Configure the DMA Tx/Rx channel.
+ * (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
+ * (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+ *
+ * (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
+ * flow control and Mode (Receiver/Transmitter) in the huart handle Init structure.
+ *
+ * (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...)
+ * in the huart handle AdvancedInit structure.
+ *
+ * (#) For the UART asynchronous mode, initialize the UART registers by calling
+ * the HAL_UART_Init() API.
+ *
+ * (#) For the UART Half duplex mode, initialize the UART registers by calling
+ * the HAL_HalfDuplex_Init() API.
+ *
+ * (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers
+ * by calling the HAL_LIN_Init() API.
+ *
+ * (#) For the UART Multiprocessor mode, initialize the UART registers
+ * by calling the HAL_MultiProcessor_Init() API.
+ *
+ * (#) For the UART RS485 Driver Enabled mode, initialize the UART registers
+ * by calling the HAL_RS485Ex_Init() API.
+ *
+ * [..]
+ * (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(),
+ * also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by
+ * calling the customized HAL_UART_MspInit() API.
+ *
+ * @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015-2017 STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include <assert.h>
+#include <bl_common.h>
+#include <platform_def.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp1xx_hal_uart.h>
+#include <string.h>
+
+/** @addtogroup STM32MP1xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UART UART
+ * @brief HAL UART module driver
+ * @{
+ */
+
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup UART_Private_Constants UART Private Constants
+ * @{
+ */
+#define UART_CR1_FIELDS \
+ ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 | \
+ USART_CR1_FIFOEN))
+
+#define USART_CR3_FIELDS \
+ ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT | \
+ USART_CR3_TXFTCFG | USART_CR3_RXFTCFG))
+
+
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup UART_Exported_Functions UART Exported Functions
+ * @{
+ */
+
+/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+ * @verbatim
+ * ===============================================================================
+ * ##### Initialization and Configuration functions #####
+ * ===============================================================================
+ * [..]
+ * This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
+ * in asynchronous mode.
+ * (+) For the asynchronous mode the parameters below can be configured:
+ * (++) Baud Rate
+ * (++) Word Length
+ * (++) Stop Bit
+ * (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ * in the data register is transmitted but is changed by the parity bit.
+ * (++) Hardware flow control
+ * (++) Receiver/transmitter modes
+ * (++) Over Sampling Method
+ * (++) One-Bit Sampling Method
+ * (+) For the asynchronous mode, the following advanced features can be configured as well:
+ * (++) TX and/or RX pin level inversion
+ * (++) data logical level inversion
+ * (++) RX and TX pins swap
+ * (++) RX overrun detection disabling
+ * (++) DMA disabling on RX error
+ * (++) MSB first on communication line
+ * (++) auto Baud rate detection
+ * [..]
+ * The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API
+ * follow respectively the UART asynchronous, UART Half duplex, UART LIN mode
+ * and UART multiprocessor mode configuration procedures (details for the procedures
+ * are available in reference manual).
+ *
+ * @endverbatim
+ *
+ * Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ * 8-bit or 9-bit), the possible UART formats are listed in the
+ * following table.
+ *
+ * Table 1. UART frame format.
+ * +-----------------------------------------------------------------------+
+ * | M1 bit | M0 bit | PCE bit | UART frame |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ * |---------|---------|-----------|---------------------------------------|
+ * | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ * +-----------------------------------------------------------------------+
+ *
+ * @{
+ */
+
+/**
+ * @brief Initialize the UART mode according to the specified
+ * parameters in the UART_InitTypeDef and initialize the associated handle.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if (!huart)
+ return HAL_ERROR;
+
+ /* Check the parameters */
+ if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
+ assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
+ else
+ assert_param(IS_UART_INSTANCE(huart->Instance));
+
+ /* Allocate lock resource and initialize it */
+ if (huart->gState == HAL_UART_STATE_RESET)
+ huart->Lock = HAL_UNLOCKED;
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ return HAL_ERROR;
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ UART_AdvFeatureConfig(huart);
+
+ /* In asynchronous mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL |
+ USART_CR3_IREN));
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return UART_CheckIdleState(huart);
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group2 IO operation functions
+ * @brief UART Transmit/Receive functions
+ *
+ * @verbatim
+ * ===============================================================================
+ * ##### IO operation functions #####
+ * ===============================================================================
+ * This subsection provides a set of functions allowing to manage the UART asynchronous
+ * and Half duplex data transfers.
+ *
+ * (#) There are two mode of transfer:
+ * (+) Blocking mode: The communication is performed in polling mode.
+ * The HAL status of all data processing is returned by the same function
+ * after finishing transfer.
+ * (+) Non-Blocking mode: The communication is performed using Interrupts
+ * or DMA, These API's return the HAL status.
+ * The end of the data processing will be indicated through the
+ * dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
+ * using DMA mode.
+ * The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
+ * will be executed respectively at the end of the transmit or Receive process
+ * The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected
+ *
+ * (#) Blocking mode API's are :
+ * (+) HAL_UART_Transmit()
+ * (+) HAL_UART_Receive()
+ *
+ * (#) Non-Blocking mode API's with Interrupt are :
+ * (+) HAL_UART_Transmit_IT()
+ * (+) HAL_UART_Receive_IT()
+ * (+) HAL_UART_IRQHandler()
+ *
+ * (#) Non-Blocking mode API's with DMA are :
+ * (+) HAL_UART_Transmit_DMA()
+ * (+) HAL_UART_Receive_DMA()
+ * (+) HAL_UART_DMAPause()
+ * (+) HAL_UART_DMAResume()
+ * (+) HAL_UART_DMAStop()
+ *
+ * (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
+ * (+) HAL_UART_TxHalfCpltCallback()
+ * (+) HAL_UART_TxCpltCallback()
+ * (+) HAL_UART_RxHalfCpltCallback()
+ * (+) HAL_UART_RxCpltCallback()
+ * (+) HAL_UART_ErrorCallback()
+ *
+ * -@- In the Half duplex communication, it is forbidden to run the transmit
+ * and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful.
+ *
+ * @endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send an amount of data in blocking mode.
+ * @param huart: UART handle.
+ * @param pData: Pointer to data buffer.
+ * @param Size: Amount of data to be sent.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint16_t *tmp;
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef ret = HAL_OK;
+
+ /* Check that a Tx process is not already ongoing */
+ if (huart->gState != HAL_UART_STATE_READY)
+ return HAL_BUSY;
+
+ if ((!pData) || (Size == 0U))
+ return HAL_ERROR;
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->gState = HAL_UART_STATE_BUSY_TX;
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+ while (huart->TxXferCount > 0U) {
+ huart->TxXferCount--;
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET,
+ tickstart, Timeout) != HAL_OK) {
+ ret = HAL_TIMEOUT;
+ goto end;
+ }
+
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) &&
+ (huart->Init.Parity == UART_PARITY_NONE)) {
+ tmp = (uint16_t *)pData;
+ huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU);
+ pData += 2U;
+ } else {
+ huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU);
+ }
+ }
+
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart,
+ Timeout) != HAL_OK) {
+ ret = HAL_TIMEOUT;
+ goto end;
+ }
+
+end:
+ /* At end of Tx process, restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return ret;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be received.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint16_t *tmp;
+ uint16_t uhMask;
+ uint32_t tickstart = 0;
+ HAL_StatusTypeDef ret = HAL_OK;
+
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState != HAL_UART_STATE_READY)
+ return HAL_BUSY;
+
+ if ((!pData) || (Size == 0U))
+ return HAL_ERROR;
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->RxState = HAL_UART_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+ uhMask = huart->Mask;
+
+ /* as long as data have to be received */
+ while (huart->RxXferCount > 0U) {
+ huart->RxXferCount--;
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET,
+ tickstart, Timeout) != HAL_OK) {
+ ret = HAL_TIMEOUT;
+ goto end;
+ }
+
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) &&
+ (huart->Init.Parity == UART_PARITY_NONE)) {
+ tmp = (uint16_t *)pData;
+ *tmp = (uint16_t)(huart->Instance->RDR & uhMask);
+ pData += 2U;
+ } else {
+ *pData++ = (uint8_t)(huart->Instance->RDR &
+ (uint8_t)uhMask);
+ }
+ }
+
+end:
+ /* At end of Rx process, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return ret;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions
+ * @brief UART control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the UART.
+ (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode
+ (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode
+ (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode
+ (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode
+ (+) UART_SetConfig() API configures the UART peripheral
+ (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features
+ (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization
+ (+) UART_Wakeup_AddressConfig() API configures the wake-up from stop mode parameters
+ (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter
+ (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver
+ (+) HAL_LIN_SendBreak() API transmits the break characters
+@endverbatim
+ * @{
+ */
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief UART Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) Return the UART handle state.
+ (+) Return the UART handle error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the UART handle state.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+ * @retval HAL state
+ */
+HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart)
+{
+ uint32_t temp1 = huart->gState;
+ uint32_t temp2 = huart->RxState;
+
+ return (HAL_UART_StateTypeDef)(temp1 | temp2);
+}
+
+/**
+ * @brief Return the UART handle error code.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+ * @retval UART Error Code
+*/
+uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart)
+{
+ return huart->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Private_Functions UART Private Functions
+ * @{
+ */
+
+static unsigned long uart_get_clock_freq(UART_HandleTypeDef *huart)
+{
+ return fdt_get_uart_clock_freq((uintptr_t)huart->Instance);
+}
+
+/**
+ * @brief Configure the UART peripheral.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart)
+{
+ uint32_t tmpreg;
+ unsigned long clockfreq;
+
+ /*---------------------- USART CR1 Configuration --------------------
+ * Clear M, PCE, PS, TE, RE and OVER8 bits and configure
+ * the UART Word Length, Parity, Mode and oversampling:
+ * set the M bits according to huart->Init.WordLength value
+ * set PCE and PS bits according to huart->Init.Parity value
+ * set TE and RE bits according to huart->Init.Mode value
+ * set OVER8 bit according to huart->Init.OverSampling value
+ */
+ tmpreg = (uint32_t)(huart->Init.WordLength |
+ huart->Init.Parity |
+ huart->Init.Mode |
+ huart->Init.OverSampling);
+ tmpreg |= (uint32_t)huart->Init.FIFOMode;
+ MODIFY_REG(huart->Instance->CR1, UART_CR1_FIELDS, tmpreg);
+
+ /*--------------------- USART CR2 Configuration ---------------------
+ * Configure the UART Stop Bits: Set STOP[13:12] bits according
+ * to huart->Init.StopBits value
+ */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
+
+ /*--------------------- USART CR3 Configuration ---------------------
+ * Configure
+ * - UART HardWare Flow Control: set CTSE and RTSE bits according
+ * to huart->Init.HwFlowCtl value
+ * - one-bit sampling method versus three samples' majority rule
+ * according to huart->Init.OneBitSampling (not applicable to LPUART)
+ * - set TXFTCFG bit according to husart->Init.TXFIFOThreshold value
+ * - set RXFTCFG bit according to husart->Init.RXFIFOThreshold value
+ */
+ tmpreg = (uint32_t)huart->Init.HwFlowCtl;
+
+ tmpreg |= huart->Init.OneBitSampling;
+
+ if (huart->Init.FIFOMode == UART_FIFOMODE_ENABLE)
+ tmpreg |= ((uint32_t)huart->Init.TXFIFOThreshold |
+ (uint32_t)huart->Init.RXFIFOThreshold);
+
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_FIELDS, tmpreg);
+
+ /*--------------------- USART PRESC Configuration -------------------
+ * Configure
+ * - UART Clock Prescaler : set PRESCALER according to
+ * huart->Init.Prescaler value
+ */
+ MODIFY_REG(huart->Instance->PRESC, USART_PRESC_PRESCALER,
+ huart->Init.Prescaler);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+
+ clockfreq = uart_get_clock_freq(huart);
+ if (!clockfreq)
+ return HAL_ERROR;
+
+ if (huart->Init.OverSampling == UART_OVERSAMPLING_8) {
+ uint16_t usartdiv =
+ (uint16_t)uart_div_sampling8(clockfreq,
+ huart->Init.BaudRate,
+ huart->Init.Prescaler);
+
+ uint16_t brrtemp = usartdiv & 0xFFF0U;
+
+ brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U);
+ huart->Instance->BRR = brrtemp;
+ } else {
+ huart->Instance->BRR =
+ (uint16_t)uart_div_sampling16(clockfreq,
+ huart->Init.BaudRate,
+ huart->Init.Prescaler);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the UART peripheral advanced features.
+ * @param huart: UART handle.
+ * @retval None
+ */
+void UART_AdvFeatureConfig(UART_HandleTypeDef *huart)
+{
+ /* Check whether the set of advanced features to configure is properly set */
+ assert_param(
+ IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit));
+
+ /* if required, configure TX pin active level inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_TXINVERT_INIT)) {
+ assert_param(
+ IS_UART_ADVFEATURE_TXINV(
+ huart->AdvancedInit.TxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV,
+ huart->AdvancedInit.TxPinLevelInvert);
+ }
+
+ /* if required, configure RX pin active level inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_RXINVERT_INIT)) {
+ assert_param(
+ IS_UART_ADVFEATURE_RXINV(
+ huart->AdvancedInit.RxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV,
+ huart->AdvancedInit.RxPinLevelInvert);
+ }
+
+ /* if required, configure data inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_DATAINVERT_INIT)) {
+ assert_param(
+ IS_UART_ADVFEATURE_DATAINV(
+ huart->AdvancedInit.DataInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV,
+ huart->AdvancedInit.DataInvert);
+ }
+
+ /* if required, configure RX/TX pins swap */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_SWAP_INIT)) {
+ assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP,
+ huart->AdvancedInit.Swap);
+ }
+
+ /* if required, configure RX overrun detection disabling */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_RXOVERRUNDISABLE_INIT)) {
+ assert_param(IS_UART_OVERRUN(
+ huart->AdvancedInit.OverrunDisable));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS,
+ huart->AdvancedInit.OverrunDisable);
+ }
+
+ /* if required, configure DMA disabling on reception error */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_DMADISABLEONERROR_INIT)) {
+ assert_param(
+ IS_UART_ADVFEATURE_DMAONRXERROR(
+ huart->AdvancedInit.DMADisableonRxError));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE,
+ huart->AdvancedInit.DMADisableonRxError);
+ }
+
+ /* if required, configure auto Baud rate detection scheme */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_AUTOBAUDRATE_INIT)) {
+ assert_param(
+ IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(
+ huart->Instance));
+ assert_param(
+ IS_UART_ADVFEATURE_AUTOBAUDRATE(
+ huart->AdvancedInit.AutoBaudRateEnable));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN,
+ huart->AdvancedInit.AutoBaudRateEnable);
+ /* set auto Baudrate detection parameters if detection is enabled */
+ if (huart->AdvancedInit.AutoBaudRateEnable ==
+ UART_ADVFEATURE_AUTOBAUDRATE_ENABLE) {
+ assert_param(
+ IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(
+ huart->AdvancedInit.AutoBaudRateMode));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE,
+ huart->AdvancedInit.AutoBaudRateMode);
+ }
+ }
+
+ /* if required, configure MSB first on communication line */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit,
+ UART_ADVFEATURE_MSBFIRST_INIT)) {
+ assert_param(
+ IS_UART_ADVFEATURE_MSBFIRST(
+ huart->AdvancedInit.MSBFirst));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST,
+ huart->AdvancedInit.MSBFirst);
+ }
+}
+
+/**
+ * @brief Check the UART Idle State.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart)
+{
+ uint32_t tickstart;
+
+ /* Initialize the UART ErrorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* Check if the Transmitter is enabled */
+ if ((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) {
+ /* Wait until TEACK flag is set */
+ if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK,
+ RESET, tickstart,
+ HAL_UART_TIMEOUT_VALUE) !=
+ HAL_OK) {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Check if the Receiver is enabled */
+ if ((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) {
+ /* Wait until REACK flag is set */
+ if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET,
+ tickstart,
+ HAL_UART_TIMEOUT_VALUE) !=
+ HAL_OK) {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the UART State */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle UART Communication Timeout.
+ * @param huart: UART handle.
+ * @param Flag Specifies the UART flag to check
+ * @param Status Flag status (SET or RESET)
+ * @param Tickstart Tick start value
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart,
+ uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart,
+ uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY) {
+ if ((Timeout == 0U) ||
+ ((HAL_GetTick() - Tickstart) > Timeout)) {
+ /*
+ * Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error)
+ * interrupts for the interrupt process
+ */
+ CLEAR_BIT(huart->Instance->CR1,
+ (USART_CR1_RXNEIE | USART_CR1_PEIE |
+ USART_CR1_TXEIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+#endif /* HAL_UART_MODULE_ENABLED */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/drivers/st/usb_dwc2/usb_dwc2.c b/drivers/st/usb_dwc2/usb_dwc2.c
new file mode 100644
index 0000000..a920553
--- /dev/null
+++ b/drivers/st/usb_dwc2/usb_dwc2.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <stdint.h>
+#include <usb_dwc2.h>
+
+static usb_dwc2_t dwc2_handle;
+
+static const usb_driver_t usb_dwc2driver = {
+ .disable_int = usb_dwc2_disable_int,
+ .ep0_out_start = usb_dwc2_ep0_out_start,
+ .ep_start_xfer = usb_dwc2_ep_start_xfer,
+ .ep0_start_xfer = usb_dwc2_ep0_start_xfer,
+ .write_packet = usb_dwc2_write_packet,
+ .read_packet = usb_dwc2_read_packet,
+ .ep_set_stall = usb_dwc2_ep_set_stall,
+ .stop_device = usb_dwc2_stop_device,
+ .set_address = usb_dwc2_set_address,
+ .dev_disconnect = usb_dwc2_dev_disconnect,
+ .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo,
+ .it_handler = usb_dwc2_it_handler
+};
+
+/*
+ * USB_OTG_FlushTxFifo : Flush a Tx FIFO
+ * USBx : Selected device
+ * num : FIFO number
+ * This parameter can be a value from 1 to 15
+ * 15 means Flush all Tx FIFOs
+ * return : status
+ */
+static usb_status_t usb_dwc2_flush_tx_fifo(usb_dwc2_global_t *usbx,
+ uint32_t num)
+{
+ uint32_t count = 0;
+
+ usbx->grstctl = (USB_OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << 6));
+
+ do {
+ if (++count > 200000)
+ return USBD_TIMEOUT;
+ } while ((usbx->grstctl & USB_OTG_GRSTCTL_TXFFLSH) ==
+ USB_OTG_GRSTCTL_TXFFLSH);
+
+ return USBD_OK;
+}
+
+/*
+ * USB_FlushRxFifo : Flush Rx FIFO
+ * param : USBx : Selected device
+ * return : status
+ */
+static usb_status_t usb_dwc2_flush_rx_fifo(usb_dwc2_global_t *usbx)
+{
+ uint32_t count = 0;
+
+ usbx->grstctl = USB_OTG_GRSTCTL_RXFFLSH;
+
+ do {
+ if (++count > 200000)
+ return USBD_TIMEOUT;
+ } while ((usbx->grstctl & USB_OTG_GRSTCTL_RXFFLSH) ==
+ USB_OTG_GRSTCTL_RXFFLSH);
+
+ return USBD_OK;
+}
+
+/*
+ * USB_ReadInterrupts: return the global USB interrupt status
+ * param USBx : Selected device
+ * return : interrupt register value
+ */
+static uint32_t usb_dwc2_read_int(usb_dwc2_global_t *usbx)
+{
+ uint32_t v = 0;
+
+ v = usbx->gintsts;
+ v &= usbx->gintmsk;
+
+ return v;
+}
+
+/*
+ * usb_dwc2_all_out_ep_int : return the USB device OUT endpoints interrupt
+ * param : USBx : Selected device
+ * return : device OUT endpoint interrupts
+ */
+static uint32_t usb_dwc2_all_out_ep_int(usb_dwc2_global_t *usbx)
+{
+ uint32_t v = 0;
+
+ v = dwc2_handle.usb_device->daint;
+ v &= dwc2_handle.usb_device->daintmsk;
+
+ return ((v & 0xffff0000) >> 16);
+}
+
+/*
+ * usb_dwc2_all_in_ep_int: return the USB device IN endpoints interrupt
+ * param : USBx : Selected device
+ * return : device IN endpoint interrupts
+ */
+static uint32_t usb_dwc2_all_in_ep_int(usb_dwc2_global_t *usbx)
+{
+ uint32_t v = 0;
+
+ v = dwc2_handle.usb_device->daint;
+ v &= dwc2_handle.usb_device->daintmsk;
+
+ return ((v & 0xFFFF));
+}
+
+/*
+ * usb_dwc2_out_ep_int : returns Device OUT EP Interrupt register
+ * USBx : Selected device
+ * epnum : endpoint number
+ * This parameter can be a value from 0 to 15
+ * return : Device OUT EP Interrupt register
+ */
+static uint32_t usb_dwc2_out_ep_int(usb_dwc2_global_t *usbx, uint8_t epnum)
+{
+ uint32_t v = 0;
+
+ v = dwc2_handle.usb_out_endpoint[epnum]->epint;
+ v &= dwc2_handle.usb_device->doepmsk;
+
+ return v;
+}
+
+/*
+ * usb_dwc2_in_ep_int : Returns Device IN EP Interrupt register
+ * param : USBx : Selected device
+ * param : epnum : endpoint number
+ * This parameter can be a value from 0 to 15
+ * return : Device IN EP Interrupt register
+ */
+static uint32_t usb_dwc2_in_ep_int(usb_dwc2_global_t *usbx, uint8_t epnum)
+{
+ uint32_t msk, emp;
+
+ msk = dwc2_handle.usb_device->diepmsk;
+ emp = dwc2_handle.usb_device->diepempmsk;
+ msk |= ((emp >> epnum) & 0x1) << 7;
+
+ return (dwc2_handle.usb_in_endpoint[epnum]->epint & msk);
+}
+
+/*
+ * usb_dwc2_get_mode : Returns USB core mode
+ * param : USBx : Selected device
+ * return : core mode : Host or Device
+ * This parameter can be one of the these values:
+ * 0 : Host
+ * 1 : Device
+ */
+static uint32_t usb_dwc2_get_mode(usb_dwc2_global_t *usbx)
+{
+ return ((usbx->gintsts) & 0x1);
+}
+
+/*
+ * usb_dwc2_activate_setup : Activate EP0 for Setup transactions
+ * param : USBx : Selected device
+ * return : status
+ */
+static usb_status_t usb_dwc2_activate_setup(usb_dwc2_global_t *usbx)
+{
+ /* Set the MPS of the IN EP based on the enumeration speed */
+ dwc2_handle.usb_in_endpoint[0]->epctl &= ~USB_OTG_DIEPCTL_MPSIZ;
+
+ if ((dwc2_handle.usb_device->dsts & USB_OTG_DSTS_ENUMSPD) ==
+ DSTS_ENUMSPD_LS_PHY_6MHZ)
+ dwc2_handle.usb_in_endpoint[0]->epctl |= 3;
+
+ dwc2_handle.usb_device->dctl |= USB_OTG_DCTL_CGINAK;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_disable_int :
+ * Disable the controller's Global Int in the AHB Config reg
+ * param : handle : Selected device
+ * return : status
+ */
+usb_status_t usb_dwc2_disable_int(void *handle)
+{
+ usb_dwc2_global_t *usbx = ((usb_dwc2_t *)handle)->usb_global;
+
+ usbx->gahbcfg &= ~USB_OTG_GAHBCFG_GINT;
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_ep0_out_start : Prepare the EP0 to start the first control setup
+ * param : handle : Selected device
+ * return : status
+ */
+usb_status_t usb_dwc2_ep0_out_start(void *handle)
+{
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ dwc2_handle.usb_out_endpoint[0]->eptsiz = 0;
+ dwc2_handle.usb_out_endpoint[0]->eptsiz |= (USB_OTG_DOEPTSIZ_PKTCNT &
+ (1 << 19));
+ dwc2_handle.usb_out_endpoint[0]->eptsiz |= (3 * 8);
+ dwc2_handle.usb_out_endpoint[0]->eptsiz |= USB_OTG_DOEPTSIZ_STUPCNT;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_ep_start_xfer : setup and starts a transfer over an EP
+ * param : handle : Selected device
+ * param : ep: pointer to endpoint structure
+ * return : status
+ */
+usb_status_t usb_dwc2_ep_start_xfer(void *handle, usb_otg_ep_t *ep)
+{
+ usb_dwc2_global_t *usbx = ((usb_dwc2_t *)handle)->usb_global;
+
+ /* IN endpoint */
+ if (ep->is_in == 1) {
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0) {
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19));
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ } else {
+ /* Program the transfer size and packet count
+ * as follows: xfersize = N * maxpacket +
+ * short_packet pktcnt = N + (short_packet
+ * exist ? 1 : 0)
+ */
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_PKTCNT &
+ (((ep->xfer_len + ep->maxpacket - 1) /
+ ep->maxpacket) << 19));
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_XFRSIZ &
+ ep->xfer_len);
+
+ if (ep->type == EP_TYPE_ISOC) {
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_MULCNT);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_MULCNT &
+ (1 << 29));
+ }
+ }
+
+ if (ep->type != EP_TYPE_ISOC) {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ dwc2_handle.usb_device->diepempmsk |=
+ 1 << ep->num;
+ }
+
+ if (ep->type == EP_TYPE_ISOC) {
+ if ((dwc2_handle.usb_device->dsts & (1 << 8)) == 0) {
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl |=
+ USB_OTG_DIEPCTL_SODDFRM;
+ } else {
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl |=
+ USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl |=
+ (USB_OTG_DIEPCTL_CNAK |
+ USB_OTG_DIEPCTL_EPENA);
+
+ if (ep->type == EP_TYPE_ISOC)
+ usb_dwc2_write_packet(usbx, ep->xfer_buff,
+ ep->num, ep->xfer_len);
+ } else {
+ /* Program the transfer size and packet count as follows:
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+ if (ep->xfer_len == 0) {
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_XFRSIZ &
+ ep->maxpacket);
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19));
+ } else {
+ uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1) /
+ ep->maxpacket;
+
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_PKTCNT &
+ (pktcnt << 19));
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_XFRSIZ &
+ (ep->maxpacket * pktcnt));
+ }
+
+ if (ep->type == EP_TYPE_ISOC) {
+ if ((dwc2_handle.usb_device->dsts & (1 << 8)) == 0)
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl |=
+ USB_OTG_DOEPCTL_SODDFRM;
+ else
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl |=
+ USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
+ }
+ /* EP enable */
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl |=
+ (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+ }
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_ep0_start_xfer : setup and starts a transfer over the EP 0
+ * param : handle : Selected device
+ * param : ep: pointer to endpoint structure
+ * return : status
+ */
+usb_status_t usb_dwc2_ep0_start_xfer(void *handle, usb_otg_ep_t *ep)
+{
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ /* IN endpoint */
+ if (ep->is_in == 1) {
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0) {
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19));
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ } else {
+ /* Program the transfer size and packet count
+ * as follows: xfersize = N * maxpacket +
+ * short_packet pktcnt = N + (short_packet
+ * exist ? 1 : 0)
+ */
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DIEPTSIZ_PKTCNT);
+
+ if (ep->xfer_len > ep->maxpacket)
+ ep->xfer_len = ep->maxpacket;
+
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19));
+ dwc2_handle.usb_in_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DIEPTSIZ_XFRSIZ &
+ ep->xfer_len);
+ }
+
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ dwc2_handle.usb_device->diepempmsk |= 1 << (ep->num);
+
+ /* EP enable, IN data in FIFO */
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl |=
+ (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+ } else {
+ /* Program the transfer size and packet count as follows:
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz &=
+ ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+ if (ep->xfer_len > 0)
+ ep->xfer_len = ep->maxpacket;
+
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_PKTCNT &
+ (1 << 19));
+ dwc2_handle.usb_out_endpoint[ep->num]->eptsiz |=
+ (USB_OTG_DOEPTSIZ_XFRSIZ &
+ (ep->maxpacket));
+
+ /* EP enable */
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl |=
+ (USB_OTG_DOEPCTL_CNAK |
+ USB_OTG_DOEPCTL_EPENA);
+ }
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_write_packet : Writes a packet into the Tx FIFO associated
+ * with the EP/channel
+ * param : handle : Selected device
+ * param : src : pointer to source buffer
+ * param : ch_ep_num : endpoint or host channel number
+ * param : len : Number of bytes to write
+ * return : status
+ */
+usb_status_t usb_dwc2_write_packet(void *handle, uint8_t *src,
+ uint8_t ch_ep_num, uint16_t len)
+{
+ uint32_t count32b, i, j;
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ count32b = (len + 3) / 4;
+ for (i = 0; i < count32b; i++, src += 4) {
+ uint32_t src_copy = 0;
+
+ /* Data written to fifo need to be 4 bytes aligned */
+ for (j = 0; j < 4; j++)
+ src_copy += (*(src + j)) << (8 * j);
+
+ *dwc2_handle.usb_fifo[ch_ep_num] = src_copy;
+ }
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_read_packet : read a packet from the Tx FIFO associated
+ * with the EP/channel
+ * param : handle : Selected device
+ * param : src : source pointer
+ * param : ch_ep_num : endpoint or host channel number
+ * param : len : Number of bytes to read
+ * return : pointer to destination buffer
+ */
+void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len)
+{
+ uint32_t i = 0;
+ uint32_t count32b = (len + 3) / 4;
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest);
+
+ for (i = 0; i < count32b; i++, dest += 4) {
+ *(uint32_t *)dest = *dwc2_handle.usb_fifo[0];
+ dsb();
+ }
+
+ return ((void *)dest);
+}
+
+/*
+ * usb_dwc2_EPSetStall : set a stall condition over an EP
+ * param : handle : Selected device
+ * param : ep: pointer to endpoint structure
+ * return : status
+ */
+usb_status_t usb_dwc2_ep_set_stall(void *handle, usb_otg_ep_t *ep)
+{
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+ if (ep->is_in == 1) {
+ if ((dwc2_handle.usb_in_endpoint[ep->num]->epctl &
+ USB_OTG_DIEPCTL_EPENA) == 0)
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl &=
+ ~(USB_OTG_DIEPCTL_EPDIS);
+ dwc2_handle.usb_in_endpoint[ep->num]->epctl |=
+ USB_OTG_DIEPCTL_STALL;
+ } else {
+ if ((dwc2_handle.usb_out_endpoint[ep->num]->epctl &
+ USB_OTG_DOEPCTL_EPENA) == 0)
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl &=
+ ~(USB_OTG_DOEPCTL_EPDIS);
+ dwc2_handle.usb_out_endpoint[ep->num]->epctl |=
+ USB_OTG_DOEPCTL_STALL;
+ }
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_stop_device : Stop the usb device mode
+ * param : handle : Selected device
+ * return : status
+ */
+usb_status_t usb_dwc2_stop_device(void *handle)
+{
+ uint32_t i = 0;
+ usb_dwc2_global_t *usbx = ((usb_dwc2_t *)handle)->usb_global;
+
+ /* Clear Pending interrupt */
+ for (i = 0; i < 15 ; i++) {
+ dwc2_handle.usb_in_endpoint[i]->epint = 0xFF;
+ dwc2_handle.usb_out_endpoint[i]->epint = 0xFF;
+ }
+ dwc2_handle.usb_device->daint = 0xFFFFFFFF;
+
+ /* Clear interrupt masks */
+ dwc2_handle.usb_device->diepmsk = 0;
+ dwc2_handle.usb_device->doepmsk = 0;
+ dwc2_handle.usb_device->daintmsk = 0;
+
+ /* Flush the FIFO */
+ usb_dwc2_flush_rx_fifo(usbx);
+ usb_dwc2_flush_tx_fifo(usbx, 0x10);
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_set_address : Stop the usb device mode
+ * param : handle : Selected device
+ * param : address : new device address to be assigned
+ * This parameter can be a value from 0 to 255
+ * return : status
+ */
+usb_status_t usb_dwc2_set_address(void *handle, uint8_t address)
+{
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ dwc2_handle.usb_device->dcfg &= ~(USB_OTG_DCFG_DAD);
+ dwc2_handle.usb_device->dcfg |= (address << 4) & USB_OTG_DCFG_DAD;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_dev_disconnect :
+ * Disconnect the USB device by disabling the pull-up/pull-down
+ * param : handle : Selected device
+ * return : status
+ */
+usb_status_t usb_dwc2_dev_disconnect(void *handle)
+{
+ /*usb_dwc2_global_t *USBx = (usb_dwc2_global_t *)handle;*/
+
+ dwc2_handle.usb_device->dctl |= USB_OTG_DCTL_SDIS;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dwc2_write_empty_tx_fifo
+ * check FIFO for the next packet to be loaded
+ * param : handle : Selected device
+ * param : epnum : endpoint number
+ * param : xfer_len : block length
+ * param : xfer_count : number of block
+ * param : maxpacket : max packet length
+ * param : xfer_buff : buffer pointer
+ * retval : status
+ */
+usb_status_t usb_dwc2_write_empty_tx_fifo(void *handle,
+ uint32_t epnum, uint32_t xfer_len,
+ uint32_t *xfer_count,
+ uint32_t maxpacket,
+ uint8_t **xfer_buff)
+{
+ int32_t len = 0;
+ uint32_t len32b;
+ usb_dwc2_global_t *usbx = ((usb_dwc2_t *)handle)->usb_global;
+
+ len = xfer_len - *xfer_count;
+
+ if ((len > 0) && ((uint32_t)len > maxpacket))
+ len = maxpacket;
+
+ len32b = (len + 3) / 4;
+
+ while ((dwc2_handle.usb_in_endpoint[epnum]->txfsts &
+ USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
+ (*xfer_count < xfer_len) && (xfer_len != 0)) {
+ /* Write the FIFO */
+ len = xfer_len - *xfer_count;
+
+ if ((len > 0) && ((uint32_t)len > maxpacket))
+ len = maxpacket;
+
+ len32b = (len + 3) / 4;
+
+ usb_dwc2_write_packet(usbx, *xfer_buff, epnum, len);
+
+ *xfer_buff += len;
+ *xfer_count += len;
+ }
+
+ if (len <= 0) {
+ uint32_t fifoemptymsk = 0x1 << epnum;
+
+ dwc2_handle.usb_device->diepempmsk &= ~fifoemptymsk;
+ }
+
+ return USBD_OK;
+}
+
+/*
+ * @brief This function handles PCD interrupt request.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+usb_action_t usb_dwc2_it_handler(void *handle, uint32_t *param)
+{
+ usb_dwc2_global_t *usbx = ((usb_dwc2_t *)handle)->usb_global;
+ uint32_t ep_intr, epint, epnum = 0;
+ uint32_t temp;
+
+ /* ensure that we are in device mode */
+ if (usb_dwc2_get_mode(usbx) != USB_OTG_MODE_DEVICE)
+ return USB_NOTHING;
+
+ /* avoid spurious interrupt */
+ if (!usb_dwc2_read_int(usbx))
+ return USB_NOTHING;
+
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_MMIS)
+ /* incorrect mode, acknowledge the interrupt */
+ usbx->gintsts = USB_OTG_GINTSTS_MMIS;
+
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_OEPINT) {
+ /* Read in the device interrupt bits */
+ ep_intr = usb_dwc2_all_out_ep_int(usbx);
+
+ while (!(ep_intr & 1)) {
+ epnum++;
+ ep_intr >>= 1;
+ }
+
+ if (ep_intr & 1) {
+ epint = usb_dwc2_out_ep_int(usbx, epnum);
+
+ if ((epint & USB_OTG_DOEPINT_XFRC) ==
+ USB_OTG_DOEPINT_XFRC) {
+ dwc2_handle.usb_out_endpoint[epnum]->epint =
+ USB_OTG_DOEPINT_XFRC;
+ *param = epnum;
+ return USB_DATA_OUT;
+ }
+ if ((epint & USB_OTG_DOEPINT_STUP) ==
+ USB_OTG_DOEPINT_STUP) {
+ /* Inform the upper layer that a setup packet
+ * is available
+ */
+ dwc2_handle.usb_out_endpoint[epnum]->epint =
+ USB_OTG_DOEPINT_STUP;
+ return USB_SETUP;
+ }
+ if ((epint & USB_OTG_DOEPINT_OTEPDIS) ==
+ USB_OTG_DOEPINT_OTEPDIS)
+ dwc2_handle.usb_out_endpoint[epnum]->epint =
+ USB_OTG_DOEPINT_OTEPDIS;
+ }
+ }
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_IEPINT) {
+ /* Read in the device interrupt bits */
+ ep_intr = usb_dwc2_all_in_ep_int(usbx);
+
+ while (!(ep_intr & 1)) {
+ epnum++;
+ ep_intr >>= 1;
+ }
+ /* In ITR */
+ if (ep_intr & 0x1) {
+ epint = usb_dwc2_in_ep_int(usbx, epnum);
+
+ if ((epint & USB_OTG_DIEPINT_XFRC) ==
+ USB_OTG_DIEPINT_XFRC) {
+ uint32_t fifoemptymsk = 0x1 << epnum;
+
+ dwc2_handle.usb_device->diepempmsk &=
+ ~fifoemptymsk;
+
+ dwc2_handle.usb_in_endpoint[epnum]->epint =
+ USB_OTG_DIEPINT_XFRC;
+
+ *param = epnum;
+ return USB_DATA_IN;
+ }
+ if ((epint & USB_OTG_DIEPINT_TOC) ==
+ USB_OTG_DIEPINT_TOC)
+ dwc2_handle.usb_in_endpoint[epnum]->epint =
+ USB_OTG_DIEPINT_TOC;
+
+ if ((epint & USB_OTG_DIEPINT_ITTXFE) ==
+ USB_OTG_DIEPINT_ITTXFE)
+ dwc2_handle.usb_in_endpoint[epnum]->epint =
+ USB_OTG_DIEPINT_ITTXFE;
+
+ if ((epint & USB_OTG_DIEPINT_INEPNE) ==
+ USB_OTG_DIEPINT_INEPNE)
+ dwc2_handle.usb_in_endpoint[epnum]->epint =
+ USB_OTG_DIEPINT_INEPNE;
+
+ if ((epint & USB_OTG_DIEPINT_EPDISD) ==
+ USB_OTG_DIEPINT_EPDISD)
+ dwc2_handle.usb_in_endpoint[epnum]->epint =
+ USB_OTG_DIEPINT_EPDISD;
+
+ if ((epint & USB_OTG_DIEPINT_TXFE) ==
+ USB_OTG_DIEPINT_TXFE) {
+ *param = epnum;
+ return USB_WRITE_EMPTY;
+ }
+ }
+ }
+
+ /* Handle Resume Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_WKUINT) {
+ INFO("handle USB : Resume\n");
+ /* Clear the Remote Wake-up Signaling */
+ dwc2_handle.usb_device->dctl &= ~USB_OTG_DCTL_RWUSIG;
+ usbx->gintsts = USB_OTG_GINTSTS_WKUINT;
+ return USB_RESUME;
+ }
+
+ /* Handle Suspend Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_USBSUSP) {
+ INFO("handle USB : Suspend int\n");
+ usbx->gintsts = USB_OTG_GINTSTS_USBSUSP;
+ if ((dwc2_handle.usb_device->dsts & USB_OTG_DSTS_SUSPSTS) ==
+ USB_OTG_DSTS_SUSPSTS){
+ return USB_SUSPEND;
+ }
+ }
+
+ /* Handle LPM Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_LPMINT) {
+ INFO("handle USB : LPM int enter in suspend\n");
+ usbx->gintsts = USB_OTG_GINTSTS_LPMINT;
+ *param = (usbx->glpmcfg & USB_OTG_GLPMCFG_BESL) >> 2;
+ return USB_LPM;
+ }
+
+ /* Handle Reset Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_USBRST) {
+ INFO("handle USB : Reset\n");
+ dwc2_handle.usb_device->dctl &= ~USB_OTG_DCTL_RWUSIG;
+ usb_dwc2_flush_tx_fifo(usbx, 0);
+
+ dwc2_handle.usb_device->daint = 0xFFFFFFFF;
+ dwc2_handle.usb_device->daintmsk |= 0x10001;
+
+ dwc2_handle.usb_device->doepmsk |= (USB_OTG_DOEPMSK_STUPM |
+ USB_OTG_DOEPMSK_XFRCM |
+ USB_OTG_DOEPMSK_EPDM);
+ dwc2_handle.usb_device->diepmsk |= (USB_OTG_DIEPMSK_TOM |
+ USB_OTG_DIEPMSK_XFRCM |
+ USB_OTG_DIEPMSK_EPDM);
+
+ /* Set Default Address to 0 */
+ dwc2_handle.usb_device->dcfg &= ~USB_OTG_DCFG_DAD;
+
+ /* setup EP0 to receive SETUP packets */
+ usb_dwc2_ep0_out_start(usbx);
+
+ usbx->gintsts = USB_OTG_GINTSTS_USBRST;
+ }
+
+ /* Handle Enumeration done Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_ENUMDNE) {
+ usb_dwc2_activate_setup(usbx);
+ usbx->gusbcfg &= ~USB_OTG_GUSBCFG_TRDT;
+
+ usbx->gusbcfg |= (uint32_t)((USBD_HS_TRDT_VALUE << 10) &
+ USB_OTG_GUSBCFG_TRDT);
+
+ usbx->gintsts = USB_OTG_GINTSTS_ENUMDNE;
+ return USB_ENUM_DONE;
+ }
+
+ /* Handle RxQLevel Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_RXFLVL) {
+ usbx->gintmsk &= ~USB_OTG_GINTSTS_RXFLVL;
+ temp = usbx->grxstsp;
+ *param = (temp & USB_OTG_GRXSTSP_EPNUM);
+ *param |= ((temp & USB_OTG_GRXSTSP_BCNT) << 0xC);
+
+ if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) {
+ if ((temp & USB_OTG_GRXSTSP_BCNT) != 0) {
+ usbx->gintmsk |= USB_OTG_GINTSTS_RXFLVL;
+ return USB_READ_DATA_PACKET;
+ }
+ } else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==
+ STS_SETUP_UPDT) {
+ usbx->gintmsk |= USB_OTG_GINTSTS_RXFLVL;
+ return USB_READ_SETUP_PACKET;
+ }
+ usbx->gintmsk |= USB_OTG_GINTSTS_RXFLVL;
+ }
+
+ /* Handle SOF Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_SOF) {
+ INFO("handle USB : SOF\n");
+ usbx->gintsts = USB_OTG_GINTSTS_SOF;
+ return USB_SOF;
+ }
+
+ /* Handle Incomplete ISO IN Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_IISOIXFR) {
+ INFO("handle USB : ISO IN\n");
+ usbx->gintsts = USB_OTG_GINTSTS_IISOIXFR;
+ }
+
+ /* Handle Incomplete ISO OUT Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_PXFR_INCOMPISOOUT) {
+ INFO("handle USB : ISO OUT\n");
+ usbx->gintsts = USB_OTG_GINTSTS_PXFR_INCOMPISOOUT;
+ }
+
+ /* Handle Connection event Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_SRQINT) {
+ INFO("handle USB : Connect\n");
+ usbx->gintsts = USB_OTG_GINTSTS_SRQINT;
+ }
+
+ /* Handle Disconnection event Interrupt */
+ if (usb_dwc2_read_int(usbx) & USB_OTG_GINTSTS_OTGINT) {
+ INFO("handle USB : Disconnect\n");
+ temp = usbx->gotgint;
+ if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
+ return USB_DISCONNECT;
+ }
+ return USB_NOTHING;
+}
+
+void usb_dwc2_init_driver(usb_handle_t *usb_core_handle,
+ uint32_t *base_register)
+{
+ uint32_t i = 0;
+ uintptr_t base = (uintptr_t)base_register;
+
+ dwc2_handle.usb_global = (usb_dwc2_global_t *)base;
+
+ dwc2_handle.usb_device = (usb_dwc2_device_t *)
+ (base + USB_OTG_DEVICE_BASE);
+
+ for (i = 0; i < USB_MAX_ENDPOINT_NB; i++) {
+ dwc2_handle.usb_in_endpoint[i] = (usb_dwc2_endpoint_t *)
+ (base + USB_OTG_IN_ENDPOINT_BASE +
+ (i * sizeof(usb_dwc2_endpoint_t)));
+ dwc2_handle.usb_out_endpoint[i] = (usb_dwc2_endpoint_t *)
+ (base + USB_OTG_OUT_ENDPOINT_BASE +
+ (i * sizeof(usb_dwc2_endpoint_t)));
+ dwc2_handle.usb_fifo[i] = (uint32_t *)(base +
+ USB_OTG_FIFO_BASE +
+ (i * USB_OTG_FIFO_SIZE));
+ }
+
+ register_usb_driver(usb_core_handle, &usb_dwc2driver,
+ (void *)&dwc2_handle);
+}
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index d46fa61..34cce95 100644
--- a/drivers/ti/uart/aarch64/16550_console.S
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -7,6 +7,7 @@
#include <arch.h>
#include <asm_macros.S>
#include <assert_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
#include <uart_16550.h>
@@ -111,7 +112,7 @@ func console_16550_register
mov x0, x6
mov x30, x7
- finish_console_register 16550
+ finish_console_register 16550 putc=1, getc=1, flush=1
register_fail:
ret x7
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
index be4e2c3..1a5c51c 100644
--- a/fdts/stm32mp15-ddr.dtsi
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -5,7 +5,7 @@
/ {
soc {
- ddr: ddr@0x5A003000{
+ ddr: ddr@5A003000{
compatible = "st,stm32mp1-ddr";
diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
new file mode 100644
index 0000000..16b8cf6
--- /dev/null
+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+/* STM32MP157C DK1/DK2 BOARD configuration
+ * 1x DDR3L 4Gb, 16-bit, 533MHz.
+ * Reference used NT5CC256M16DP-DI from NANYA
+ *
+ * DDR type / Platform DDR3/3L
+ * freq 533MHz
+ * width 16
+ * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G
+ * DDR density 4
+ * timing mode optimized
+ * Scheduling/QoS options : type = 2
+ * address mapping : RBC
+ * Tc > + 85C : N
+ */
+
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41"
+#define DDR_MEM_SPEED 533000
+#define DDR_MEM_SIZE 0x20000000
+
+#define DDR_MSTR 0x00041401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0081008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B2414
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ADDRMAP1 0x00070707
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x1F000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x06060606
+#define DDR_ADDRMAP6 0x0F060606
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200001F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000208
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
index 58a4cdc..82e7104 100644
--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -3,7 +3,7 @@
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
-/* STM32MP157C ED1 and ED2 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
*
@@ -15,10 +15,11 @@
* timing mode optimized
* Scheduling/QoS options : type = 2
* address mapping : RBC
+ * Tc > + 85C : N
*/
-#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39"
-#define DDR_MEM_SPEED 533
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41"
+#define DDR_MEM_SPEED 533000
#define DDR_MEM_SIZE 0x40000000
#define DDR_MSTR 0x00040401
@@ -62,7 +63,7 @@
#define DDR_ADDRMAP11 0x00000000
#define DDR_ODTCFG 0x06000600
#define DDR_ODTMAP 0x00000001
-#define DDR_SCHED 0x00001201
+#define DDR_SCHED 0x00000C01
#define DDR_SCHED1 0x00000000
#define DDR_PERFHPR1 0x01000001
#define DDR_PERFLPR1 0x08000200
@@ -74,15 +75,15 @@
#define DDR_PCCFG 0x00000010
#define DDR_PCFGR_0 0x00010000
#define DDR_PCFGW_0 0x00000000
-#define DDR_PCFGQOS0_0 0x02100B03
+#define DDR_PCFGQOS0_0 0x02100C03
#define DDR_PCFGQOS1_0 0x00800100
-#define DDR_PCFGWQOS0_0 0x01100B03
+#define DDR_PCFGWQOS0_0 0x01100C03
#define DDR_PCFGWQOS1_0 0x01000200
#define DDR_PCFGR_1 0x00010000
#define DDR_PCFGW_1 0x00000000
-#define DDR_PCFGQOS0_1 0x02100B03
-#define DDR_PCFGQOS1_1 0x00800000
-#define DDR_PCFGWQOS0_1 0x01100B03
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
#define DDR_PCFGWQOS1_1 0x01000200
#define DDR_PGCR 0x01442E02
#define DDR_PTR0 0x0022AA5B
diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi
index 21bd34e..8037e4f 100644
--- a/fdts/stm32mp157-pinctrl.dtsi
+++ b/fdts/stm32mp157-pinctrl.dtsi
@@ -3,13 +3,14 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+
/ {
soc {
- pinctrl: pin-controller {
+ pinctrl: pin-controller@50002000 {
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "st,stm32mp157-pinctrl";
ranges = <0 0x50002000 0xa400>;
pins-are-numbered;
@@ -134,54 +135,76 @@
status = "disabled";
};
- uart4_pins_a: uart4@0 {
+ qspi_bk1_pins_a: qspi-bk1-0 {
pins1 {
- pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+ <STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */
+ <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+ <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <0>;
+ slew-rate = <1>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
- bias-disable;
+ pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <1>;
};
};
- usart3_pins_a: usart3@0 {
+ qspi_bk2_pins_a: qspi-bk2-0 {
pins1 {
- pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
- <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+ pinmux = <STM32_PINMUX('H', 2, AF9)>, /* QSPI_BK2_IO0 */
+ <STM32_PINMUX('H', 3, AF9)>, /* QSPI_BK2_IO1 */
+ <STM32_PINMUX('G', 10, AF11)>, /* QSPI_BK2_IO2 */
+ <STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <0>;
+ slew-rate = <1>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
- <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
- bias-disable;
+ pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <1>;
};
};
- sdmmc1_b4_pins_a: sdmmc1-b4@0 {
+ qspi_clk_pins_a: qspi-clk-0 {
pins {
+ pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+ pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
<STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
- <STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
<STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
- slew-rate = <3>;
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+ slew-rate = <2>;
drive-push-pull;
bias-disable;
};
};
- sdmmc1_dir_pins_a: sdmmc1-dir@0 {
+ sdmmc1_dir_pins_a: sdmmc1-dir-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
<STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
<STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
- slew-rate = <3>;
+ slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
@@ -191,36 +214,113 @@
};
};
- sdmmc2_b4_pins_a: sdmmc2-b4@0 {
- pins {
+ sdmmc1_dir_pins_b: sdmmc1-dir-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 12, AF8)>, /* SDMMC1_D0DIR */
+ <STM32_PINMUX('E', 14, AF11)>, /* SDMMC1_D123DIR */
+ <STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+ bias-pull-up;
+ };
+ };
+
+ sdmmc2_b4_pins_a: sdmmc2-b4-0 {
+ pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
- <STM32_PINMUX('E', 3, AF9)>, /* SDMMC2_CK */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
- slew-rate = <3>;
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+ slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
};
- sdmmc2_d47_pins_a: sdmmc2-d47@0 {
+ sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
- slew-rate = <3>;
+ slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
+
+ uart4_pins_a: uart4-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ bias-disable;
+ };
+ };
+
+ uart7_pins_a: uart7-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+ bias-disable;
+ };
+ };
+
+ usart3_pins_a: usart3-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+ <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+ <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+ bias-disable;
+ };
+ };
+
+ usart3_pins_b: usart3-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+ <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+ <STM32_PINMUX('B', 13, AF7)>; /* USART3_CTS_NSS */
+ bias-disable;
+ };
+ };
};
- pinctrl_z: pin-controller-z {
+ pinctrl_z: pin-controller-z@54004000 {
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "st,stm32mp157-z-pinctrl";
ranges = <0 0x54004000 0x400>;
pins-are-numbered;
@@ -236,7 +336,7 @@
status = "disabled";
};
- i2c4_pins_a: i2c4@0 {
+ i2c4_pins_a: i2c4-0 {
pins {
pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts
new file mode 100644
index 0000000..fadb442
--- /dev/null
+++ b/fdts/stm32mp157a-dk1.dts
@@ -0,0 +1,464 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018-2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157cac-pinctrl.dtsi"
+
+/ {
+ model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
+ compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
+
+ aliases {
+ serial0 = &uart4;
+ serial1 = &usart3;
+ serial2 = &uart7;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+};
+
+&clk_hse {
+ st,digbypass;
+};
+
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_pins_a>;
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+
+ pmic: stpmic@33 {
+ compatible = "st,stpmic1";
+ reg = <0x33>;
+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ status = "okay";
+
+ st,main-control-register = <0x04>;
+ st,vin-control-register = <0xc0>;
+ st,usb-control-register = <0x20>;
+
+ regulators {
+ compatible = "st,stpmic1-regulators";
+
+ ldo1-supply = <&v3v3>;
+ ldo3-supply = <&vdd_ddr>;
+ ldo6-supply = <&v3v3>;
+
+ vddcore: buck1 {
+ regulator-name = "vddcore";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd_ddr: buck2 {
+ regulator-name = "vdd_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd: buck3 {
+ regulator-name = "vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ st,mask-reset;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ v3v3: buck4 {
+ regulator-name = "v3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-over-current-protection;
+ regulator-initial-mode = <0>;
+ };
+
+ v1v8_audio: ldo1 {
+ regulator-name = "v1v8_audio";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ v3v3_hdmi: ldo2 {
+ regulator-name = "v3v3_hdmi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vtt_ddr: ldo3 {
+ regulator-name = "vtt_ddr";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <750000>;
+ regulator-always-on;
+ regulator-over-current-protection;
+ };
+
+ vdd_usb: ldo4 {
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vdda: ldo5 {
+ regulator-name = "vdda";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-boot-on;
+ };
+
+ v1v2_hdmi: ldo6 {
+ regulator-name = "v1v2_hdmi";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ vref_ddr: vref_ddr {
+ regulator-name = "vref_ddr";
+ regulator-always-on;
+ regulator-over-current-protection;
+ };
+ };
+ };
+};
+
+&iwdg2 {
+ timeout-sec = <32>;
+ status = "okay";
+};
+
+&pwr {
+ pwr-supply = <&vdd>;
+};
+
+&rng1 {
+ status = "okay";
+};
+
+&rtc {
+ status = "okay";
+};
+
+&sdmmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_b4_pins_a>;
+ broken-cd;
+ st,neg-edge;
+ bus-width = <4>;
+ vmmc-supply = <&v3v3>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins_a>;
+ status = "okay";
+};
+
+&uart7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart7_pins_a>;
+ status = "disabled";
+};
+
+&usart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usart3_pins_b>;
+ status = "disabled";
+};
+
+
+/* ATF Specific */
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
+#include "stm32mp157c-security.dtsi"
+
+/ {
+ aliases {
+ gpio0 = &gpioa;
+ gpio1 = &gpiob;
+ gpio2 = &gpioc;
+ gpio3 = &gpiod;
+ gpio4 = &gpioe;
+ gpio5 = &gpiof;
+ gpio6 = &gpiog;
+ gpio7 = &gpioh;
+ gpio8 = &gpioi;
+ gpio25 = &gpioz;
+ i2c3 = &i2c4;
+ };
+};
+
+/* CLOCK init */
+&rcc {
+ secure-status = "okay";
+ st,hsi-cal;
+ st,csi-cal;
+ st,cal-sec = <60>;
+ st,clksrc = <
+ CLK_MPU_PLL1P
+ CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
+ CLK_PLL12_HSE
+ CLK_PLL3_HSE
+ CLK_PLL4_HSE
+ CLK_RTC_LSE
+ CLK_MCO1_DISABLED
+ CLK_MCO2_DISABLED
+ >;
+
+ st,clkdiv = <
+ 1 /*MPU*/
+ 0 /*AXI*/
+ 0 /*MCU*/
+ 1 /*APB1*/
+ 1 /*APB2*/
+ 1 /*APB3*/
+ 1 /*APB4*/
+ 2 /*APB5*/
+ 23 /*RTC*/
+ 0 /*MCO1*/
+ 0 /*MCO2*/
+ >;
+
+ st,pkcs = <
+ CLK_CKPER_HSE
+ CLK_FMC_ACLK
+ CLK_QSPI_ACLK
+ CLK_ETH_DISABLED
+ CLK_SDMMC12_PLL4P
+ CLK_DSI_DSIPLL
+ CLK_STGEN_HSE
+ CLK_USBPHY_HSE
+ CLK_SPI2S1_PLL3Q
+ CLK_SPI2S23_PLL3Q
+ CLK_SPI45_HSI
+ CLK_SPI6_HSI
+ CLK_I2C46_HSI
+ CLK_SDMMC3_PLL4P
+ CLK_USBO_USBPHY
+ CLK_ADC_CKPER
+ CLK_CEC_LSE
+ CLK_I2C12_HSI
+ CLK_I2C35_HSI
+ CLK_UART1_HSI
+ CLK_UART24_HSI
+ CLK_UART35_HSI
+ CLK_UART6_HSI
+ CLK_UART78_HSI
+ CLK_SPDIF_PLL4P
+ CLK_FDCAN_PLL4Q
+ CLK_SAI1_PLL3Q
+ CLK_SAI2_PLL3Q
+ CLK_SAI3_PLL3Q
+ CLK_SAI4_PLL3Q
+ CLK_RNG1_LSI
+ CLK_RNG2_LSI
+ CLK_LPTIM1_PCLK1
+ CLK_LPTIM23_PCLK3
+ CLK_LPTIM45_LSE
+ >;
+
+ /* VCO = 1300.0 MHz => P = 650 (CPU) */
+ pll1: st,pll@0 {
+ cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+ frac = < 0x800 >;
+ };
+
+ /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+ pll2: st,pll@1 {
+ cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+ frac = < 0x1400 >;
+ };
+
+ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+ pll3: st,pll@2 {
+ cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+ frac = < 0x1a04 >;
+ };
+
+ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
+ pll4: st,pll@3 {
+ cfg = < 3 98 5 7 7 PQR(1,1,1) >;
+ };
+};
+
+/* Security specific */
+&etzpc {
+ st,decprot = <
+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ >;
+};
+
+&iwdg2 {
+ secure-status = "okay";
+};
+
+&pwr {
+ system_suspend_supported_soc_modes = <
+ STM32_PM_CSLEEP_RUN
+ STM32_PM_CSTOP_ALLOW_LP_STOP
+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR
+ >;
+
+ system_off_soc_mode = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
+};
+
+&timers15 {
+ secure-status = "okay";
+ st,hsi-cal-input = <7>;
+ st,csi_cal-input = <8>;
+};
+
+/* Low-power states of regulators */
+&vddcore {
+ lp-stop {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1200000>;
+ };
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd_ddr {
+ lp-stop {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd {
+ lp-stop {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+};
+
+&v3v3 {
+ lp-stop {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&v1v8_audio {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&v3v3_hdmi {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vtt_ddr {
+ lp-stop {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd_usb {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdda {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&v1v2_hdmi {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vref_ddr {
+ lp-stop {
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts
new file mode 100644
index 0000000..fdcf4c8
--- /dev/null
+++ b/fdts/stm32mp157c-dk2.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157a-dk1.dts"
+
+/ {
+ model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
+ compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
+
+};
+
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index e3dabe8..0daf4be 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -1,24 +1,30 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
/dts-v1/;
#include "stm32mp157c.dtsi"
#include "stm32mp157caa-pinctrl.dtsi"
/ {
- model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter";
+ model = "STMicroelectronics STM32MP157C eval daughter";
compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
chosen {
- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
- stdout-path = "serial3:115200n8";
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ serial0 = &uart4;
};
};
+&clk_hse {
+ st,digbypass;
+};
+
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins_a>;
@@ -26,37 +32,88 @@
i2c-scl-falling-time-ns = <20>;
status = "okay";
- pmic: stpmu1@33 {
- compatible = "st,stpmu1";
+ pmic: stpmic@33 {
+ compatible = "st,stpmic1";
reg = <0x33>;
+ interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
status = "okay";
- st,main_control_register = <0x04>;
- st,vin_control_register = <0xc0>;
- st,usb_control_register = <0x30>;
+ st,main-control-register = <0x04>;
+ st,vin-control-register = <0xc0>;
+ st,usb-control-register = <0x20>;
regulators {
- compatible = "st,stpmu1-regulators";
+ compatible = "st,stpmic1-regulators";
+
+ ldo1-supply = <&v3v3>;
+ ldo2-supply = <&v3v3>;
+ ldo3-supply = <&vdd_ddr>;
+ ldo5-supply = <&v3v3>;
+ ldo6-supply = <&v3v3>;
+
+ vddcore: buck1 {
+ regulator-name = "vddcore";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd_ddr: buck2 {
+ regulator-name = "vdd_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
+
+ vdd: buck3 {
+ regulator-name = "vdd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ st,mask-reset;
+ regulator-initial-mode = <0>;
+ regulator-over-current-protection;
+ };
v3v3: buck4 {
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- regulator-boot-on;
+ regulator-always-on;
+ regulator-over-current-protection;
+ regulator-initial-mode = <0>;
+ };
+
+ vdda: ldo1 {
+ regulator-name = "vdda";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ v2v8: ldo2 {
+ regulator-name = "v2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vtt_ddr: ldo3 {
+ regulator-name = "vtt_ddr";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <750000>;
+ regulator-always-on;
regulator-over-current-protection;
- regulator-initial-mode = <8>;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <3300000>;
- regulator-unchanged-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
+ };
+
+ vdd_usb: ldo4 {
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
};
vdd_sd: ldo5 {
@@ -64,40 +121,49 @@
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
regulator-boot-on;
+ };
- regulator-state-standby {
- regulator-suspend-microvolt = <2900000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
+ v1v8: ldo6 {
+ regulator-name = "v1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vref_ddr: vref_ddr {
+ regulator-name = "vref_ddr";
+ regulator-always-on;
+ regulator-over-current-protection;
};
};
};
};
&iwdg2 {
- instance = <2>;
timeout-sec = <32>;
status = "okay";
};
+&pwr {
+ pwr-supply = <&vdd>;
+};
+
&rng1 {
status = "okay";
};
+&rtc {
+ status = "okay";
+};
+
&sdmmc1 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
broken-cd;
- st,dirpol;
- st,negedge;
- st,pin-ckin;
+ st,sig-dir;
+ st,neg-edge;
+ st,use-ckin;
bus-width = <4>;
+ vmmc-supply = <&vdd_sd>;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;
@@ -112,22 +178,25 @@
non-removable;
no-sd;
no-sdio;
- st,dirpol;
- st,negedge;
+ st,neg-edge;
bus-width = <8>;
+ vmmc-supply = <&v3v3>;
+ vqmmc-supply = <&v3v3>;
+ mmc-ddr-3_3v;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
- resets = <&rcc UART4_R>;
status = "okay";
};
/* ATF Specific */
#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <dt-bindings/power/stm32mp1-power.h>
#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+#include "stm32mp157c-security.dtsi"
/ {
aliases {
@@ -145,21 +214,18 @@
gpio25 = &gpioz;
i2c3 = &i2c4;
};
-
- soc {
- stgen: stgen@5C008000 {
- compatible = "st,stm32-stgen";
- reg = <0x5C008000 0x1000>;
- status = "okay";
- };
- };
};
/* CLOCK init */
&rcc {
+ secure-status = "okay";
+ st,hsi-cal;
+ st,csi-cal;
+ st,cal-sec = <60>;
st,clksrc = <
CLK_MPU_PLL1P
CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
CLK_PLL12_HSE
CLK_PLL3_HSE
CLK_PLL4_HSE
@@ -171,6 +237,7 @@
st,clkdiv = <
1 /*MPU*/
0 /*AXI*/
+ 0 /*MCU*/
1 /*APB1*/
1 /*APB2*/
1 /*APB3*/
@@ -186,7 +253,7 @@
CLK_FMC_ACLK
CLK_QSPI_ACLK
CLK_ETH_DISABLED
- CLK_SDMMC12_PLL3R
+ CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
CLK_USBPHY_HSE
@@ -195,7 +262,7 @@
CLK_SPI45_HSI
CLK_SPI6_HSI
CLK_I2C46_HSI
- CLK_SDMMC3_PLL3R
+ CLK_SDMMC3_PLL4P
CLK_USBO_USBPHY
CLK_ADC_CKPER
CLK_CEC_LSE
@@ -206,17 +273,17 @@
CLK_UART35_HSI
CLK_UART6_HSI
CLK_UART78_HSI
- CLK_SPDIF_PLL3Q
+ CLK_SPDIF_PLL4P
CLK_FDCAN_PLL4Q
CLK_SAI1_PLL3Q
CLK_SAI2_PLL3Q
CLK_SAI3_PLL3Q
CLK_SAI4_PLL3Q
- CLK_RNG1_CSI
- CLK_RNG2_CSI
+ CLK_RNG1_LSI
+ CLK_RNG2_LSI
CLK_LPTIM1_PCLK1
CLK_LPTIM23_PCLK3
- CLK_LPTIM45_PCLK3
+ CLK_LPTIM45_LSE
>;
/* VCO = 1300.0 MHz => P = 650 (CPU) */
@@ -231,16 +298,167 @@
frac = < 0x1400 >;
};
- /* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */
+ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
pll3: st,pll@2 {
- cfg = < 2 97 3 15 7 PQR(1,1,1) >;
- frac = < 0x9ba >;
+ cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+ frac = < 0x1a04 >;
};
- /* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */
+ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
pll4: st,pll@3 {
- cfg = < 5 126 8 8 8 PQR(1,1,1) >;
+ cfg = < 3 98 5 7 7 PQR(1,1,1) >;
};
};
-/delete-node/ &clk_csi;
+/* Security specific */
+&etzpc {
+ st,decprot = <
+ DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
+ >;
+};
+
+&iwdg2 {
+ secure-status = "okay";
+};
+
+&pwr {
+ system_suspend_supported_soc_modes = <
+ STM32_PM_CSLEEP_RUN
+ STM32_PM_CSTOP_ALLOW_LP_STOP
+ STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR
+ >;
+ system_off_soc_mode = <STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF>;
+};
+
+&timers15 {
+ secure-status = "okay";
+ st,hsi-cal-input = <7>;
+ st,csi_cal-input = <8>;
+};
+
+/* Low-power states of regulators */
+&vddcore {
+ lp-stop {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1200000>;
+ };
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd_ddr {
+ lp-stop {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-suspend-microvolt = <1350000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd {
+ lp-stop {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-suspend-microvolt = <3300000>;
+ regulator-on-in-suspend;
+ };
+};
+
+&v3v3 {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdda {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&v2v8 {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vtt_ddr {
+ lp-stop {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd_usb {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vdd_sd {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&v1v8 {
+ standby-ddr-sr {
+ regulator-off-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
+
+&vref_ddr {
+ lp-stop {
+ regulator-on-in-suspend;
+ };
+ standby-ddr-sr {
+ regulator-on-in-suspend;
+ };
+ standby-ddr-off {
+ regulator-off-in-suspend;
+ };
+};
diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts
index 98a9d35..cfde8ed 100644
--- a/fdts/stm32mp157c-ev1.dts
+++ b/fdts/stm32mp157c-ev1.dts
@@ -3,23 +3,65 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
/dts-v1/;
+
#include "stm32mp157c-ed1.dts"
/ {
- model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother";
+ model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
chosen {
- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
- stdout-path = "serial3:115200n8";
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ serial1 = &usart3;
+ };
+};
+
+&fmc {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand: nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>;
+ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash0: mx66l51235l@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ flash1: mx66l51235l@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
};
};
&usart3 {
pinctrl-names = "default";
pinctrl-0 = <&usart3_pins_a>;
- resets = <&rcc USART3_R>;
status = "disabled";
};
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
new file mode 100644
index 0000000..8d45a33
--- /dev/null
+++ b/fdts/stm32mp157c-security.dtsi
@@ -0,0 +1,71 @@
+/*
+ * Copyright : STMicroelectronics 2017
+ *
+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
+ */
+
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+
+/ {
+ soc {
+ iwdg1: iwdg@5C003000 {
+ compatible = "st,stm32mp1-iwdg";
+ reg = <0x5C003000 0x400>;
+ clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
+ clock-names = "pclk", "lsi";
+ interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ secure-status = "disabled";
+ };
+
+ etzpc: etzpc@5C007000 {
+ compatible = "st,stm32-etzpc";
+ reg = <0x5C007000 0x400>;
+ clocks = <&rcc TZPC>;
+ status = "disabled";
+ secure-status = "okay";
+ };
+
+ stgen: stgen@5C008000 {
+ compatible = "st,stm32-stgen";
+ reg = <0x5C008000 0x1000>;
+ };
+ };
+};
+
+&bsec {
+ mac_addr: mac_addr@e4 {
+ reg = <0xe4 0x6>;
+ };
+ /* Spare field to align on 32-bit OTP granularity */
+ spare_ns_ea: spare_ns_ea@ea {
+ reg = <0xea 0x2>;
+ };
+ board_id: board_id@ec {
+ reg = <0xec 0x4>;
+ };
+};
+
+&iwdg2 {
+ secure-interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&rcc {
+ secure-interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "wakeup";
+};
+
+&sdmmc1 {
+ compatible = "st,stm32-sdmmc2";
+};
+
+&sdmmc2 {
+ compatible = "st,stm32-sdmmc2";
+};
+
+&tamp {
+ compatible = "st,stm32-tamp";
+ clocks = <&rcc RTCAPB>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ secure-status= "disabled";
+};
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
index 8b13c0e..06c2cf1 100644
--- a/fdts/stm32mp157c.dtsi
+++ b/fdts/stm32mp157c.dtsi
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
@@ -11,15 +11,12 @@
#address-cells = <1>;
#size-cells = <1>;
- aliases {
- serial0 = &usart1;
- serial1 = &usart2;
- serial2 = &usart3;
- serial3 = &uart4;
- serial4 = &uart5;
- serial5 = &usart6;
- serial6 = &uart7;
- serial7 = &uart8;
+ intc: interrupt-controller@a0021000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0xa0021000 0x1000>,
+ <0xa0022000 0x2000>;
};
clocks {
@@ -56,7 +53,7 @@
clk_i2s_ckin: i2s_ckin {
#clock-cells = <0>;
compatible = "fixed-clock";
- clock-frequency = <64000000>;
+ clock-frequency = <0>;
};
clk_dsi_phy: ck_dsi_phy {
@@ -64,31 +61,38 @@
compatible = "fixed-clock";
clock-frequency = <0>;
};
-
- clk_usbo_48m: ck_usbo_48m {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <48000000>;
- };
};
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
+ interrupt-parent = <&intc>;
ranges;
+ timers12: timer@40006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40006000 0x400>;
+ clocks = <&rcc TIM12_K>;
+ clock-names = "int";
+ status = "disabled";
+ };
+
usart2: serial@4000e000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
clocks = <&rcc USART2_K>;
+ resets = <&rcc USART2_R>;
status = "disabled";
};
usart3: serial@4000f000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
clocks = <&rcc USART3_K>;
+ resets = <&rcc USART3_R>;
status = "disabled";
};
@@ -96,6 +100,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
clocks = <&rcc UART4_K>;
+ resets = <&rcc UART4_R>;
status = "disabled";
};
@@ -103,6 +108,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
clocks = <&rcc UART5_K>;
+ resets = <&rcc UART5_R>;
status = "disabled";
};
@@ -111,6 +117,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
clocks = <&rcc UART7_K>;
+ resets = <&rcc UART7_R>;
status = "disabled";
};
@@ -118,21 +125,34 @@
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
clocks = <&rcc UART8_K>;
+ resets = <&rcc UART8_R>;
status = "disabled";
};
usart6: serial@44003000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
clocks = <&rcc USART6_K>;
+ resets = <&rcc USART6_R>;
+ status = "disabled";
+ };
+
+ timers15: timer@44006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44006000 0x400>;
+ clocks = <&rcc TIM15_K>;
+ clock-names = "int";
status = "disabled";
};
sdmmc3: sdmmc@48004000 {
- compatible = "st,stm32-sdmmc2";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00253180>;
reg = <0x48004000 0x400>, <0x48005000 0x400>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC3_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC3_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -140,18 +160,69 @@
status = "disabled";
};
+ usbotg_hs: usb-otg@49000000 {
+ compatible = "st,stm32mp1-hsotg", "snps,dwc2";
+ reg = <0x49000000 0x10000>;
+ clocks = <&rcc USBO_K>;
+ clock-names = "otg";
+ resets = <&rcc USBO_R>;
+ reset-names = "dwc2";
+ status = "disabled";
+ };
+
rcc: rcc@50000000 {
- compatible = "syscon", "st,stm32mp1-rcc";
+ compatible = "st,stm32mp1-rcc", "syscon";
+ reg = <0x50000000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
- reg = <0x50000000 0x1000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pwr: pwr@50001000 {
+ compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd";
+ reg = <0x50001000 0x400>;
};
- rcc_reboot: rcc-reboot@50000000 {
- compatible = "syscon-reboot";
- regmap = <&rcc>;
- offset = <0x404>;
- mask = <0x1>;
+ exti: interrupt-controller@5000d000 {
+ compatible = "st,stm32mp1-exti", "syscon";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x5000d000 0x400>;
+
+ /* exti_pwr is an extra interrupt controller used for
+ * EXTI 55 to 60. It's mapped on pwr interrupt
+ * controller.
+ */
+ exti_pwr: exti-pwr {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pwr>;
+ st,irq-number = <6>;
+ };
+ };
+
+ syscfg: syscon@50020000 {
+ compatible = "st,stm32mp157-syscfg", "syscon";
+ reg = <0x50020000 0x400>;
+ clocks = <&rcc SYSCFG>;
+ };
+
+ cryp1: cryp@54001000 {
+ compatible = "st,stm32mp1-cryp";
+ reg = <0x54001000 0x400>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CRYP1>;
+ resets = <&rcc CRYP1_R>;
+ status = "disabled";
+ };
+
+ hash1: hash@54002000 {
+ compatible = "st,stm32f756-hash";
+ reg = <0x54002000 0x400>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc HASH1>;
+ resets = <&rcc HASH1_R>;
+ status = "disabled";
};
rng1: rng@54003000 {
@@ -162,13 +233,15 @@
status = "disabled";
};
- fmc_nand: fmc_nand@58002000 {
- compatible = "st,stm32mp1-fmc";
+ fmc: nand-controller@58002000 {
+ compatible = "st,stm32mp15-fmc2";
reg = <0x58002000 0x1000>,
- <0x80000000 0x40000>,
- <0x81000000 0x40000>,
- <0x88000000 0x40000>,
- <0x89000000 0x40000>;
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>;
status = "disabled";
@@ -177,15 +250,18 @@
qspi: qspi@58003000 {
compatible = "st,stm32f469-qspi";
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
+ reg-names = "qspi", "qspi_mm";
clocks = <&rcc QSPI_K>;
+ resets = <&rcc QSPI_R>;
status = "disabled";
};
sdmmc1: sdmmc@58005000 {
- compatible = "st,stm32-sdmmc2";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00253180>;
reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC1_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC1_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -194,10 +270,11 @@
};
sdmmc2: sdmmc@58007000 {
- compatible = "st,stm32-sdmmc2";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00253180>;
reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC2_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -205,7 +282,7 @@
status = "disabled";
};
- iwdg2: iwdg@5a002000 {
+ iwdg2: watchdog@5a002000 {
compatible = "st,stm32mp1-iwdg";
reg = <0x5a002000 0x400>;
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
@@ -214,15 +291,34 @@
};
usart1: serial@5c000000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 26 1>;
clocks = <&rcc USART1_K>;
+ resets = <&rcc USART1_R>;
+ status = "disabled";
+ };
+
+ spi6: spi@5c001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32h7-spi";
+ reg = <0x5c001000 0x400>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc SPI6_K>;
+ resets = <&rcc SPI6_R>;
status = "disabled";
};
i2c4: i2c@5c002000 {
compatible = "st,stm32f7-i2c";
reg = <0x5c002000 0x400>;
+ interrupt-names = "event", "error", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 24 1>;
clocks = <&rcc I2C4_K>;
resets = <&rcc I2C4_R>;
#address-cells = <1>;
@@ -235,6 +331,41 @@
reg = <0x5c004000 0x400>;
clocks = <&rcc RTCAPB>, <&rcc RTC>;
clock-names = "pclk", "rtc_ck";
+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 19 1>;
+ status = "disabled";
+ };
+
+ bsec: nvmem@5c005000 {
+ compatible = "st,stm32mp15-bsec";
+ reg = <0x5c005000 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ts_cal1: calib@5c {
+ reg = <0x5c 0x2>;
+ };
+ ts_cal2: calib@5e {
+ reg = <0x5e 0x2>;
+ };
+ };
+
+ i2c6: i2c@5c009000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x5c009000 0x400>;
+ interrupt-names = "event", "error", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 54 1>;
+ clocks = <&rcc I2C6_K>;
+ resets = <&rcc I2C6_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ tamp: tamp@5c00a000 {
+ compatible = "simple-bus", "syscon", "simple-mfd";
+ reg = <0x5c00a000 0x400>;
};
};
};
diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi
index 774561a..9b9cd08 100644
--- a/fdts/stm32mp157caa-pinctrl.dtsi
+++ b/fdts/stm32mp157caa-pinctrl.dtsi
@@ -7,8 +7,8 @@
#include "stm32mp157-pinctrl.dtsi"
/ {
soc {
- pinctrl: pin-controller {
- compatible = "st,stm32mp157caa-pinctrl";
+ pinctrl: pin-controller@50002000 {
+ st,package = <STM32MP157CAA>;
gpioa: gpio@50002000 {
status = "okay";
@@ -77,8 +77,8 @@
};
};
- pinctrl_z: pin-controller-z {
- compatible = "st,stm32mp157caa-z-pinctrl";
+ pinctrl_z: pin-controller-z@54004000 {
+ st,package = <STM32MP157CAA>;
gpioz: gpio@54004000 {
status = "okay";
diff --git a/fdts/stm32mp157cab-pinctrl.dtsi b/fdts/stm32mp157cab-pinctrl.dtsi
new file mode 100644
index 0000000..c570cf9
--- /dev/null
+++ b/fdts/stm32mp157cab-pinctrl.dtsi
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ */
+
+#include "stm32mp157-pinctrl.dtsi"
+/ {
+ soc {
+ pinctrl: pin-controller@50002000 {
+ st,package = <STM32MP157CAB>;
+
+ gpioa: gpio@50002000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 0 16>;
+ };
+
+ gpiob: gpio@50003000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 16 16>;
+ };
+
+ gpioc: gpio@50004000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 32 16>;
+ };
+
+ gpiod: gpio@50005000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ gpioe: gpio@50006000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 64 16>;
+ };
+
+ gpiof: gpio@50007000 {
+ status = "okay";
+ ngpios = <6>;
+ gpio-ranges = <&pinctrl 6 86 6>;
+ };
+
+ gpiog: gpio@50008000 {
+ status = "okay";
+ ngpios = <10>;
+ gpio-ranges = <&pinctrl 6 102 10>;
+ };
+
+ gpioh: gpio@50009000 {
+ status = "okay";
+ ngpios = <2>;
+ gpio-ranges = <&pinctrl 0 112 2>;
+ };
+ };
+ };
+};
diff --git a/fdts/stm32mp157cac-pinctrl.dtsi b/fdts/stm32mp157cac-pinctrl.dtsi
new file mode 100644
index 0000000..777f991
--- /dev/null
+++ b/fdts/stm32mp157cac-pinctrl.dtsi
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ */
+
+#include "stm32mp157-pinctrl.dtsi"
+/ {
+ soc {
+ pinctrl: pin-controller@50002000 {
+ st,package = <STM32MP157CAC>;
+
+ gpioa: gpio@50002000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 0 16>;
+ };
+
+ gpiob: gpio@50003000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 16 16>;
+ };
+
+ gpioc: gpio@50004000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 32 16>;
+ };
+
+ gpiod: gpio@50005000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ gpioe: gpio@50006000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 64 16>;
+ };
+
+ gpiof: gpio@50007000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 80 16>;
+ };
+
+ gpiog: gpio@50008000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 96 16>;
+ };
+
+ gpioh: gpio@50009000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 112 16>;
+ };
+
+ gpioi: gpio@5000a000 {
+ status = "okay";
+ ngpios = <12>;
+ gpio-ranges = <&pinctrl 0 128 12>;
+ };
+ };
+
+ pinctrl_z: pin-controller-z@54004000 {
+ st,package = <STM32MP157CAC>;
+
+ gpioz: gpio@54004000 {
+ status = "okay";
+ ngpios = <8>;
+ gpio-ranges = <&pinctrl_z 0 400 8>;
+ };
+ };
+ };
+};
diff --git a/fdts/stm32mp157cad-pinctrl.dtsi b/fdts/stm32mp157cad-pinctrl.dtsi
new file mode 100644
index 0000000..c4c303a
--- /dev/null
+++ b/fdts/stm32mp157cad-pinctrl.dtsi
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ */
+
+#include "stm32mp157-pinctrl.dtsi"
+/ {
+ soc {
+ pinctrl: pin-controller@50002000 {
+ st,package = <STM32MP157CAD>;
+
+ gpioa: gpio@50002000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 0 16>;
+ };
+
+ gpiob: gpio@50003000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 16 16>;
+ };
+
+ gpioc: gpio@50004000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 32 16>;
+ };
+
+ gpiod: gpio@50005000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ gpioe: gpio@50006000 {
+ status = "okay";
+ ngpios = <16>;
+ gpio-ranges = <&pinctrl 0 64 16>;
+ };
+
+ gpiof: gpio@50007000 {
+ status = "okay";
+ ngpios = <6>;
+ gpio-ranges = <&pinctrl 6 86 6>;
+ };
+
+ gpiog: gpio@50008000 {
+ status = "okay";
+ ngpios = <10>;
+ gpio-ranges = <&pinctrl 6 102 10>;
+ };
+
+ gpioh: gpio@50009000 {
+ status = "okay";
+ ngpios = <2>;
+ gpio-ranges = <&pinctrl 0 112 2>;
+ };
+ };
+ };
+};
diff --git a/include/common/aarch32/console_macros.S b/include/common/aarch32/console_macros.S
new file mode 100644
index 0000000..7c30688
--- /dev/null
+++ b/include/common/aarch32/console_macros.S
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __CONSOLE_MACROS_S__
+#define __CONSOLE_MACROS_S__
+
+#include <console.h>
+
+/*
+ * This macro encapsulates the common setup that has to be done at the end of
+ * a console driver's register function. It will register all of the driver's
+ * callbacks in the console_t structure and initialize the flags field (by
+ * default consoles are enabled for the "boot" and "crash" states, this can be
+ * changed after registration with the console_set_scope() function). It ends
+ * with a tail call that will include return to the caller.
+ * REQUIRES console_t pointer in x0 and a valid return address in x30.
+ */
+/*
+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between
+ * the 2 variants of the finish_console_register macro and will be removed
+ * once the deprecated variant is removed.
+ */
+#ifndef USE_FINISH_CONSOLE_REG_2
+#if !ERROR_DEPRECATED
+ /* This version of the macro is deprecated. Use the new version */
+ .macro finish_console_register _driver
+ /*
+ * Add these weak definitions so we will automatically write a 0 if the
+ * function doesn't exist. I'd rather use .ifdef but that only works if
+ * the function was defined (not just declared .global) above this point
+ * in the file, which we can't guarantee.
+ */
+ .weak console_\_driver\()_putc
+ .weak console_\_driver\()_getc
+ .weak console_\_driver\()_flush
+
+ /* Don't use adrp on weak funcs! See GNU ld bugzilla issue 22589. */
+ ldr r1, =console_\_driver\()_putc
+ str r1, [r0, #CONSOLE_T_PUTC]
+ ldr r1, =console_\_driver\()_getc
+ str r1, [r0, #CONSOLE_T_GETC]
+ ldr r1, =console_\_driver\()_flush
+ str r1, [r0, #CONSOLE_T_FLUSH]
+ mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
+ str r1, [r0, #CONSOLE_T_FLAGS]
+ b console_register
+ .endm
+#endif /* ERROR_DEPRECATED */
+#else /* USE_FINISH_CONSOLE_REG_2 */
+ /* The new version of the macro not using weak references */
+ .macro finish_console_register _driver, putc=0, getc=0, flush=0
+ /*
+ * If any of the callback is not specified or set as 0, then the
+ * corresponding callback entry in console_t is set to 0.
+ */
+ .ifne \putc
+ ldr r1, =console_\_driver\()_putc
+ .else
+ mov r1, #0
+ .endif
+ str r1, [r0, #CONSOLE_T_PUTC]
+
+ .ifne \getc
+ ldr r1, =console_\_driver\()_getc
+ .else
+ mov r1, #0
+ .endif
+ str r1, [r0, #CONSOLE_T_GETC]
+
+ .ifne \flush
+ ldr r1, =console_\_driver\()_flush
+ .else
+ mov r1, #0
+ .endif
+ str r1, [r0, #CONSOLE_T_FLUSH]
+
+ mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
+ str r1, [r0, #CONSOLE_T_FLAGS]
+ b console_register
+ .endm
+#endif /* USE_FINISH_CONSOLE_REG_2 */
+#endif /* __CONSOLE_MACROS_S__ */
diff --git a/include/common/aarch64/console_macros.S b/include/common/aarch64/console_macros.S
index 0ebea2c..b285ecc 100644
--- a/include/common/aarch64/console_macros.S
+++ b/include/common/aarch64/console_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,6 +17,14 @@
* with a tail call that will include return to the caller.
* REQUIRES console_t pointer in x0 and a valid return address in x30.
*/
+/*
+ * The USE_FINISH_CONSOLE_REG_2 guard is introduced to allow selection between
+ * the 2 variants of the finish_console_register macro and will be removed
+ * once the deprecated variant is removed.
+ */
+#ifndef USE_FINISH_CONSOLE_REG_2
+#if !ERROR_DEPRECATED
+ /* This version of the macro is deprecated. Use the new version */
.macro finish_console_register _driver
/*
* Add these weak definitions so we will automatically write a 0 if the
@@ -39,5 +47,41 @@
str x1, [x0, #CONSOLE_T_FLAGS]
b console_register
.endm
+#endif /* ERROR_DEPRECATED */
+#else /* USE_FINISH_CONSOLE_REG_2 */
+ /* The new version of the macro not using weak references */
+ .macro finish_console_register _driver, putc=0, getc=0, flush=0
+ /*
+ * If any of the callback is not specified or set as 0, then the
+ * corresponding callback entry in console_t is set to 0.
+ */
+ .ifne \putc
+ adrp x1, console_\_driver\()_putc
+ add x1, x1, :lo12:console_\_driver\()_putc
+ str x1, [x0, #CONSOLE_T_PUTC]
+ .else
+ str xzr, [x0, #CONSOLE_T_PUTC]
+ .endif
+
+ .ifne \getc
+ adrp x1, console_\_driver\()_getc
+ add x1, x1, :lo12:console_\_driver\()_getc
+ str x1, [x0, #CONSOLE_T_GETC]
+ .else
+ str xzr, [x0, #CONSOLE_T_GETC]
+ .endif
+ .ifne \flush
+ adrp x1, console_\_driver\()_flush
+ add x1, x1, :lo12:console_\_driver\()_flush
+ str x1, [x0, #CONSOLE_T_FLUSH]
+ .else
+ str xzr, [x0, #CONSOLE_T_FLUSH]
+ .endif
+
+ mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH)
+ str x1, [x0, #CONSOLE_T_FLAGS]
+ b console_register
+ .endm
+#endif /* USE_FINISH_CONSOLE_REG_2 */
#endif /* __CONSOLE_MACROS_S__ */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index a97914d..96bfb53 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -77,7 +77,13 @@
/* NT_FW_CONFIG */
#define NT_FW_CONFIG_ID U(27)
+/* GPT Partition */
+#define GPT_IMAGE_ID U(28)
+
+/* Binary with STM32 header */
+#define STM32_IMAGE_ID U(29)
+
/* Define size of the array */
-#define MAX_NUMBER_IDS U(28)
+#define MAX_NUMBER_IDS U(30)
#endif /* __TBBR_IMG_DEF_H__ */
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index 095099c..a0c7542 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -32,6 +32,7 @@
#define BUILD_CONFIG_NR_SHIFT 0
#define BUILD_CONFIG_NR_MASK 0x1f
+#define FILTER_OFFSET 0x10
/*
* Number of gate keepers is implementation defined. But we know the max for
* this device is 4. Get implementation details from BUILD_CONFIG.
@@ -112,6 +113,9 @@ void tzc400_configure_region(unsigned int filters,
void tzc400_set_action(tzc_action_t action);
void tzc400_enable_filters(void);
void tzc400_disable_filters(void);
+void tzc400_clear_all_interrupts(void);
+int tzc400_is_pending_interrupt(void);
+void tzc400_it_handler(void);
static inline void tzc_init(uintptr_t base)
{
diff --git a/include/drivers/io/io_driver.h b/include/drivers/io/io_driver.h
index 8306407..3d2c3ab 100644
--- a/include/drivers/io/io_driver.h
+++ b/include/drivers/io/io_driver.h
@@ -39,7 +39,7 @@ typedef struct io_dev_funcs {
io_type_t (*type)(void);
int (*open)(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity);
- int (*seek)(io_entity_t *entity, int mode, ssize_t offset);
+ int (*seek)(io_entity_t *entity, int mode, signed long long offset);
int (*size)(io_entity_t *entity, size_t *length);
int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read);
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index 485ed8c..2bf7721 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -22,6 +22,12 @@ typedef enum {
IO_TYPE_DUMMY,
IO_TYPE_FIRMWARE_IMAGE_PACKAGE,
IO_TYPE_BLOCK,
+ IO_TYPE_MMC,
+ IO_TYPE_STM32IMAGE,
+ IO_TYPE_UART,
+ IO_TYPE_QSPI,
+ IO_TYPE_NAND,
+ IO_TYPE_USB,
IO_TYPE_MAX
} io_type_t;
@@ -86,7 +92,7 @@ int io_dev_close(uintptr_t dev_handle);
/* Synchronous operations */
int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle);
-int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset);
+int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset);
int io_size(uintptr_t handle, size_t *length);
diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h
new file mode 100644
index 0000000..b21bde8
--- /dev/null
+++ b/include/drivers/st/bsec.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __BSEC_H__
+#define __BSEC_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <utils_def.h>
+
+/*
+ * IP configuration
+ */
+#define BSEC_OTP_MASK GENMASK(4, 0)
+#define BSEC_OTP_BANK_SHIFT 5
+#define BSEC_TIMEOUT_VALUE 0xFFFF
+
+#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03
+#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */
+#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0)
+#define ADDR_UPPER_OTP_PERLOCK_SHIFT 0x04
+#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */
+#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0)
+
+/*
+ * Return status
+ */
+#define BSEC_OK 0U
+#define BSEC_ERROR 0xFFFFFFFFU
+#define BSEC_DISTURBED 0xFFFFFFFEU
+#define BSEC_INVALID_PARAM 0xFFFFFFFCU
+#define BSEC_PROG_FAIL 0xFFFFFFFBU
+#define BSEC_LOCK_FAIL 0xFFFFFFFAU
+#define BSEC_WRITE_FAIL 0xFFFFFFF9U
+#define BSEC_SHADOW_FAIL 0xFFFFFFF8U
+#define BSEC_TIMEOUT 0xFFFFFFF7U
+
+/*
+ * BSEC REGISTER OFFSET (base relative)
+ */
+#define BSEC_OTP_CONF_OFF 0x000U
+#define BSEC_OTP_CTRL_OFF 0x004U
+#define BSEC_OTP_WRDATA_OFF 0x008U
+#define BSEC_OTP_STATUS_OFF 0x00CU
+#define BSEC_OTP_LOCK_OFF 0x010U
+#define BSEC_DEN_OFF 0x014U
+#define BSEC_DISTURBED_OFF 0x01CU
+#define BSEC_DISTURBED1_OFF 0x020U
+#define BSEC_DISTURBED2_OFF 0x024U
+#define BSEC_ERROR_OFF 0x034U
+#define BSEC_ERROR1_OFF 0x038U
+#define BSEC_ERROR2_OFF 0x03CU
+#define BSEC_WRLOCK_OFF 0x04CU /* Safmem permanent lock */
+#define BSEC_WRLOCK1_OFF 0x050U
+#define BSEC_WRLOCK2_OFF 0x054U
+#define BSEC_SPLOCK_OFF 0x064U /* Program safmem sticky lock */
+#define BSEC_SPLOCK1_OFF 0x068U
+#define BSEC_SPLOCK2_OFF 0x06CU
+#define BSEC_SWLOCK_OFF 0x07CU /* Write in OTP sticky lock */
+#define BSEC_SWLOCK1_OFF 0x080U
+#define BSEC_SWLOCK2_OFF 0x084U
+#define BSEC_SRLOCK_OFF 0x094U /* Shadowing sticky lock */
+#define BSEC_SRLOCK1_OFF 0x098U
+#define BSEC_SRLOCK2_OFF 0x09CU
+#define BSEC_JTAG_IN_OFF 0x0ACU
+#define BSEC_JTAG_OUT_OFF 0x0B0U
+#define BSEC_SCRATCH_OFF 0x0B4U
+#define BSEC_OTP_DATA_OFF 0x200U
+#define BSEC_IPHW_CFG_OFF 0xFF0U
+#define BSEC_IPVR_OFF 0xFF4U
+#define BSEC_IP_ID_OFF 0xFF8U
+#define BSEC_IP_MAGIC_ID_OFF 0xFFCU
+
+/*
+ * BSEC_CONFIGURATION Register
+ */
+#define BSEC_CONF_POWER_UP_MASK BIT(0)
+#define BSEC_CONF_POWER_UP_SHIFT 0
+#define BSEC_CONF_FRQ_MASK GENMASK(2, 1)
+#define BSEC_CONF_FRQ_SHIFT 1
+#define BSEC_CONF_PRG_WIDTH_MASK GENMASK(6, 3)
+#define BSEC_CONF_PRG_WIDTH_SHIFT 3
+#define BSEC_CONF_TREAD_MASK GENMASK(8, 7)
+#define BSEC_CONF_TREAD_SHIFT 7
+
+/*
+ * BSEC_CONTROL Register
+ */
+#define BSEC_READ 0x000U
+#define BSEC_WRITE 0x100U
+#define BSEC_LOCK 0x200U
+
+/*
+ * BSEC_OTP_LOCK register
+ */
+#define UPPER_OTP_LOCK_MASK BIT(0)
+#define UPPER_OTP_LOCK_SHIFT 0
+#define DENREG_LOCK_MASK BIT(2)
+#define DENREG_LOCK_SHIFT 2
+#define GPLOCK_LOCK_MASK BIT(4)
+#define GPLOCK_LOCK_SHIFT 4
+
+/*
+ * BSEC_OTP_STATUS Register
+ */
+#define BSEC_MODE_STATUS_MASK GENMASK(2, 0)
+#define BSEC_MODE_BUSY_MASK BIT(3)
+#define BSEC_MODE_PROGFAIL_MASK BIT(4)
+#define BSEC_MODE_PWR_MASK BIT(5)
+#define BSEC_MODE_BIST1_LOCK_MASK BIT(6)
+#define BSEC_MODE_BIST2_LOCK_MASK BIT(7)
+
+/* OTP MODE*/
+#define BSEC_MODE_OPEN1 0x00
+#define BSEC_MODE_SECURED 0x01
+#define BSEC_MODE_OPEN2 0x02
+#define BSEC_MODE_INVALID 0x04
+
+/* BSEC_DENABLE Register */
+#define BSEC_HDPEN BIT(4)
+#define BSEC_SPIDEN BIT(5)
+#define BSEC_SPINDEN BIT(6)
+#define BSEC_DBGSWGEN BIT(10)
+#define BSEC_DEN_ALL_MSK GENMASK(10, 0)
+
+/* BSEC_FENABLE Register */
+#define BSEC_FEN_ALL_MSK GENMASK(14, 0)
+
+/*
+ * OTP Lock services definition
+ * Value must corresponding to the bit number in the register
+ */
+#define BSEC_LOCK_UPPER_OTP 0x00
+#define BSEC_LOCK_DEBUG 0x02
+#define BSEC_LOCK_PROGRAM 0x03
+
+/* Values for struct bsec_config::freq */
+#define FREQ_10_20_MHZ 0x0
+#define FREQ_20_30_MHZ 0x1
+#define FREQ_30_45_MHZ 0x2
+#define FREQ_45_67_MHZ 0x3
+
+/*
+ * Device info structure, providing device-specific functions and a means of
+ * adding driver-specific state
+ */
+struct bsec_config {
+ uint8_t tread; /* SAFMEM Reading current level default 0 */
+ uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */
+ uint8_t freq; /* SAFMEM CLOCK see freq value define
+ * default FREQ_45_67_MHZ
+ */
+ uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */
+ uint8_t prog_lock; /* Programming Sticky lock
+ * 1 programming is locked until next reset
+ */
+ uint8_t den_lock; /* Debug enable is sticky lock
+ * 1 debug enable is locked until next reset
+ */
+ uint8_t upper_otp_lock; /* Shadowing of upper OTP is sticky lock
+ * 1 shadowing of upper OTP is locked
+ * until next reset
+ */
+};
+
+uint32_t bsec_probe(void);
+uint32_t bsec_get_base(void);
+
+uint32_t bsec_set_config(struct bsec_config *cfg);
+uint32_t bsec_get_config(struct bsec_config *cfg);
+
+uint32_t bsec_shadow_register(uint32_t otp);
+uint32_t bsec_read_otp(uint32_t *val, uint32_t otp);
+uint32_t bsec_write_otp(uint32_t val, uint32_t otp);
+uint32_t bsec_program_otp(uint32_t val, uint32_t otp);
+uint32_t bsec_permanent_lock_otp(uint32_t otp);
+
+uint32_t bsec_write_debug_conf(uint32_t val);
+uint32_t bsec_read_debug_conf(void);
+uint32_t bsec_write_feature_conf(uint32_t val);
+uint32_t bsec_read_feature_conf(uint32_t *val);
+
+uint32_t bsec_get_status(void);
+uint32_t bsec_get_hw_conf(void);
+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);
+
+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);
+
+#endif /*__BSEC_H__*/
diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h
new file mode 100644
index 0000000..c31d996
--- /dev/null
+++ b/include/drivers/st/etzpc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __ETZPC_H__
+#define __ETZPC_H__
+
+/* Define security level for each peripheral (DECPROT) */
+enum etzpc_decprot_attributes {
+ TZPC_DECPROT_S_RW = 0,
+ TZPC_DECPROT_NS_R_S_W = 1,
+ TZPC_DECPROT_MCU_ISOLATION = 2,
+ TZPC_DECPROT_NS_RW = 3,
+ TZPC_DECPROT_MAX = 4,
+};
+
+void etzpc_configure_decprot(uint32_t decprot_id,
+ enum etzpc_decprot_attributes decprot_attr);
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id);
+void etzpc_lock_decprot(uint32_t decprot_id);
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value);
+uint16_t etzpc_get_tzma(uint32_t tzma_id);
+void etzpc_lock_tzma(uint32_t tzma_id);
+bool etzpc_get_lock_tzma(uint32_t tzma_id);
+uint8_t etzpc_get_num_per_sec(void);
+uint8_t etzpc_get_revision(void);
+uintptr_t etzpc_get_base_address(void);
+int etzpc_init(void);
+
+#endif /* __ETZPC_H__ */
diff --git a/include/drivers/st/hash_sec.h b/include/drivers/st/hash_sec.h
new file mode 100644
index 0000000..a8d8b9b
--- /dev/null
+++ b/include/drivers/st/hash_sec.h
@@ -0,0 +1,113 @@
+/**
+ ******************************************************************************
+ * @file hash_sec.h
+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project
+ * @version V0.1
+ * @date 22-Sept-2015
+ * @brief Header file for STM32MP1 HASH driver module.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __HASH_SEC_H
+#define __HASH_SEC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stm32mp1xx_hal.h>
+#include <stm32_hal_hash_reg.h>
+
+/* Definitions----------------------------------------------------------------*/
+#define HASH ((HASH_TypeDef *)HASH_BASE)
+#define HASH_DIGEST ((HASH_DIGEST_TypeDef *)(HASH_BASE + 0x310))
+
+#define HASH_TIMEOUT_VALUE 0x500000
+
+/*
+ * HASH IP uses 512 bits : ie 64 bytes block in order to start computation of
+ * Hash intermediate Digest
+ * The digest intermediate computation starts only after 64 bytes are entered
+ */
+#define HASH_BLOCK_SIZE_NB_BYTES 64
+
+/**
+ * @brief Set the number of valid bits in last word 32 bits written in Data
+ * register
+ * @param SIZE: size in byte of last data written in Data register.
+ * @retval None
+ */
+
+#define __HAL_HASH_SET_NBVALIDBITSINLAST32BITSWORD(SIZE) \
+ do { \
+ HASH->STR &= ~(HASH_STR_NBW); \
+ HASH->STR |= 8 * ((SIZE) % 4); \
+ } while (0)
+
+/**
+ * @brief HASH Handle Structure definition
+ */
+typedef struct {
+ HASH_TypeDef *Instance; /*!< HASH Registers base address */
+ uint32_t State;
+ uint32_t Error;
+ const uint8_t *pHashInBuffPtr; /*!< Pointer to input buffer */
+ const uint8_t *pHashOutBuffPtr; /*!< Pointer to output buffer */
+} HASH_HandleTypeDef;
+
+#define HASH_DIGEST_DONE 0x0
+#define HASH_TIMEOUT 0x1
+#define HASH_INIT_DONE 0x2
+#define HASH_ACCU_DONE 0x3
+#define HASH_FINISHED 0x4
+#define HASH_INIT_NOT_DONE 0x5
+
+/** @defgroup HASH_Algo_Selection
+ * @{
+ */
+#define HASH_AlgoSelection_SHA256 HASH_CR_ALGO /*!< HASH function is SHA256 */
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Data_Type
+ * @{
+ */
+#define HASH_DATATYPE_8B HASH_CR_DATATYPE_1 /*!< 8-bit data. All bytes are
+ * swapped
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/* HASH processing using polling *********************************************/
+Std_ReturnType HASH_SHA256_Init(HASH_HandleTypeDef *hHash);
+
+Std_ReturnType HASH_SHA256_Start(HASH_HandleTypeDef *hHash,
+ const uint8_t *pInBuffer,
+ uint32_t sizeInBytes,
+ uint8_t *pOutBuffer, uint32_t Timeout);
+
+Std_ReturnType HASH_SHA256_Accumulate(HASH_HandleTypeDef *hHash,
+ const uint8_t *pInBuffer,
+ uint32_t sizeInBytes);
+
+Std_ReturnType HASH_SHA256_Finish(HASH_HandleTypeDef *hHash,
+ uint8_t *pOutBuffer, uint32_t Timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HASH_SEC_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/include/drivers/st/io_mmc.h b/include/drivers/st/io_mmc.h
new file mode 100644
index 0000000..de71e7d
--- /dev/null
+++ b/include/drivers/st/io_mmc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_MMC_H
+#define IO_MMC_H
+
+#include <io_driver.h>
+
+int register_io_dev_mmc(const io_dev_connector_t **dev_con);
+
+#endif /* IO_MMC_H */
diff --git a/include/drivers/st/io_nand.h b/include/drivers/st/io_nand.h
new file mode 100644
index 0000000..13c8fbf
--- /dev/null
+++ b/include/drivers/st/io_nand.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IO_NAND_H__
+#define __IO_NAND_H__
+
+#define STM32_NAND_MAX_BLOCK_SIZE 512
+
+typedef struct nand_device_info {
+ uint64_t device_size; /* Size of device in bytes */
+ uint32_t block_size; /* block size in bytes */
+} nand_device_info_t;
+
+int register_io_dev_nand(const io_dev_connector_t **dev_con);
+
+#endif /* __IO_NAND_H__ */
diff --git a/include/drivers/st/io_programmer.h b/include/drivers/st/io_programmer.h
new file mode 100644
index 0000000..454aa68
--- /dev/null
+++ b/include/drivers/st/io_programmer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IO_PROGRAMMER_H__
+#define __IO_PROGRAMMER_H__
+
+/* Phase definition */
+#define PHASE_FLASHLAYOUT 0
+#define PHASE_FSBL1 1
+#define PHASE_FSBL2 2
+#define PHASE_SSBL 3
+
+/* Command definition */
+#define GET_CMD_COMMAND 0x00
+#define GET_VER_COMMAND 0x01
+#define GET_ID_COMMAND 0x02
+#define PHASE_COMMAND 0x03
+#define START_COMMAND 0x21
+#define DOWNLOAD_COMMAND 0x31
+
+/* Answer defines */
+#define INIT_BYTE 0x7F
+#define ACK_BYTE 0x79
+#define NACK_BYTE 0x1F
+#define ABORT 0x5F
+
+#define PROGRAMMER_TIMEOUT 0xFFFFFFFE
+
+#define DEVICE_ID_BYTE1 0x05
+#define DEVICE_ID_BYTE2 0x00
+
+/* phase structure */
+struct phase_struct {
+ uint32_t keep_header;
+ uint32_t current_packet;
+ size_t max_size;
+ uint8_t phase_id;
+};
+
+/* current phase struct variable */
+static struct phase_struct current_phase = {
+ .phase_id = PHASE_FSBL1,
+ .max_size = 0,
+ .keep_header = 0,
+ .current_packet = 0,
+};
+
+#endif /* __IO_PROGRAMMER_H__ */
diff --git a/include/drivers/st/io_programmer_st_usb.h b/include/drivers/st/io_programmer_st_usb.h
new file mode 100644
index 0000000..f6ad9c7
--- /dev/null
+++ b/include/drivers/st/io_programmer_st_usb.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IO_USB_H__
+#define __IO_USB_H__
+
+#define IO_USB_TIMEOUT 0xFFFFF
+/* need to call the USB Handler 4 times after to have
+ * received the detach request
+ */
+#define DETACH_TIMEOUT 0x100
+
+#define USB_DFU_MAX_XFER_SIZE 1024
+
+int register_io_dev_usb(const io_dev_connector_t **dev_con);
+
+#endif /* __IO_USB_H__ */
diff --git a/include/drivers/st/io_qspi.h b/include/drivers/st/io_qspi.h
new file mode 100644
index 0000000..fc03faf
--- /dev/null
+++ b/include/drivers/st/io_qspi.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IO_QSPI_H__
+#define __IO_QSPI_H__
+
+#define QSPI_FMODE_MASK 0x0C000000
+#define QSPI_FMODE_MEMORY_MAPPED 0x0C000000
+
+#define QSPI_NOR_MAX_SIZE 0x10000000 /* 256 MB*/
+#define QSPI_NOR_LBA_SIZE 0x00000200 /* 512 B*/
+#define QSPI_NOR_BLK_SIZE 0x00040000 /* 256 KB*/
+
+#define QSPI_CR_EN 0x00000001
+#define QSPI_CR_ABORT 0x00000002
+#define QSPI_CR_TCEN 0x00000008
+#define QSPI_CR_SSHIFT 0x00000010
+#define QSPI_CR_DFM 0x00000040
+#define QSPI_CR_PRESCALER_SHIFT 24
+
+#define QSPI_DCR_CSHT 0x00000100
+#define QSPI_DCR_FSIZE_MASK 0x001F0000
+#define QSPI_DCR_FSIZE_SHIFT 16
+
+#define QSPI_CCR_INST 0x0000000B
+#define QSPI_CCR_IMODE 0x00000100
+#define QSPI_CCR_ADMODE 0x00000400
+#define QSPI_CCR_ADSIZE 0x00002000
+#define QSPI_CCR_ABMODE 0x00000000
+#define QSPI_CCR_ABSIZE 0x00000000
+#define QSPI_CCR_DCYC 0x00200000
+#define QSPI_CCR_DMODE 0x01000000
+#define QSPI_CCR_FMODE_MM 0x0C000000
+#define QSPI_CCR_FMODE 0x04000000
+#define QSPI_CCR_SIOO 0x00000000
+#define QSPI_CCR_DDRM 0x00000000
+#define QSPI_CCR_DHHC 0x00000000
+
+#define QSPI_SR_FLEVEL 0x1F00
+#define QSPI_SR_BUSY 0x0020
+#define QSPI_SR_TOF 0x0010
+#define QSPI_SR_SMF 0x0008
+#define QSPI_SR_FTF 0x0004
+#define QSPI_SR_TCF 0x0002
+#define QSPI_SR_TEF 0x0001
+
+#define QSPI_FCR_CTOF 0x0008
+#define QSPI_FCR_CSMF 0x0004
+#define QSPI_FCR_CTCF 0x0002
+#define QSPI_FCR_CTEF 0x0001
+
+#define QSPI_DFLT_READ_FLAGS (QSPI_CCR_INST | QSPI_CCR_IMODE | \
+ QSPI_CCR_ADMODE | QSPI_CCR_ADSIZE | \
+ QSPI_CCR_ABMODE | QSPI_CCR_ABSIZE | \
+ QSPI_CCR_DCYC | QSPI_CCR_DMODE | \
+ QSPI_CCR_SIOO | QSPI_CCR_DDRM | \
+ QSPI_CCR_DHHC)
+
+/*
+ * QUAD Serial Peripheral Interface
+ */
+
+typedef struct {
+ volatile uint32_t CR; /* Control register */
+ volatile uint32_t DCR; /* Device Configuration register */
+ volatile uint32_t SR; /* Status register */
+ volatile uint32_t FCR; /* Flag Clear register */
+ volatile uint32_t DLR; /* Data Length register */
+ volatile uint32_t CCR; /* Communication Configuration register */
+ volatile uint32_t AR; /* Address register */
+ volatile uint32_t ABR; /* Alternate Bytes register */
+ volatile uint32_t DR; /* Data register */
+ volatile uint32_t PSMKR; /* Polling Status Mask register */
+ volatile uint32_t PSMAR; /* Polling Status Match register */
+ volatile uint32_t PIR; /* Polling Interval register */
+ volatile uint32_t LPTR; /* Low Power Timeout register */
+} QUADSPI_TypeDef;
+
+/*
+ * QSPI Handle Structure definition
+ */
+typedef struct {
+ QUADSPI_TypeDef *instance; /* QSPI registers base address */
+ uint32_t is_dual;
+} QSPI_HandleTypeDef;
+
+int register_io_dev_qspi(const io_dev_connector_t **dev_con);
+
+#endif /* __IO_QSPI_H__ */
diff --git a/include/drivers/st/io_stm32image.h b/include/drivers/st/io_stm32image.h
new file mode 100644
index 0000000..b668219
--- /dev/null
+++ b/include/drivers/st/io_stm32image.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_STM32IMAGE_H
+#define IO_STM32IMAGE_H
+
+#include <io_driver.h>
+#include <partition.h>
+
+#define MAX_LBA_SIZE 512
+#define MAX_PART_NAME_SIZE (EFI_NAMELEN + 1)
+#define STM32_PART_NUM (PLAT_PARTITION_MAX_ENTRIES - STM32_TF_A_COPIES)
+
+struct stm32image_part_info {
+ char name[MAX_PART_NAME_SIZE];
+ uint32_t binary_type;
+ uintptr_t part_offset;
+ uint32_t bkp_offset;
+};
+
+struct stm32image_device_info {
+ struct stm32image_part_info part_info[STM32_PART_NUM];
+ uint32_t device_size;
+ uint32_t lba_size;
+};
+
+int register_io_dev_stm32image(const io_dev_connector_t **dev_con);
+
+#endif /* IO_STM32IMAGE_H */
diff --git a/include/drivers/st/io_uart.h b/include/drivers/st/io_uart.h
new file mode 100644
index 0000000..2f9ecb3
--- /dev/null
+++ b/include/drivers/st/io_uart.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IO_UART_H__
+#define __IO_UART_H__
+
+int register_io_dev_uart(const io_dev_connector_t **dev_con);
+
+#endif /* __IO_UART_H__ */
diff --git a/include/drivers/st/nand.h b/include/drivers/st/nand.h
new file mode 100644
index 0000000..f92511d
--- /dev/null
+++ b/include/drivers/st/nand.h
@@ -0,0 +1,252 @@
+/*
+ ******************************************************************************
+ * @file nand.h
+ * @author mgentilini - MCD IntroPack team - MPU AP v1 bootROM project
+ * @version V0.1
+ * @date 28-April-2016
+ * @brief Header file for STM32MP1 Nand driver module.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#ifndef __NAND_H
+#define __NAND_H
+
+#include <stm32mp1xx_hal.h>
+
+/* FMC NAND Flash 'common memory' data area */
+#define FLASH_COMMON_MEM_BASE 0x80000000
+/* FMC NAND Flash 'attribute memory' data area */
+#define FLASH_ATTRIB_MEM_BASE 0x88000000
+
+#define BCH_PAGE_SECTOR 512
+
+/* BBM */
+#define GOOD_BLOCK 0
+#define BAD_BLOCK 1
+
+/**************** Bit definition for FMC_PCR register *******************/
+/* Wait feature enable bit */
+#define FMC_PCR_PWAITEN ((uint32_t)0x00000002)
+/* PC Card/NAND Flash memory bank enable bit */
+#define FMC_PCR_PBKEN ((uint32_t)0x00000004)
+
+/* PWID[1:0] bits (NAND Flash databus width) */
+#define FMC_PCR_PWID ((uint32_t)0x00000030)
+#define FMC_PCR_PWID_0 ((uint32_t)0x00000010) /* Bit 0 */
+#define FMC_PCR_PWID_1 ((uint32_t)0x00000020) /* Bit 1 */
+
+/* ECC computation logic enable bit */
+#define FMC_PCR_ECCEN ((uint32_t)0x00000040)
+
+/* ECC algorithm */
+#define FMC_PCR_ECCALG ((uint32_t)0x00000100)
+
+/* TCLR[3:0] bits (CLE to RE delay) */
+#define FMC_PCR_TCLR_0 ((uint32_t)0x00000200) /* Bit 0 */
+#define FMC_PCR_TCLR_1 ((uint32_t)0x00000400) /* Bit 1 */
+#define FMC_PCR_TCLR_2 ((uint32_t)0x00000800) /* Bit 2 */
+#define FMC_PCR_TCLR_3 ((uint32_t)0x00001000) /* Bit 3 */
+
+/* TAR[3:0] bits (ALE to RE delay) */
+#define FMC_PCR_TAR_0 ((uint32_t)0x00002000) /* Bit 0 */
+#define FMC_PCR_TAR_1 ((uint32_t)0x00004000) /* Bit 1 */
+#define FMC_PCR_TAR_2 ((uint32_t)0x00008000) /* Bit 2 */
+#define FMC_PCR_TAR_3 ((uint32_t)0x00010000) /* Bit 3 */
+
+/* ECCSS[1:0] bits (ECC sector size) */
+#define FMC_PCR_ECCSS ((uint32_t)0x000E0000)
+#define FMC_PCR_ECCSS_0 ((uint32_t)0x00020000) /* Bit 0 */
+#define FMC_PCR_ECCSS_1 ((uint32_t)0x00040000) /* Bit 1 */
+#define FMC_PCR_ECCSS_2 ((uint32_t)0x00080000) /* Bit 2 */
+
+/* BCH Error correction capability */
+#define FMC_PCR_BCHECC ((uint32_t)0x01000000)
+
+/* Write enable */
+#define FMC_PCR_WE ((uint32_t)0x02000000)
+
+/**************** Bit definition for FMC_BCR1 register *******************/
+/* FMC controller enable */
+#define FMC_BCR1_FMCEN ((uint32_t)0x80000000)
+
+/**************** Bit definition for FMC_BCHISR register *******************/
+/* Decoder Error Ready Flag */
+#define FMC_BCHISR_DERF ((uint32_t)0x00000002)
+/* Decoder Uncorrectable Error Flag */
+#define FMC_BCHISR_DUEF ((uint32_t)0x00000001)
+/* Decoder Error Found Flag */
+#define FMC_BCHISR_DEFF ((uint32_t)0x00000004)
+
+/**************** Bit definition for FMC_BCHSR register *******************/
+/* Decoder Error Number */
+#define FMC_BCHSR_DEN ((uint32_t)0x0000000F)
+
+/**************** Bit definition for FMC_BCHDSR0 register *******************/
+/* Decoder Uncorrectable Error */
+#define FMC_BCHDSR0_DUE ((uint32_t)0x00000001)
+/* Decoder Error Number */
+#define FMC_BCHDSR0_DEN ((uint32_t)0x000000F0)
+
+/**************** Bit definition for FMC_BCHDSR1 register *******************/
+#define FMC_BCHDSR1_EBP1 ((uint32_t)0x00001FFF)
+#define FMC_BCHDSR1_EBP2 ((uint32_t)0x1FFF0000)
+
+/**************** Bit definition for FMC_BCHDSR2 register *******************/
+#define FMC_BCHDSR2_EBP1 ((uint32_t)0x00001FFF)
+#define FMC_BCHDSR2_EBP2 ((uint32_t)0x1FFF0000)
+
+/**************** Bit definition for FMC_BCHDSR3 register *******************/
+#define FMC_BCHDSR3_EBP1 ((uint32_t)0x00001FFF)
+#define FMC_BCHDSR3_EBP2 ((uint32_t)0x1FFF0000)
+
+/**************** Bit definition for FMC_BCHDSR4 register *******************/
+#define FMC_BCHDSR4_EBP1 ((uint32_t)0x00001FFF)
+#define FMC_BCHDSR4_EBP2 ((uint32_t)0x1FFF0000)
+
+/**************** Bit definition for FMC_SR register **********************/
+#define FMC_SR_NWRF ((uint32_t)0x00000040)
+#define FMC_SR_PF ((uint32_t)0x00000010)
+
+#define FMC_NSEC_PER_SEC 1000000000L
+
+/* Timings */
+#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
+
+/* Register: FMC_PCR */
+#define FMC_PCR_TCLR(x) (((x) & 0xf) << 9)
+#define FMC_PCR_TAR(x) (((x) & 0xf) << 13)
+
+/* Register: FMC_PMEM */
+#define FMC_PMEM_MEMSET(x) (((x) & 0xff) << 0)
+#define FMC_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
+#define FMC_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
+#define FMC_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
+
+/* Register: FMC_PATT */
+#define FMC_PATT_ATTSET(x) (((x) & 0xff) << 0)
+#define FMC_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
+#define FMC_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
+#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_EBP2_MASK 16
+
+/* 1st addressing cycle */
+#define ADDR_1ST_CYCLE(__ADDRESS__) (uint8_t)(__ADDRESS__)
+/* 2nd addressing cycle */
+#define ADDR_2ND_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 8)
+/* 3rd addressing cycle */
+#define ADDR_3RD_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 16)
+/* 4th addressing cycle */
+#define ADDR_4TH_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 24)
+
+typedef struct {
+ uint8_t tclr;
+ uint8_t tar;
+ uint8_t thiz;
+ uint8_t twait;
+ uint8_t thold_mem;
+ uint8_t tset_mem;
+ uint8_t thold_att;
+ uint8_t tset_att;
+} nand_timings;
+
+typedef struct {
+ uint32_t Signature; /* NAND Parameter page signature */
+
+ uint32_t PageSize; /* NAND memory page (without spare area) size
+ * measured in B
+ */
+
+ uint32_t BlockSize; /* NAND memory block size in number
+ * of pages
+ */
+
+ uint32_t BlockNb; /* NAND memory number of blocks */
+
+ uint32_t ZoneSize; /* NAND memory zone size measured in number
+ * of blocks
+ */
+
+ uint32_t BusWidth; /* NAND memory bus width in bytes */
+
+ uint32_t ECCcorrectability; /* NAND number of bits ECC correctability */
+
+ uint32_t page_size_shift;
+ uint32_t block_size_shift;
+
+ nand_timings timings;
+
+} NAND_InfoTypeDef;
+
+/* NAND Memory address Structure definition */
+typedef struct {
+ uint16_t Page; /* NAND memory Page address */
+
+ uint16_t Zone; /* NAND memory Zone address */
+
+ uint16_t Block; /* NAND memory Block address */
+} NAND_AddressTypeDef;
+
+/* NAND Memory electronic signature Structure definition */
+typedef struct {
+ uint8_t Maker_Id;
+
+ uint8_t Device_Id;
+} NAND_IDTypeDef;
+
+/* NAND handle Structure definition */
+typedef struct {
+ FMC_TypeDef *Instance; /* Register base address */
+
+ NAND_InfoTypeDef Info; /* NAND characteristic information structure */
+} NAND_HandleTypeDef;
+
+/* Exported functions */
+Std_ReturnType nand_initialize(NAND_HandleTypeDef *hnand);
+Std_ReturnType NAND_Read_Logical_Page(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address,
+ uint8_t *Buffer, uint32_t bch_sector_nb);
+uint32_t NAND_Check_Bad_Block(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address);
+Std_ReturnType NAND_Address_Inc(NAND_HandleTypeDef *hNand,
+ NAND_AddressTypeDef *Address,
+ uint32_t numPagesRead);
+
+#endif /* __NAND_H */
+
diff --git a/include/drivers/st/stm32_console.h b/include/drivers/st/stm32_console.h
new file mode 100644
index 0000000..57e6d74
--- /dev/null
+++ b/include/drivers/st/stm32_console.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_CONSOLE_H
+#define STM32_CONSOLE_H
+
+#include <console.h>
+
+#define CONSOLE_T_STM32_BASE CONSOLE_T_DRVDATA
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+struct console_stm32 {
+ console_t console;
+ uintptr_t base;
+};
+
+/*
+ * Initialize a new STM32 console instance and register it with the console
+ * framework. The |console| pointer must point to storage that will be valid
+ * for the lifetime of the console, such as a global or static local variable.
+ * Its contents will be reinitialized from scratch.
+ */
+int console_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ struct console_stm32 *console);
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* STM32_CONSOLE_H */
diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h
index 7a5ccd3..33cef04 100644
--- a/include/drivers/st/stm32_gpio.h
+++ b/include/drivers/st/stm32_gpio.h
@@ -4,15 +4,11 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __PLAT_GPIO_H__
-#define __PLAT_GPIO_H__
+#ifndef STM32_GPIO_H
+#define STM32_GPIO_H
#include <utils_def.h>
-#define STM32_GPIOA_BANK U(0x50002000)
-#define STM32_GPIOZ_BANK U(0x54004000)
-#define STM32_GPIO_BANK_OFFSET U(0x1000)
-
#define GPIO_MODE_OFFSET U(0x00)
#define GPIO_TYPE_OFFSET U(0x04)
#define GPIO_SPEED_OFFSET U(0x08)
@@ -20,56 +16,14 @@
#define GPIO_BSRR_OFFSET U(0x18)
#define GPIO_AFRL_OFFSET U(0x20)
#define GPIO_AFRH_OFFSET U(0x24)
+#define GPIO_SECR_OFFSET U(0x30)
#define GPIO_ALT_LOWER_LIMIT U(0x08)
-#define GPIO_BANK_A U(0x00)
-#define GPIO_BANK_B U(0x01)
-#define GPIO_BANK_C U(0x02)
-#define GPIO_BANK_D U(0x03)
-#define GPIO_BANK_E U(0x04)
-#define GPIO_BANK_F U(0x05)
-#define GPIO_BANK_G U(0x06)
-#define GPIO_BANK_H U(0x07)
-#define GPIO_BANK_I U(0x08)
-#define GPIO_BANK_J U(0x09)
-#define GPIO_BANK_K U(0x0A)
-#define GPIO_BANK_Z U(0x19)
-
-#define GPIO_PIN_0 U(0x00)
-#define GPIO_PIN_1 U(0x01)
-#define GPIO_PIN_2 U(0x02)
-#define GPIO_PIN_3 U(0x03)
-#define GPIO_PIN_4 U(0x04)
-#define GPIO_PIN_5 U(0x05)
-#define GPIO_PIN_6 U(0x06)
-#define GPIO_PIN_7 U(0x07)
-#define GPIO_PIN_8 U(0x08)
-#define GPIO_PIN_9 U(0x09)
-#define GPIO_PIN_10 U(0x0A)
-#define GPIO_PIN_11 U(0x0B)
-#define GPIO_PIN_12 U(0x0C)
-#define GPIO_PIN_13 U(0x0D)
-#define GPIO_PIN_14 U(0x0E)
-#define GPIO_PIN_15 U(0x0F)
-#define GPIO_PIN_MAX GPIO_PIN_15
+#define GPIO_PIN_(_x) U(_x)
+#define GPIO_PIN_MAX GPIO_PIN_(15)
-#define GPIO_ALTERNATE_0 0x00
-#define GPIO_ALTERNATE_1 0x01
-#define GPIO_ALTERNATE_2 0x02
-#define GPIO_ALTERNATE_3 0x03
-#define GPIO_ALTERNATE_4 0x04
-#define GPIO_ALTERNATE_5 0x05
-#define GPIO_ALTERNATE_6 0x06
-#define GPIO_ALTERNATE_7 0x07
-#define GPIO_ALTERNATE_8 0x08
-#define GPIO_ALTERNATE_9 0x09
-#define GPIO_ALTERNATE_10 0x0A
-#define GPIO_ALTERNATE_11 0x0B
-#define GPIO_ALTERNATE_12 0x0C
-#define GPIO_ALTERNATE_13 0x0D
-#define GPIO_ALTERNATE_14 0x0E
-#define GPIO_ALTERNATE_15 0x0F
+#define GPIO_ALTERNATE_(_x) U(_x)
#define GPIO_ALTERNATE_MASK U(0x0F)
#define GPIO_MODE_INPUT 0x00
@@ -82,8 +36,8 @@
#define GPIO_SPEED_LOW 0x00
#define GPIO_SPEED_MEDIUM 0x01
-#define GPIO_SPEED_FAST 0x02
-#define GPIO_SPEED_HIGH 0x03
+#define GPIO_SPEED_HIGH 0x02
+#define GPIO_SPEED_VERY_HIGH 0x03
#define GPIO_SPEED_MASK U(0x03)
#define GPIO_NO_PULL 0x00
@@ -94,8 +48,10 @@
#ifndef __ASSEMBLY__
#include <stdint.h>
+int dt_set_pinctrl_config(int node);
void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
- uint32_t pull, uint32_t alternate);
+ uint32_t pull, uint32_t alternate, uint8_t status);
+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure);
#endif /*__ASSEMBLY__*/
-#endif /*__PLAT_GPIO_H__*/
+#endif /* STM32_GPIO_H */
diff --git a/include/drivers/st/stm32_hal_hash_reg.h b/include/drivers/st/stm32_hal_hash_reg.h
new file mode 100644
index 0000000..e7a589b
--- /dev/null
+++ b/include/drivers/st/stm32_hal_hash_reg.h
@@ -0,0 +1,136 @@
+/**
+ ******************************************************************************
+ * @file stm32_hal_hash_reg.h
+ * @author MCD Intropack Team - MPU AP v1 bootROM project
+ * @date 22 September 2015
+ * @brief STM32 Device Peripheral Access Layer Header File.
+ *
+ * This file contains:
+ * - Data structures and the address mapping for all peripherals
+ * - Peripheral's registers declarations and bits definition
+ * - Macros to access peripherals registers hardware
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#ifndef _STM32_HAL_HASH_REG_H_
+#define _STM32_HAL_HASH_REG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+
+/** @addtogroup Peripheral_registers_structures
+ * @{
+ */
+
+/**
+ * @brief Secure digital input/output Interface
+ */
+#ifndef __ASM_INCLUDE__
+/**
+ * @brief HASH
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */
+ __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */
+ __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */
+ __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */
+ __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */
+ __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */
+ uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */
+ __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */
+} HASH_TypeDef;
+#endif /* __ASM_INCLUDE__ */
+
+#ifndef __ASM_INCLUDE__
+/**
+ * @brief HASH_DIGEST
+ */
+
+typedef struct
+{
+ __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */
+} HASH_DIGEST_TypeDef;
+#endif /* __ASM_INCLUDE__ */
+
+
+
+
+
+/** @addtogroup Exported_constants
+ * @{
+ */
+
+ /** @addtogroup Peripheral_Registers_Bits_Definition
+ * @{
+ */
+
+/****************** Bits definition for HASH_CR register ********************/
+#define HASH_CR_INIT ((uint32_t)0x00000004)
+#define HASH_CR_DMAE ((uint32_t)0x00000008)
+#define HASH_CR_DATATYPE ((uint32_t)0x00000030)
+#define HASH_CR_DATATYPE_0 ((uint32_t)0x00000010)
+#define HASH_CR_DATATYPE_1 ((uint32_t)0x00000020)
+#define HASH_CR_MODE ((uint32_t)0x00000040)
+#define HASH_CR_ALGO ((uint32_t)0x00040080)
+#define HASH_CR_ALGO_0 ((uint32_t)0x00000080)
+#define HASH_CR_ALGO_1 ((uint32_t)0x00040000)
+#define HASH_CR_NBW ((uint32_t)0x00000F00)
+#define HASH_CR_NBW_0 ((uint32_t)0x00000100)
+#define HASH_CR_NBW_1 ((uint32_t)0x00000200)
+#define HASH_CR_NBW_2 ((uint32_t)0x00000400)
+#define HASH_CR_NBW_3 ((uint32_t)0x00000800)
+#define HASH_CR_DINNE ((uint32_t)0x00001000)
+#define HASH_CR_MDMAT ((uint32_t)0x00002000)
+#define HASH_CR_LKEY ((uint32_t)0x00010000)
+
+/****************** Bits definition for HASH_STR register *******************/
+#define HASH_STR_NBW ((uint32_t)0x0000001F)
+#define HASH_STR_NBW_0 ((uint32_t)0x00000001)
+#define HASH_STR_NBW_1 ((uint32_t)0x00000002)
+#define HASH_STR_NBW_2 ((uint32_t)0x00000004)
+#define HASH_STR_NBW_3 ((uint32_t)0x00000008)
+#define HASH_STR_NBW_4 ((uint32_t)0x00000010)
+#define HASH_STR_DCAL ((uint32_t)0x00000100)
+
+/****************** Bits definition for HASH_IMR register *******************/
+#define HASH_IMR_DINIM ((uint32_t)0x00000001)
+#define HASH_IMR_DCIM ((uint32_t)0x00000002)
+
+/****************** Bits definition for HASH_SR register ********************/
+#define HASH_SR_DINIS ((uint32_t)0x00000001)
+#define HASH_SR_DCIS ((uint32_t)0x00000002)
+#define HASH_SR_DMAS ((uint32_t)0x00000004)
+#define HASH_SR_BUSY ((uint32_t)0x00000008)
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _STM32_HAL_HASH_REG_H_ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h
index 29b9d34..4d5e302 100644
--- a/include/drivers/st/stm32_i2c.h
+++ b/include/drivers/st/stm32_i2c.h
@@ -1,11 +1,11 @@
/*
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
*
- * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
-#ifndef __STM32MP1_I2C_H
-#define __STM32MP1_I2C_H
+#ifndef STM32_I2C_H
+#define STM32_I2C_H
#include <stdint.h>
#include <utils_def.h>
@@ -72,6 +72,21 @@
#define I2C_TIMINGR_SDADEL GENMASK(19, 16)
#define I2C_TIMINGR_SCLDEL GENMASK(23, 20)
#define I2C_TIMINGR_PRESC GENMASK(31, 28)
+#define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1)
+#define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1)
+#define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1)
+#define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1)
+#define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1)
+#define I2C_SET_TIMINGR_SCLL(n) ((n) & \
+ (I2C_TIMINGR_SCLL_MAX - 1))
+#define I2C_SET_TIMINGR_SCLH(n) (((n) & \
+ (I2C_TIMINGR_SCLH_MAX - 1)) << 8)
+#define I2C_SET_TIMINGR_SDADEL(n) (((n) & \
+ (I2C_TIMINGR_SDADEL_MAX - 1)) << 16)
+#define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \
+ (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20)
+#define I2C_SET_TIMINGR_PRESC(n) (((n) & \
+ (I2C_TIMINGR_PRESC_MAX - 1)) << 28)
/* Bit definition for I2C_TIMEOUTR register */
#define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0)
@@ -110,94 +125,113 @@
#define I2C_ICR_TIMOUTCF BIT(12)
#define I2C_ICR_ALERTCF BIT(13)
-struct stm32_i2c_init_s {
- uint32_t timing; /* Specifies the I2C_TIMINGR_register value
- * This parameter is calculated by referring
- * to I2C initialization section in Reference
- * manual.
- */
-
- uint32_t own_address1; /* Specifies the first device own address.
- * This parameter can be a 7-bit or 10-bit
- * address.
- */
-
- uint32_t addressing_mode; /* Specifies if 7-bit or 10-bit addressing
- * mode is selected.
- * This parameter can be a value of @ref
- * I2C_ADDRESSING_MODE.
- */
-
- uint32_t dual_address_mode; /* Specifies if dual addressing mode is
- * selected.
- * This parameter can be a value of @ref
- * I2C_DUAL_ADDRESSING_MODE.
- */
-
- uint32_t own_address2; /* Specifies the second device own address
- * if dual addressing mode is selected.
- * This parameter can be a 7-bit address.
- */
-
- uint32_t own_address2_masks; /* Specifies the acknowledge mask address
- * second device own address if dual
- * addressing mode is selected.
- * This parameter can be a value of @ref
- * I2C_OWN_ADDRESS2_MASKS.
- */
-
- uint32_t general_call_mode; /* Specifies if general call mode is
- * selected.
- * This parameter can be a value of @ref
- * I2C_GENERAL_CALL_ADDRESSING_MODE.
- */
-
- uint32_t no_stretch_mode; /* Specifies if nostretch mode is
- * selected.
- * This parameter can be a value of @ref
- * I2C_NOSTRETCH_MODE.
- */
+enum i2c_speed_e {
+ I2C_SPEED_STANDARD, /* 100 kHz */
+ I2C_SPEED_FAST, /* 400 kHz */
+ I2C_SPEED_FAST_PLUS, /* 1 MHz */
+};
+
+#define STANDARD_RATE 100000
+#define FAST_RATE 400000
+#define FAST_PLUS_RATE 1000000
+struct stm32_i2c_init_s {
+ uint32_t own_address1; /*
+ * Specifies the first device own
+ * address. This parameter can be a
+ * 7-bit or 10-bit address.
+ */
+
+ uint32_t addressing_mode; /*
+ * Specifies if 7-bit or 10-bit
+ * addressing mode is selected.
+ * This parameter can be a value of
+ * @ref I2C_ADDRESSING_MODE.
+ */
+
+ uint32_t dual_address_mode; /*
+ * Specifies if dual addressing mode is
+ * selected.
+ * This parameter can be a value of @ref
+ * I2C_DUAL_ADDRESSING_MODE.
+ */
+
+ uint32_t own_address2; /*
+ * Specifies the second device own
+ * address if dual addressing mode is
+ * selected. This parameter can be a
+ * 7-bit address.
+ */
+
+ uint32_t own_address2_masks; /*
+ * Specifies the acknowledge mask
+ * address second device own address
+ * if dual addressing mode is selected
+ * This parameter can be a value of @ref
+ * I2C_OWN_ADDRESS2_MASKS.
+ */
+
+ uint32_t general_call_mode; /*
+ * Specifies if general call mode is
+ * selected.
+ * This parameter can be a value of @ref
+ * I2C_GENERAL_CALL_ADDRESSING_MODE.
+ */
+
+ uint32_t no_stretch_mode; /*
+ * Specifies if nostretch mode is
+ * selected.
+ * This parameter can be a value of @ref
+ * I2C_NOSTRETCH_MODE.
+ */
+
+ uint32_t rise_time; /*
+ * Specifies the SCL clock pin rising
+ * time in nanoseconds.
+ */
+
+ uint32_t fall_time; /*
+ * Specifies the SCL clock pin falling
+ * time in nanoseconds.
+ */
+
+ enum i2c_speed_e speed_mode; /*
+ * Specifies the I2C clock source
+ * frequency mode.
+ * This parameter can be a value of @ref
+ * i2c_speed_mode_e.
+ */
+
+ int analog_filter; /*
+ * Specifies if the I2C analog noise
+ * filter is selected.
+ * This parameter can be 0 (filter
+ * off), all other values mean filter
+ * on.
+ */
+
+ uint8_t digital_filter_coef; /*
+ * Specifies the I2C digital noise
+ * filter coefficient.
+ * This parameter can be a value
+ * between 0 and
+ * STM32_I2C_DIGITAL_FILTER_MAX.
+ */
};
enum i2c_state_e {
- I2C_STATE_RESET = 0x00U, /* Peripheral is not yet
- * initialized.
- */
- I2C_STATE_READY = 0x20U, /* Peripheral Initialized
- * and ready for use.
- */
- I2C_STATE_BUSY = 0x24U, /* An internal process is
- * ongoing.
- */
- I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission process
- * is ongoing.
- */
- I2C_STATE_BUSY_RX = 0x22U, /* Data Reception process
- * is ongoing.
- */
- I2C_STATE_LISTEN = 0x28U, /* Address Listen Mode is
- * ongoing.
- */
- I2C_STATE_BUSY_TX_LISTEN = 0x29U, /* Address Listen Mode
- * and Data Transmission
- * process is ongoing.
- */
- I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /* Address Listen Mode
- * and Data Reception
- * process is ongoing.
- */
- I2C_STATE_ABORT = 0x60U, /* Abort user request ongoing. */
- I2C_STATE_TIMEOUT = 0xA0U, /* Timeout state. */
- I2C_STATE_ERROR = 0xE0U /* Error. */
-
+ I2C_STATE_RESET = 0x00U, /* Not yet initialized */
+ I2C_STATE_READY = 0x20U, /* Ready for use */
+ I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */
+ I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */
+ I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */
};
enum i2c_mode_e {
- I2C_MODE_NONE = 0x00U, /* No I2C communication on going. */
- I2C_MODE_MASTER = 0x10U, /* I2C communication is in Master Mode. */
- I2C_MODE_SLAVE = 0x20U, /* I2C communication is in Slave Mode. */
- I2C_MODE_MEM = 0x40U /* I2C communication is in Memory Mode. */
+ I2C_MODE_NONE = 0x00U, /* No active communication */
+ I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */
+ I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */
+ I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */
};
@@ -212,52 +246,38 @@ enum i2c_mode_e {
struct i2c_handle_s {
uint32_t i2c_base_addr; /* Registers base address */
-
- struct stm32_i2c_init_s i2c_init; /* Communication parameters */
-
- uint8_t *p_buff; /* Pointer to transfer buffer */
-
- uint16_t xfer_size; /* Transfer size */
-
- uint16_t xfer_count; /* Transfer counter */
-
- uint32_t prev_state; /* Communication previous
- * state
- */
-
- uint8_t lock; /* Locking object */
-
- enum i2c_state_e i2c_state; /* Communication state */
-
- enum i2c_mode_e i2c_mode; /* Communication mode */
-
- uint32_t i2c_err; /* Error code */
+ unsigned int dt_status; /* DT nsec/sec status */
+ unsigned int clock; /* Clock reference */
+ uint8_t lock; /* Locking object */
+ enum i2c_state_e i2c_state; /* Communication state */
+ enum i2c_mode_e i2c_mode; /* Communication mode */
+ uint32_t i2c_err; /* Error code */
};
-#define I2C_ADDRESSINGMODE_7BIT 0x00000001U
-#define I2C_ADDRESSINGMODE_10BIT 0x00000002U
+#define I2C_ADDRESSINGMODE_7BIT 0x00000001U
+#define I2C_ADDRESSINGMODE_10BIT 0x00000002U
-#define I2C_DUALADDRESS_DISABLE 0x00000000U
-#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN
+#define I2C_DUALADDRESS_DISABLE 0x00000000U
+#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN
-#define I2C_GENERALCALL_DISABLE 0x00000000U
-#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN
+#define I2C_GENERALCALL_DISABLE 0x00000000U
+#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN
-#define I2C_NOSTRETCH_DISABLE 0x00000000U
-#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
+#define I2C_NOSTRETCH_DISABLE 0x00000000U
+#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
-#define I2C_MEMADD_SIZE_8BIT 0x00000001U
-#define I2C_MEMADD_SIZE_16BIT 0x00000002U
+#define I2C_MEMADD_SIZE_8BIT 0x00000001U
+#define I2C_MEMADD_SIZE_16BIT 0x00000002U
-#define I2C_RELOAD_MODE I2C_CR2_RELOAD
-#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND
-#define I2C_SOFTEND_MODE 0x00000000U
+#define I2C_RELOAD_MODE I2C_CR2_RELOAD
+#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND
+#define I2C_SOFTEND_MODE 0x00000000U
-#define I2C_NO_STARTSTOP 0x00000000U
-#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP)
-#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \
- I2C_CR2_RD_WRN)
-#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START)
+#define I2C_NO_STARTSTOP 0x00000000U
+#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP)
+#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \
+ I2C_CR2_RD_WRN)
+#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START)
#define I2C_FLAG_TXE I2C_ISR_TXE
#define I2C_FLAG_TXIS I2C_ISR_TXIS
@@ -280,21 +300,36 @@ struct i2c_handle_s {
I2C_CR2_NBYTES | I2C_CR2_RELOAD | \
I2C_CR2_RD_WRN)
-#define I2C_ANALOGFILTER_ENABLE ((uint32_t)0x00000000U)
-#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF
+#define I2C_TIMEOUT_BUSY_MS 25U
-int stm32_i2c_init(struct i2c_handle_s *hi2c);
+#define I2C_ANALOGFILTER_ENABLE 0x00000000U
+#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF
+/* STM32 specific defines */
+#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */
+#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */
+#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD
+#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */
+#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */
+#define STM32_I2C_DIGITAL_FILTER_MAX 16
+
+int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
+ struct stm32_i2c_init_s *init);
+int stm32_i2c_init(struct i2c_handle_s *hi2c,
+ struct stm32_i2c_init_s *init_data);
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
uint16_t mem_addr, uint16_t mem_add_size,
- uint8_t *p_data, uint16_t size, uint32_t timeout);
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms);
int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
uint16_t mem_addr, uint16_t mem_add_size,
- uint8_t *p_data, uint16_t size, uint32_t timeout);
-int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr,
- uint32_t trials, uint32_t timeout);
-
-int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
- uint32_t analog_filter);
-
-#endif /* __STM32MP1_I2C_H */
+ uint8_t *p_data, uint16_t size, uint32_t timeout_ms);
+int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint8_t *p_data, uint16_t size,
+ uint32_t timeout_ms);
+int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint8_t *p_data, uint16_t size,
+ uint32_t timeout_ms);
+bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr,
+ uint32_t trials, uint32_t timeout_ms);
+
+#endif /* STM32_I2C_H */
diff --git a/include/drivers/st/stm32_iwdg.h b/include/drivers/st/stm32_iwdg.h
new file mode 100644
index 0000000..b6d4769
--- /dev/null
+++ b/include/drivers/st/stm32_iwdg.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32_IWDG_H__
+#define __STM32_IWDG_H__
+
+#include <stdint.h>
+
+#define IWDG_HW_ENABLED BIT(0)
+#define IWDG_ENABLE_ON_STOP BIT(1)
+#define IWDG_ENABLE_ON_STANDBY BIT(2)
+
+int stm32_iwdg_init(void);
+void stm32_iwdg_refresh(uint32_t instance);
+void __dead2 stm32_iwdg_it_handler(int id);
+
+#endif /* __STM32_IWDG_H__ */
diff --git a/include/drivers/st/stm32_rng.h b/include/drivers/st/stm32_rng.h
new file mode 100644
index 0000000..a644118
--- /dev/null
+++ b/include/drivers/st/stm32_rng.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_RNG_H
+#define STM32_RNG_H
+
+int stm32_rng_read(uint8_t *out, uint32_t size);
+int stm32_rng_init(void);
+
+#endif /* STM32_RNG_H */
diff --git a/include/drivers/st/stm32_rtc.h b/include/drivers/st/stm32_rtc.h
new file mode 100644
index 0000000..bc9e61e
--- /dev/null
+++ b/include/drivers/st/stm32_rtc.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_RTC_H__
+#define __PLAT_RTC_H__
+
+#include <stdbool.h>
+
+#define RTC_TR 0x00U
+#define RTC_DR 0x04U
+#define RTC_SSR 0x08U
+#define RTC_ICSR 0x0CU
+#define RTC_PRER 0x10U
+#define RTC_WUTR 0x14U
+#define RTC_CR 0x18U
+#define RTC_SMCR 0x20U
+#define RTC_WPR 0x24U
+#define RTC_CALR 0x28U
+#define RTC_SHIFTR 0x2CU
+#define RTC_TSTR 0x30U
+#define RTC_TSDR 0x34U
+#define RTC_TSSSR 0x38U
+#define RTC_ALRMAR 0x40U
+#define RTC_ALRMASSR 0x44U
+#define RTC_ALRMBR 0x48U
+#define RTC_ALRMBSSR 0x4CU
+#define RTC_SR 0x50U
+#define RTC_SCR 0x5CU
+#define RTC_OR 0x60U
+
+struct stm32_rtc_calendar {
+ uint32_t ssr;
+ uint32_t tr;
+ uint32_t dr;
+};
+
+enum months {
+ JANUARY = 1,
+ FEBRUARY,
+ MARCH,
+ APRIL,
+ MAY,
+ JUNE,
+ JULY,
+ AUGUST,
+ SEPTEMBER,
+ OCTOBER,
+ NOVEMBER,
+ DECEMBER,
+ NB_MONTHS = 12
+};
+
+struct stm32_rtc_time {
+ uint32_t hour;
+ uint32_t min;
+ uint32_t sec;
+ uint32_t wday;
+ uint32_t day;
+ enum months month;
+ uint32_t year;
+};
+
+void stm32_rtc_get_calendar(struct stm32_rtc_calendar *calendar);
+unsigned long long stm32_rtc_diff_calendar(struct stm32_rtc_calendar *current,
+ struct stm32_rtc_calendar *ref);
+void stm32_rtc_set_tamper_timestamp(void);
+bool stm32_rtc_is_timestamp_enable(void);
+void stm32_rtc_get_timestamp(struct stm32_rtc_time *tamp_ts);
+int stm32_rtc_init(void);
+
+/* SMP protection on RTC registers access */
+void stm32_rtc_regs_lock(void);
+void stm32_rtc_regs_unlock(void);
+
+#endif /* __PLAT_RTC_H__ */
diff --git a/include/drivers/st/stm32_sdmmc2.h b/include/drivers/st/stm32_sdmmc2.h
new file mode 100644
index 0000000..b172659
--- /dev/null
+++ b/include/drivers/st/stm32_sdmmc2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_SDMMC2_H
+#define STM32_SDMMC2_H
+
+#include <mmc.h>
+#include <stdbool.h>
+
+struct stm32_sdmmc2_params {
+ uintptr_t reg_base;
+ unsigned int clk_rate;
+ unsigned int bus_width;
+ unsigned int flags;
+ struct mmc_device_info *device_info;
+ unsigned int pin_ckin;
+ unsigned int negedge;
+ unsigned int dirpol;
+ unsigned int clock_id;
+ unsigned int reset_id;
+ bool use_dma;
+};
+
+unsigned long long stm32_sdmmc2_mmc_get_device_size(void);
+int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params);
+bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory);
+
+#endif /* STM32_SDMMC2_H */
diff --git a/include/drivers/st/stm32_tamp.h b/include/drivers/st/stm32_tamp.h
new file mode 100644
index 0000000..3933c26
--- /dev/null
+++ b/include/drivers/st/stm32_tamp.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __TAMPER_H__
+#define __TAMPER_H__
+
+/* Internal Tamper */
+enum stm32_tamp_int_id {
+ ITAMP1 = 0,
+ ITAMP2,
+ ITAMP3,
+ ITAMP4,
+ ITAMP5,
+ ITAMP6,
+ ITAMP7,
+ ITAMP8,
+ ITAMP9,
+ ITAMP10,
+ ITAMP11,
+ ITAMP12,
+ ITAMP13,
+ ITAMP14,
+ ITAMP15,
+ ITAMP16
+};
+
+/* External Tamper */
+enum stm32_tamp_ext_id {
+ EXT_TAMP1 = 0,
+ EXT_TAMP2,
+ EXT_TAMP3,
+ EXT_TAMP4,
+ EXT_TAMP5,
+ EXT_TAMP6,
+ EXT_TAMP7,
+ EXT_TAMP8
+};
+
+enum stm32_tamp_state {
+ TAMP_DISABLE = 0,
+ TAMP_ENABLE
+};
+
+#define TAMP_UNUSED {.id = -1}
+
+/* define TAMPER modes */
+#define TAMP_TRIG_OFF 0x0U
+#define TAMP_TRIG_ON 0x1U
+#define TAMP_ACTIVE 0x2U
+#define TAMP_ERASE 0x0U
+#define TAMP_NOERASE 0x1U
+#define TAMP_NO_EVT_MASK 0x0U
+#define TAMP_EVT_MASK 0x1U
+
+/* define Passive FILTER mode */
+#define TAMP_FILTER_PRECHARGE 0x0U
+#define TAMP_FILTER_PULL_UP_DISABLE 0x1U
+#define TAMP_FILTER_DURATION_1_CYCLE 0x0U
+#define TAMP_FILTER_DURATION_2_CYCLES 0x1U
+#define TAMP_FILTER_DURATION_3_CYCLES 0x2U
+#define TAMP_FILTER_DURATION_4_CYCLES 0x3U
+#define TAMP_FILTER_COUNT_1 0x0U
+#define TAMP_FILTER_COUNT_2 0x1U
+#define TAMP_FILTER_COUNT_4 0x2U
+#define TAMP_FILTER_COUNT_8 0x3U
+#define TAMP_FILTER_SAMPLING_32768 0x0U
+#define TAMP_FILTER_SAMPLING_16384 0x1U
+#define TAMP_FILTER_SAMPLING_8192 0x2U
+#define TAMP_FILTER_SAMPLING_4096 0x3U
+#define TAMP_FILTER_SAMPLING_2048 0x4U
+#define TAMP_FILTER_SAMPLING_1024 0x5U
+#define TAMP_FILTER_SAMPLING_512 0x6U
+#define TAMP_FILTER_SAMPLING_256 0x7U
+
+/* define active filter */
+#define TAMP_ACTIVE_FILTER_OFF 0x0U
+#define TAMP_ACTIVE_FILTER_ON 0x1U
+#define TAMP_ACTIVE_ATO_DEDICTED 0x0U
+#define TAMP_ACTIVE_ATO_TAMPOUTSEL 0x1U
+#define TAMP_ACTIVE_APER_1_OUTPUT 0x0U
+#define TAMP_ACTIVE_APER_2_OUTPUTS 0x1U
+#define TAMP_ACTIVE_APER_3_4_OUTPUTS 0x2U
+#define TAMP_ACTIVE_APER_5_OUTPUTS 0x3U
+#define TAMP_ACTIVE_CKSEL_DIV_0 0x0U
+#define TAMP_ACTIVE_CKSEL_DIV_2 0x1U
+#define TAMP_ACTIVE_CKSEL_DIV_4 0x2U
+#define TAMP_ACTIVE_CKSEL_DIV_8 0x3U
+#define TAMP_ACTIVE_CKSEL_DIV_16 0x4U
+#define TAMP_ACTIVE_CKSEL_DIV_32 0x5U
+#define TAMP_ACTIVE_CKSEL_DIV_64 0x6U
+#define TAMP_ACTIVE_CKSEL_DIV_128 0x7U
+#define TAMP_ACTIVE_ATOSEL_OUT1_(X) (0x0U << (X * 2))
+#define TAMP_ACTIVE_ATOSEL_OUT2_(X) (0x1U << (X * 2))
+#define TAMP_ACTIVE_ATOSEL_OUT3_(X) (0x2U << (X * 2))
+#define TAMP_ACTIVE_ATOSEL_OUT4_(X) (0x3U << (X * 2))
+
+#define TAMP_EXT(tamp_id, trig, erase, mask) (((tamp_id) << 3) | ((trig) << 2)\
+ | ((erase) << 1) | (mask))
+
+#define TAMP_FLTCR(precharge, duration, count, sample) (((precharge) << 7) |\
+ ((duration) << 5) |\
+ ((count) << 3) |\
+ (sample))
+
+#define TAMP_ACT(filter, ato, aper, atcksel, atosel) (((filter) << 31) |\
+ ((ato) << 30) |\
+ ((aper) << 24) |\
+ ((atcksel) << 16) |\
+ (atosel) << 8)
+
+struct stm32_tamp_int {
+ int id;
+ void (*it_handler)(void);
+};
+
+struct stm32_tamp_ext {
+ int id;
+ uint8_t mode;
+ uint8_t erase;
+ uint8_t evt_mask;
+ void (*it_handler)(void);
+};
+
+/*
+ * stm32_tamp_write_mcounter : Increase monotonic counter
+ */
+void stm32_tamp_write_mcounter(void);
+
+/*
+ * stm32_tamp_it_handler : Interrupt handler
+ */
+void stm32_tamp_it_handler(void);
+
+/*
+ * stm32_tamp_configure_internal: Configure internal tamper
+ * tamper_list: List of tamper to enable
+ * nb_tamper: Number of tamper in list
+ */
+void stm32_tamp_configure_internal(struct stm32_tamp_int *tamper_list,
+ uint16_t nb_tamper);
+
+/*
+ * stm32_tamp_configure_external: Configure external tamper and associated
+ * configuration for filtering
+ * ext_tamp_list: List of external tamper to configure
+ * nb_tamper: Number of tamper in list
+ * passive_conf: Filter configuration
+ * active_conf: Configuration for active tamper
+ */
+void stm32_tamp_configure_external(struct stm32_tamp_ext *ext_tamper_list,
+ uint8_t nb_tamper, uint32_t passive_conf,
+ uint32_t active_conf);
+
+/*
+ * stm32_tamp_init: Initialize tamper from DT
+ * return 0 if disabled, 1 if enabled, else < 0
+ */
+int stm32_tamp_init(void);
+
+#endif /* __TAMPER__ */
diff --git a/include/drivers/st/stm32_timer.h b/include/drivers/st/stm32_timer.h
new file mode 100644
index 0000000..e62f3df
--- /dev/null
+++ b/include/drivers/st/stm32_timer.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_TIMER_H
+#define STM32_TIMER_H
+
+enum timer_cal {
+ HSI_CAL = 0,
+ CSI_CAL
+};
+
+unsigned long stm32_timer_hsi_freq(void);
+unsigned long stm32_timer_csi_freq(void);
+void stm32_timer_freq_func(unsigned long (**timer_freq_cb)(void),
+ enum timer_cal type);
+int stm32_timer_init(void);
+
+#endif /* STM32_TIMER_H */
diff --git a/include/drivers/st/stm32_uart_regs.h b/include/drivers/st/stm32_uart_regs.h
new file mode 100644
index 0000000..e78d3d4
--- /dev/null
+++ b/include/drivers/st/stm32_uart_regs.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_UART_REGS_H
+#define STM32_UART_REGS_H
+
+#include <utils_def.h>
+
+#define USART_CR1 U(0x00)
+#define USART_CR2 U(0x04)
+#define USART_CR3 U(0x08)
+#define USART_BRR U(0x0C)
+#define USART_GTPR U(0x10)
+#define USART_RTOR U(0x14)
+#define USART_RQR U(0x18)
+#define USART_ISR U(0x1C)
+#define USART_ICR U(0x20)
+#define USART_RDR U(0x24)
+#define USART_TDR U(0x28)
+#define USART_PRESC U(0x2C)
+
+/* USART_CR1 register fields */
+#define USART_CR1_UE BIT(0)
+#define USART_CR1_UESM BIT(1)
+#define USART_CR1_RE BIT(2)
+#define USART_CR1_TE BIT(3)
+#define USART_CR1_IDLEIE BIT(4)
+#define USART_CR1_RXNEIE BIT(5)
+#define USART_CR1_TCIE BIT(6)
+#define USART_CR1_TXEIE BIT(7)
+#define USART_CR1_PEIE BIT(8)
+#define USART_CR1_PS BIT(9)
+#define USART_CR1_PCE BIT(10)
+#define USART_CR1_WAKE BIT(11)
+#define USART_CR1_M (BIT(28) | BIT(12))
+#define USART_CR1_M0 BIT(12)
+#define USART_CR1_MME BIT(13)
+#define USART_CR1_CMIE BIT(14)
+#define USART_CR1_OVER8 BIT(15)
+#define USART_CR1_DEDT GENMASK(20, 16)
+#define USART_CR1_DEDT_0 BIT(16)
+#define USART_CR1_DEDT_1 BIT(17)
+#define USART_CR1_DEDT_2 BIT(18)
+#define USART_CR1_DEDT_3 BIT(19)
+#define USART_CR1_DEDT_4 BIT(20)
+#define USART_CR1_DEAT GENMASK(25, 21)
+#define USART_CR1_DEAT_0 BIT(21)
+#define USART_CR1_DEAT_1 BIT(22)
+#define USART_CR1_DEAT_2 BIT(23)
+#define USART_CR1_DEAT_3 BIT(24)
+#define USART_CR1_DEAT_4 BIT(25)
+#define USART_CR1_RTOIE BIT(26)
+#define USART_CR1_EOBIE BIT(27)
+#define USART_CR1_M1 BIT(28)
+#define USART_CR1_FIFOEN BIT(29)
+#define USART_CR1_TXFEIE BIT(30)
+#define USART_CR1_RXFFIE BIT(31)
+
+/* USART_CR2 register fields */
+#define USART_CR2_SLVEN BIT(0)
+#define USART_CR2_DIS_NSS BIT(3)
+#define USART_CR2_ADDM7 BIT(4)
+#define USART_CR2_LBDL BIT(5)
+#define USART_CR2_LBDIE BIT(6)
+#define USART_CR2_LBCL BIT(8)
+#define USART_CR2_CPHA BIT(9)
+#define USART_CR2_CPOL BIT(10)
+#define USART_CR2_CLKEN BIT(11)
+#define USART_CR2_STOP GENMASK(13, 12)
+#define USART_CR2_STOP_0 BIT(12)
+#define USART_CR2_STOP_1 BIT(13)
+#define USART_CR2_LINEN BIT(14)
+#define USART_CR2_SWAP BIT(15)
+#define USART_CR2_RXINV BIT(16)
+#define USART_CR2_TXINV BIT(17)
+#define USART_CR2_DATAINV BIT(18)
+#define USART_CR2_MSBFIRST BIT(19)
+#define USART_CR2_ABREN BIT(20)
+#define USART_CR2_ABRMODE GENMASK(22, 21)
+#define USART_CR2_ABRMODE_0 BIT(21)
+#define USART_CR2_ABRMODE_1 BIT(22)
+#define USART_CR2_RTOEN BIT(23)
+#define USART_CR2_ADD GENMASK(31, 24)
+
+/* USART_CR3 register fields */
+#define USART_CR3_EIE BIT(0)
+#define USART_CR3_IREN BIT(1)
+#define USART_CR3_IRLP BIT(2)
+#define USART_CR3_HDSEL BIT(3)
+#define USART_CR3_NACK BIT(4)
+#define USART_CR3_SCEN BIT(5)
+#define USART_CR3_DMAR BIT(6)
+#define USART_CR3_DMAT BIT(7)
+#define USART_CR3_RTSE BIT(8)
+#define USART_CR3_CTSE BIT(9)
+#define USART_CR3_CTSIE BIT(10)
+#define USART_CR3_ONEBIT BIT(11)
+#define USART_CR3_OVRDIS BIT(12)
+#define USART_CR3_DDRE BIT(13)
+#define USART_CR3_DEM BIT(14)
+#define USART_CR3_DEP BIT(15)
+#define USART_CR3_SCARCNT GENMASK(19, 17)
+#define USART_CR3_SCARCNT_0 BIT(17)
+#define USART_CR3_SCARCNT_1 BIT(18)
+#define USART_CR3_SCARCNT_2 BIT(19)
+#define USART_CR3_WUS GENMASK(21, 20)
+#define USART_CR3_WUS_0 BIT(20)
+#define USART_CR3_WUS_1 BIT(21)
+#define USART_CR3_WUFIE BIT(22)
+#define USART_CR3_TXFTIE BIT(23)
+#define USART_CR3_TCBGTIE BIT(24)
+#define USART_CR3_RXFTCFG GENMASK(27, 25)
+#define USART_CR3_RXFTCFG_0 BIT(25)
+#define USART_CR3_RXFTCFG_1 BIT(26)
+#define USART_CR3_RXFTCFG_2 BIT(27)
+#define USART_CR3_RXFTIE BIT(28)
+#define USART_CR3_TXFTCFG GENMASK(31, 29)
+#define USART_CR3_TXFTCFG_0 BIT(29)
+#define USART_CR3_TXFTCFG_1 BIT(30)
+#define USART_CR3_TXFTCFG_2 BIT(31)
+
+/* USART_BRR register fields */
+#define USART_BRR_DIV_FRACTION GENMASK(3, 0)
+#define USART_BRR_DIV_MANTISSA GENMASK(15, 4)
+
+/* USART_GTPR register fields */
+#define USART_GTPR_PSC GENMASK(7, 0)
+#define USART_GTPR_GT GENMASK(15, 8)
+
+/* USART_RTOR register fields */
+#define USART_RTOR_RTO GENMASK(23, 0)
+#define USART_RTOR_BLEN GENMASK(31, 24)
+
+/* USART_RQR register fields */
+#define USART_RQR_ABRRQ BIT(0)
+#define USART_RQR_SBKRQ BIT(1)
+#define USART_RQR_MMRQ BIT(2)
+#define USART_RQR_RXFRQ BIT(3)
+#define USART_RQR_TXFRQ BIT(4)
+
+/* USART_ISR register fields */
+#define USART_ISR_PE BIT(0)
+#define USART_ISR_FE BIT(1)
+#define USART_ISR_NE BIT(2)
+#define USART_ISR_ORE BIT(3)
+#define USART_ISR_IDLE BIT(4)
+#define USART_ISR_RXNE BIT(5)
+#define USART_ISR_TC BIT(6)
+#define USART_ISR_TXE BIT(7)
+#define USART_ISR_LBDF BIT(8)
+#define USART_ISR_CTSIF BIT(9)
+#define USART_ISR_CTS BIT(10)
+#define USART_ISR_RTOF BIT(11)
+#define USART_ISR_EOBF BIT(12)
+#define USART_ISR_UDR BIT(13)
+#define USART_ISR_ABRE BIT(14)
+#define USART_ISR_ABRF BIT(15)
+#define USART_ISR_BUSY BIT(16)
+#define USART_ISR_CMF BIT(17)
+#define USART_ISR_SBKF BIT(18)
+#define USART_ISR_RWU BIT(19)
+#define USART_ISR_WUF BIT(20)
+#define USART_ISR_TEACK BIT(21)
+#define USART_ISR_REACK BIT(22)
+#define USART_ISR_TXFE BIT(23)
+#define USART_ISR_RXFF BIT(24)
+#define USART_ISR_TCBGT BIT(25)
+#define USART_ISR_RXFT BIT(26)
+#define USART_ISR_TXFT BIT(27)
+
+/* USART_ICR register fields */
+#define USART_ICR_PECF BIT(0)
+#define USART_ICR_FECF BIT(1)
+#define USART_ICR_NCF BIT(2)
+#define USART_ICR_ORECF BIT(3)
+#define USART_ICR_IDLECF BIT(4)
+#define USART_ICR_TCCF BIT(6)
+#define USART_ICR_TCBGT BIT(7)
+#define USART_ICR_LBDCF BIT(8)
+#define USART_ICR_CTSCF BIT(9)
+#define USART_ICR_RTOCF BIT(11)
+#define USART_ICR_EOBCF BIT(12)
+#define USART_ICR_UDRCF BIT(13)
+#define USART_ICR_CMCF BIT(17)
+#define USART_ICR_WUCF BIT(20)
+
+/* USART_RDR register fields */
+#define USART_RDR_RDR GENMASK(8, 0)
+
+/* USART_TDR register fields */
+#define USART_TDR_TDR GENMASK(8, 0)
+
+/* USART_PRESC register fields */
+#define USART_PRESC_PRESCALER GENMASK(3, 0)
+
+#endif /* STM32_UART_REGS_H */
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index 85a1eb8..0c8583a 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -4,27 +4,72 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_CLK_H__
-#define __STM32MP1_CLK_H__
+#ifndef STM32MP1_CLK_H
+#define STM32MP1_CLK_H
-#include <arch_helpers.h>
#include <stdbool.h>
+#include <stdint.h>
+
+#include <dt-bindings/clock/stm32mp1-clks.h>
int stm32mp1_clk_probe(void);
int stm32mp1_clk_init(void);
+
+bool stm32mp1_rcc_is_secure(void);
+bool stm32mp1_rcc_is_mckprot(void);
+
+void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure);
+void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure);
bool stm32mp1_clk_is_enabled(unsigned long id);
-int stm32mp1_clk_enable(unsigned long id);
-int stm32mp1_clk_disable(unsigned long id);
-unsigned long stm32mp1_clk_get_rate(unsigned long id);
-void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
-static inline uint32_t get_timer(uint32_t base)
+static inline void stm32mp1_clk_enable_non_secure(unsigned long id)
+{
+ __stm32mp1_clk_enable(id, false);
+}
+
+static inline void stm32mp1_clk_enable_secure(unsigned long id)
+{
+ __stm32mp1_clk_enable(id, true);
+}
+
+static inline void stm32mp1_clk_disable_non_secure(unsigned long id)
{
- if (base == 0U) {
- return (uint32_t)(~read_cntpct_el0());
- }
+ __stm32mp1_clk_disable(id, false);
+}
- return base - (uint32_t)(~read_cntpct_el0());
+static inline void stm32mp1_clk_disable_secure(unsigned long id)
+{
+ __stm32mp1_clk_disable(id, true);
}
-#endif /* __STM32MP1_CLK_H__ */
+unsigned int stm32mp1_clk_get_refcount(unsigned long id);
+
+unsigned long stm32mp_clk_get_rate(unsigned long id);
+unsigned long stm32mp_clk_timer_get_rate(unsigned long id);
+
+void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
+
+bool stm32mp1_rtc_get_read_twice(void);
+
+/* SMP protection on RCC registers access */
+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);
+#endif
+
+void stm32mp1_rcc_init_late(void);
+
+void stm32mp1_register_clock_parents_secure(unsigned long id);
+
+void stm32mp1_update_earlyboot_clocks_state(void);
+
+#endif /* STM32MP1_CLK_H */
diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h
index 635a9cd..b488478 100644
--- a/include/drivers/st/stm32mp1_clkfunc.h
+++ b/include/drivers/st/stm32mp1_clkfunc.h
@@ -4,9 +4,10 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_CLKFUNC_H__
-#define __STM32MP1_CLKFUNC_H__
+#ifndef STM32MP1_CLKFUNC_H
+#define STM32MP1_CLKFUNC_H
+#include <libfdt.h>
#include <stdbool.h>
enum stm32mp_osc_id {
@@ -16,7 +17,6 @@ enum stm32mp_osc_id {
_LSI,
_LSE,
_I2S_CKIN,
- _USB_PHY_48,
NB_OSC,
_UNKNOWN_OSC_ID = 0xFF
};
@@ -29,14 +29,6 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
const char *prop_name,
uint32_t dflt_value);
-uint32_t fdt_rcc_read_addr(void);
-int fdt_rcc_read_uint32_array(const char *prop_name,
- uint32_t *array, uint32_t count);
-int fdt_rcc_subnode_offset(const char *name);
-const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp);
-bool fdt_get_rcc_secure_status(void);
+int fdt_rcc_enable_it(const char *name);
-uintptr_t fdt_get_stgen_base(void);
-int fdt_get_clock_id(int node);
-
-#endif /* __STM32MP1_CLKFUNC_H__ */
+#endif /* STM32MP1_CLKFUNC_H */
diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h
index 0765664..b2773b0 100644
--- a/include/drivers/st/stm32mp1_ddr.h
+++ b/include/drivers/st/stm32mp1_ddr.h
@@ -4,8 +4,8 @@
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
-#ifndef _STM32MP1_DDR_H
-#define _STM32MP1_DDR_H
+#ifndef STM32MP1_DDR_H
+#define STM32MP1_DDR_H
#include <stdbool.h>
@@ -152,7 +152,7 @@ struct stm32mp1_ddrphy_cal {
struct stm32mp1_ddr_info {
const char *name;
- uint16_t speed; /* in MHZ */
+ uint32_t speed; /* in kHZ */
uint32_t size; /* Memory size in byte = col * row * width */
};
@@ -165,9 +165,12 @@ struct stm32mp1_ddr_config {
struct stm32mp1_ddrphy_reg p_reg;
struct stm32mp1_ddrphy_timing p_timing;
struct stm32mp1_ddrphy_cal p_cal;
+ bool self_refresh;
+ uint32_t zdata;
};
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed);
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed);
void stm32mp1_ddr_init(struct ddr_info *priv,
struct stm32mp1_ddr_config *config);
-#endif /* _STM32MP1_DDR_H */
+
+#endif /* STM32MP1_DDR_H */
diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h
index 298a080..ecc14d2 100644
--- a/include/drivers/st/stm32mp1_ddr_helpers.h
+++ b/include/drivers/st/stm32mp1_ddr_helpers.h
@@ -4,9 +4,17 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_DDR_HELPERS_H__
-#define __STM32MP1_DDR_HELPERS_H__
+#ifndef STM32MP1_DDR_HELPERS_H
+#define STM32MP1_DDR_HELPERS_H
+
+#include <stdbool.h>
void ddr_enable_clock(void);
+int ddr_sw_self_refresh_exit(void);
+int ddr_standby_sr_entry(uint32_t *zq0cr0_zdata);
+void ddr_sr_mode_ssr(void);
+void ddr_sr_mode_asr(void);
+void ddr_sr_mode_hsr(void);
+bool ddr_is_nonsecured_area(uintptr_t address, uint32_t length);
-#endif /* __STM32MP1_DDR_HELPERS_H__ */
+#endif /* STM32MP1_DDR_HELPERS_H */
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
index 64ad965..e928688 100644
--- a/include/drivers/st/stm32mp1_ddr_regs.h
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
@@ -4,9 +4,10 @@
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
-#ifndef _RAM_STM32MP1_DDR_REGS_H
-#define _RAM_STM32MP1_DDR_REGS_H
+#ifndef STM32MP1_DDR_REGS_H
+#define STM32MP1_DDR_REGS_H
+#include <stdio.h>
#include <utils_def.h>
/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */
@@ -247,11 +248,14 @@ struct stm32mp1_ddrphy {
#define DDRCTRL_DBGSTAT 0x310
#define DDRCTRL_SWCTL 0x320
#define DDRCTRL_SWSTAT 0x324
+#define DDRCTRL_PSTAT 0x3FC
#define DDRCTRL_PCTRL_0 0x490
#define DDRCTRL_PCTRL_1 0x540
/* DDR Controller Register fields */
#define DDRCTRL_MSTR_DDR3 BIT(0)
+#define DDRCTRL_MSTR_LPDDR2 BIT(2)
+#define DDRCTRL_MSTR_LPDDR3 BIT(3)
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12)
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12)
@@ -269,7 +273,7 @@ struct stm32mp1_ddrphy {
/* Only one rank supported */
#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4
#define DDRCTRL_MRCTRL0_MR_RANK_ALL \
- (0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT)
+ BIT(DDRCTRL_MRCTRL0_MR_RANK_SHIFT)
#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12
#define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12)
#define DDRCTRL_MRCTRL0_MR_WR BIT(31)
@@ -367,6 +371,7 @@ struct stm32mp1_ddrphy {
#define DDRPHYC_DLLGCR_BPS200 BIT(23)
+#define DDRPHYC_ACDLLCR_DLLSRST BIT(30)
#define DDRPHYC_ACDLLCR_DLLDIS BIT(31)
#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0
@@ -408,6 +413,4 @@ struct stm32mp1_ddrphy {
#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14)
#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14
-void ddr_enable_clock(void);
-
-#endif /* _RAM_STM32MP1_DDR_REGS_H */
+#endif /* STM32MP1_DDR_REGS_H */
diff --git a/include/drivers/st/stm32mp1_pmic.h b/include/drivers/st/stm32mp1_pmic.h
deleted file mode 100644
index 5d94b40..0000000
--- a/include/drivers/st/stm32mp1_pmic.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __STM32MP1_PMIC_H__
-#define __STM32MP1_PMIC_H__
-
-#include <stdbool.h>
-
-bool dt_check_pmic(void);
-int dt_pmic_enable_boot_on_regulators(void);
-void initialize_pmic_i2c(void);
-void initialize_pmic(void);
-int pmic_ddr_power_init(enum ddr_type ddr_type);
-
-#endif /* __STM32MP1_PMIC_H__ */
diff --git a/include/drivers/st/stm32mp1_pwr.h b/include/drivers/st/stm32mp1_pwr.h
index e567042..1a22824 100644
--- a/include/drivers/st/stm32mp1_pwr.h
+++ b/include/drivers/st/stm32mp1_pwr.h
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_PWR_H__
-#define __STM32MP1_PWR_H__
+#ifndef STM32MP1_PWR_H
+#define STM32MP1_PWR_H
#include <utils_def.h>
@@ -13,20 +13,43 @@
#define PWR_CR2 U(0x08)
#define PWR_CR3 U(0x0C)
#define PWR_MPUCR U(0x10)
+#define PWR_MCUCR U(0x14)
#define PWR_WKUPCR U(0x20)
#define PWR_MPUWKUPENR U(0x28)
+#define PWR_OFFSET_MASK GENMASK(9, 0)
+
#define PWR_CR1_LPDS BIT(0)
#define PWR_CR1_LPCFG BIT(1)
#define PWR_CR1_LVDS BIT(2)
#define PWR_CR1_DBP BIT(8)
+#define PWR_CR2_BREN BIT(0)
+#define PWR_CR2_RREN BIT(1)
+
+#define PWR_CR3_VBE BIT(8)
+#define PWR_CR3_VBRS BIT(9)
#define PWR_CR3_DDRSREN BIT(10)
#define PWR_CR3_DDRSRDIS BIT(11)
#define PWR_CR3_DDRRETEN BIT(12)
+#define PWR_CR3_USB33DEN BIT(24)
+#define PWR_CR3_REG18EN BIT(28)
+#define PWR_CR3_REG11EN BIT(30)
#define PWR_MPUCR_PDDS BIT(0)
#define PWR_MPUCR_CSTDBYDIS BIT(3)
#define PWR_MPUCR_CSSF BIT(9)
-#endif /* __STM32MP1_PWR_H__ */
+#define PWR_MCUCR_PDDS BIT(0)
+
+#define PWR_WKUPCR_MASK GENMASK(27, 16) | GENMASK(13, 8) | GENMASK(5, 0)
+
+#define PWR_MPUWKUPENR_MASK GENMASK(5, 0)
+
+#ifndef __ASSEMBLY__
+/* SMP protection on PWR registers access */
+void pwr_regs_lock(void);
+void pwr_regs_unlock(void);
+#endif /* __ASSEMBLY__ */
+
+#endif /* STM32MP1_PWR_H */
diff --git a/include/drivers/st/stm32mp1_ram.h b/include/drivers/st/stm32mp1_ram.h
index af96177..38360e7 100644
--- a/include/drivers/st/stm32mp1_ram.h
+++ b/include/drivers/st/stm32mp1_ram.h
@@ -4,9 +4,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef _STM32MP1_RAM_H
-#define _STM32MP1_RAM_H
+#ifndef STM32MP1_RAM_H
+#define STM32MP1_RAM_H
int stm32mp1_ddr_probe(void);
-#endif /* _STM32MP1_RAM_H */
+#endif /* STM32MP1_RAM_H */
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index e28ca97..7e1b337 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_RCC_H__
-#define __STM32MP1_RCC_H__
+#ifndef STM32MP1_RCC_H
+#define STM32MP1_RCC_H
#include <utils_def.h>
@@ -68,6 +68,14 @@
#define RCC_MP_AHB6ENCLRR U(0x21C)
#define RCC_MP_TZAHB6ENSETR U(0x220)
#define RCC_MP_TZAHB6ENCLRR U(0x224)
+#define RCC_MC_APB4ENSETR U(0x280)
+#define RCC_MC_APB4ENCLRR U(0x284)
+#define RCC_MC_APB5ENSETR U(0x288)
+#define RCC_MC_APB5ENCLRR U(0x28C)
+#define RCC_MC_AHB5ENSETR U(0x290)
+#define RCC_MC_AHB5ENCLRR U(0x294)
+#define RCC_MC_AHB6ENSETR U(0x298)
+#define RCC_MC_AHB6ENCLRR U(0x29C)
#define RCC_MP_APB4LPENSETR U(0x300)
#define RCC_MP_APB4LPENCLRR U(0x304)
#define RCC_MP_APB5LPENSETR U(0x308)
@@ -78,6 +86,14 @@
#define RCC_MP_AHB6LPENCLRR U(0x31C)
#define RCC_MP_TZAHB6LPENSETR U(0x320)
#define RCC_MP_TZAHB6LPENCLRR U(0x324)
+#define RCC_MC_APB4LPENSETR U(0x380)
+#define RCC_MC_APB4LPENCLRR U(0x384)
+#define RCC_MC_APB5LPENSETR U(0x388)
+#define RCC_MC_APB5LPENCLRR U(0x38C)
+#define RCC_MC_AHB5LPENSETR U(0x390)
+#define RCC_MC_AHB5LPENCLRR U(0x394)
+#define RCC_MC_AHB6LPENSETR U(0x398)
+#define RCC_MC_AHB6LPENCLRR U(0x39C)
#define RCC_BR_RSTSCLRR U(0x400)
#define RCC_MP_GRSTCSETR U(0x404)
#define RCC_MP_RSTSCLRR U(0x408)
@@ -95,6 +111,7 @@
#define RCC_RCK4SELR U(0x824)
#define RCC_TIMG1PRER U(0x828)
#define RCC_TIMG2PRER U(0x82C)
+#define RCC_MCUDIVR U(0x830)
#define RCC_APB1DIVR U(0x834)
#define RCC_APB2DIVR U(0x838)
#define RCC_APB3DIVR U(0x83C)
@@ -162,6 +179,22 @@
#define RCC_MP_AHB4ENCLRR U(0xA2C)
#define RCC_MP_MLAHBENSETR U(0xA38)
#define RCC_MP_MLAHBENCLRR U(0xA3C)
+#define RCC_MC_APB1ENSETR U(0xA80)
+#define RCC_MC_APB1ENCLRR U(0xA84)
+#define RCC_MC_APB2ENSETR U(0xA88)
+#define RCC_MC_APB2ENCLRR U(0xA8C)
+#define RCC_MC_APB3ENSETR U(0xA90)
+#define RCC_MC_APB3ENCLRR U(0xA94)
+#define RCC_MC_AHB2ENSETR U(0xA98)
+#define RCC_MC_AHB2ENCLRR U(0xA9C)
+#define RCC_MC_AHB3ENSETR U(0xAA0)
+#define RCC_MC_AHB3ENCLRR U(0xAA4)
+#define RCC_MC_AHB4ENSETR U(0xAA8)
+#define RCC_MC_AHB4ENCLRR U(0xAAC)
+#define RCC_MC_AXIMENSETR U(0xAB0)
+#define RCC_MC_AXIMENCLRR U(0xAB4)
+#define RCC_MC_MLAHBENSETR U(0xAB8)
+#define RCC_MC_MLAHBENCLRR U(0xABC)
#define RCC_MP_APB1LPENSETR U(0xB00)
#define RCC_MP_APB1LPENCLRR U(0xB04)
#define RCC_MP_APB2LPENSETR U(0xB08)
@@ -178,12 +211,34 @@
#define RCC_MP_AXIMLPENCLRR U(0xB34)
#define RCC_MP_MLAHBLPENSETR U(0xB38)
#define RCC_MP_MLAHBLPENCLRR U(0xB3C)
+#define RCC_MC_APB1LPENSETR U(0xB80)
+#define RCC_MC_APB1LPENCLRR U(0xB84)
+#define RCC_MC_APB2LPENSETR U(0xB88)
+#define RCC_MC_APB2LPENCLRR U(0xB8C)
+#define RCC_MC_APB3LPENSETR U(0xB90)
+#define RCC_MC_APB3LPENCLRR U(0xB94)
+#define RCC_MC_AHB2LPENSETR U(0xB98)
+#define RCC_MC_AHB2LPENCLRR U(0xB9C)
+#define RCC_MC_AHB3LPENSETR U(0xBA0)
+#define RCC_MC_AHB3LPENCLRR U(0xBA4)
+#define RCC_MC_AHB4LPENSETR U(0xBA8)
+#define RCC_MC_AHB4LPENCLRR U(0xBAC)
+#define RCC_MC_AXIMLPENSETR U(0xBB0)
+#define RCC_MC_AXIMLPENCLRR U(0xBB4)
+#define RCC_MC_MLAHBLPENSETR U(0xBB8)
+#define RCC_MC_MLAHBLPENCLRR U(0xBBC)
+#define RCC_MC_RSTSCLRR U(0xC00)
+#define RCC_MC_CIER U(0xC14)
+#define RCC_MC_CIFR U(0xC18)
#define RCC_VERR U(0xFF4)
#define RCC_IDR U(0xFF8)
#define RCC_SIDR U(0xFFC)
+#define RCC_OFFSET_MASK GENMASK(11, 0)
+
/* Values for RCC_TZCR register */
#define RCC_TZCR_TZEN BIT(0)
+#define RCC_TZCR_MCKPROT BIT(1)
/* Used for most of RCC_<x>SELR registers */
#define RCC_SELR_SRC_MASK GENMASK(2, 0)
@@ -220,6 +275,10 @@
#define RCC_APBXDIV_MASK GENMASK(2, 0)
#define RCC_MPUDIV_MASK GENMASK(2, 0)
#define RCC_AXIDIV_MASK GENMASK(2, 0)
+#define RCC_MCUDIV_MASK GENMASK(3, 0)
+
+/* Used for TIMER Prescaler */
+#define RCC_TIMGXPRER_TIMGXPRE BIT(0)
/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */
#define RCC_MP_ENCLRR_OFFSET U(4)
@@ -228,6 +287,7 @@
#define RCC_BDCR_LSEON BIT(0)
#define RCC_BDCR_LSEBYP BIT(1)
#define RCC_BDCR_LSERDY BIT(2)
+#define RCC_BDCR_DIGBYP BIT(3)
#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4)
#define RCC_BDCR_LSEDRV_SHIFT 4
#define RCC_BDCR_LSECSSON BIT(8)
@@ -243,6 +303,7 @@
/* Used for all RCC_PLL<n>CR registers */
#define RCC_PLLNCR_PLLON BIT(0)
#define RCC_PLLNCR_PLLRDY BIT(1)
+#define RCC_PLLNCR_SSCG_CTRL BIT(2)
#define RCC_PLLNCR_DIVPEN BIT(4)
#define RCC_PLLNCR_DIVQEN BIT(5)
#define RCC_PLLNCR_DIVREN BIT(6)
@@ -281,8 +342,12 @@
/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */
#define RCC_OCENR_HSION BIT(0)
+#define RCC_OCENR_HSIKERON BIT(1)
#define RCC_OCENR_CSION BIT(4)
+#define RCC_OCENR_CSIKERON BIT(5)
+#define RCC_OCENR_DIGBYP BIT(7)
#define RCC_OCENR_HSEON BIT(8)
+#define RCC_OCENR_HSEKERON BIT(9)
#define RCC_OCENR_HSEBYP BIT(10)
#define RCC_OCENR_HSECSSON BIT(11)
@@ -319,6 +384,16 @@
/* Fields of RCC_HSICFGR register */
#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0)
+#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)
+
+/* Fields of RCC_CSICFGR register */
+#define RCC_CSICFGR_CSITRIM_SHIFT 8
+#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8)
+#define RCC_CSICFGR_CSICAL_SHIFT 16
+#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16)
/* Used for RCC_MCO related operations */
#define RCC_MCOCFG_MCOON BIT(12)
@@ -330,22 +405,37 @@
#define RCC_DBGCFGR_DBGCKEN BIT(8)
/* RCC register fields for reset reasons */
-#define RCC_MP_RSTSCLRR_PORRSTF BIT(0)
-#define RCC_MP_RSTSCLRR_BORRSTF BIT(1)
-#define RCC_MP_RSTSCLRR_PADRSTF BIT(2)
-#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3)
-#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4)
-#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6)
-#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8)
-#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9)
-#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11)
-#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12)
+#define RCC_MP_RSTSCLRR_PORRSTF BIT(0)
+#define RCC_MP_RSTSCLRR_BORRSTF BIT(1)
+#define RCC_MP_RSTSCLRR_PADRSTF BIT(2)
+#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3)
+#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4)
+#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6)
+#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7)
+#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8)
+#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9)
+#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11)
+#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12)
+#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13)
+#define RCC_MP_RSTSCLRR_MPUP1RSTF BIT(14)
/* Global Reset Register */
#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
+#define RCC_MP_GRSTCSETR_MCURST BIT(1)
+#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
+#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5)
/* Clock Source Interrupt Flag Register */
#define RCC_MP_CIFR_MASK U(0x110F1F)
+#define RCC_MP_CIFR_LSIRDYF BIT(0)
+#define RCC_MP_CIFR_LSERDYF BIT(1)
+#define RCC_MP_CIFR_HSIRDYF BIT(2)
+#define RCC_MP_CIFR_HSERDYF BIT(3)
+#define RCC_MP_CIFR_CSIRDYF BIT(4)
+#define RCC_MP_CIFR_PLL1DYF BIT(8)
+#define RCC_MP_CIFR_PLL2DYF BIT(9)
+#define RCC_MP_CIFR_PLL3DYF BIT(10)
+#define RCC_MP_CIFR_PLL4DYF BIT(11)
#define RCC_MP_CIFR_WKUPF BIT(20)
/* Stop Request Set Register */
@@ -362,7 +452,29 @@
/* Values of RCC_MP_APB1ENSETR register */
#define RCC_MP_APB1ENSETR_UART4EN BIT(16)
+/* Values of RCC_MP_APB5ENSETR register */
+#define RCC_MP_APB5ENSETR_SPI6EN BIT(0)
+#define RCC_MP_APB5ENSETR_I2C4EN BIT(2)
+#define RCC_MP_APB5ENSETR_I2C6EN BIT(3)
+#define RCC_MP_APB5ENSETR_USART1EN BIT(4)
+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8)
+#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15)
+
/* Values of RCC_MP_AHB4ENSETR register */
#define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6)
+#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7)
+
+/* Values of RCC_MP_AHB5ENSETR register */
+#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(0)
+#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4)
+#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5)
+#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6)
+
+/* Values of RCC_MP_IWDGFZSETR register */
+#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0)
+#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1)
+
+/* Values of RCC_PWRLPDLYCR register */
+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0)
-#endif /* __STM32MP1_RCC_H__ */
+#endif /* STM32MP1_RCC_H */
diff --git a/include/drivers/st/stm32mp1_reset.h b/include/drivers/st/stm32mp1_reset.h
deleted file mode 100644
index 76ee09d..0000000
--- a/include/drivers/st/stm32mp1_reset.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __STM32MP1_RESET_H__
-#define __STM32MP1_RESET_H__
-
-#include <stdint.h>
-
-void stm32mp1_reset_assert(uint32_t reset_id);
-void stm32mp1_reset_deassert(uint32_t reset_id);
-
-#endif /* __STM32MP1_RESET_H__ */
diff --git a/include/drivers/st/stm32mp1xx_hal.h b/include/drivers/st/stm32mp1xx_hal.h
new file mode 100644
index 0000000..5e4f9e7
--- /dev/null
+++ b/include/drivers/st/stm32mp1xx_hal.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32_HAL_H
+#define __STM32_HAL_H
+
+#include <arch_helpers.h>
+#include <mmio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <delay_timer.h>
+
+typedef enum {
+ HAL_OK = 0x00,
+ HAL_ERROR = 0x01,
+ HAL_BUSY = 0x02,
+ HAL_TIMEOUT = 0x03
+} HAL_StatusTypeDef;
+
+typedef enum {
+ HAL_UNLOCKED = 0x00,
+ HAL_LOCKED = 0x01
+} HAL_LockTypeDef;
+
+typedef enum {
+ RESET = 0,
+ SET = !RESET
+} FlagStatus, ITStatus;
+
+typedef uint32_t Std_ReturnType;
+
+#define STD_OK ((uint32_t)0x77)
+#define STD_NOT_OK ((uint32_t)0x66)
+
+#define WRITE_REG(REG, VAL) ((REG) = (VAL))
+#define READ_REG(REG) ((REG))
+#define MODIFY_REG(REG, CLEARMASK, SETMASK) \
+ WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
+
+#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET)
+#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET)
+
+#define SET_BIT(_reg, _val) mmio_setbits_32((uintptr_t)&(_reg), _val)
+#define CLEAR_BIT(_reg, _val) mmio_clrbits_32((uintptr_t)&(_reg), _val)
+
+#define __IO volatile /*!< Defines 'read / write' permissions */
+#define __I volatile const /*!< Defines 'read only' permissions */
+
+#define HAL_MAX_DELAY 0xFFFFFFFF
+
+#define assert_param(expr) ((void)0)
+
+#define HAL_GetTick() (uint32_t)read_cntpct_el0()
+
+static inline void HAL_Delay(uint32_t x)
+{
+ udelay(x);
+}
+
+/**
+ * @brief Universal Synchronous Asynchronous Receiver Transmitter
+ */
+
+typedef struct {
+ __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */
+ __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */
+ __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */
+ uint16_t RESERVED2; /*!< Reserved, 0x12 */
+ __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */
+ __IO uint16_t RQR; /*!< USART Request register, Address offset: 0x18 */
+ uint16_t RESERVED3; /*!< Reserved, 0x1A */
+ __IO uint32_t ISReg; /*!< USART Interrupt and status register, Address offset: 0x1C */
+ __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */
+ __IO uint16_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */
+ uint16_t RESERVED4; /*!< Reserved, 0x26 */
+ __IO uint16_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */
+ uint16_t RESERVED5; /*!< Reserved, 0x2A */
+ __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */
+} USART_TypeDef;
+
+typedef struct {
+ __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */
+ __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */
+ __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */
+ __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */
+ __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */
+ __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */
+ __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */
+ __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */
+ __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */
+ __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */
+ __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */
+ __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */
+ __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */
+ __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */
+ __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */
+ __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */
+ __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgment timer register, Address offset: 0x40 */
+ uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */
+ __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */
+ __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */
+ __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */
+ __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */
+ uint32_t RESERVED1[8]; /*!< Reserved, 0x4C-0x7C */
+ __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */
+} SDMMC_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t BCR1; /*!< Address offset: 0x00 */
+ __IO uint32_t BTR1; /*!< Address offset: 0x04 */
+ __IO uint32_t BCR2; /*!< Address offset: 0x08 */
+ __IO uint32_t BTR2; /*!< Address offset: 0x0C */
+ __IO uint32_t BCR3; /*!< Address offset: 0x10 */
+ __IO uint32_t BTR3; /*!< Address offset: 0x14 */
+ __IO uint32_t BCR4; /*!< Address offset: 0x18 */
+ __IO uint32_t BTR4; /*!< Address offset: 0x1C */
+ uint32_t RESERVED0[24];
+ __IO uint32_t PCReg; /*!< Address offset: 0x80 */
+ __IO uint32_t SR; /*!< Address offset: 0x84 */
+ __IO uint32_t PMEM; /*!< Address offset: 0x88 */
+ __IO uint32_t PATT; /*!< Address offset: 0x8C */
+ __IO uint32_t HPR; /*! Address offset: 0x90 */
+ __IO uint32_t HECCR; /*!< Address offset: 0x94 */
+ uint32_t RESERVED2[27];
+ __IO uint32_t BWTR1; /*!< Address offset: 0x104 */
+ uint32_t RESERVED3;
+ __IO uint32_t BWTR2; /*!< Address offset: 0x10C */
+ uint32_t RESERVED4;
+ __IO uint32_t BWTR3; /*!< Address offset: 0x114 */
+ uint32_t RESERVED5;
+ __IO uint32_t BWTR4; /*!< Address offset: 0x11c */
+ uint32_t RESERVED6[8];
+ __IO uint32_t SDCR1; /*!< Address offset: 0x140 */
+ __IO uint32_t SDCR2; /*!< Address offset: 0x144 */
+ __IO uint32_t SDTR1; /*!< Address offset: 0x148 */
+ __IO uint32_t SDTR2; /*!< Address offset: 0x14c */
+ __IO uint32_t SDCMR; /*!< Address offset: 0x150 */
+ __IO uint32_t SDRTR; /*!< Address offset: 0x154 */
+ __IO uint32_t SDSR; /*!< Address offset: 0x158 */
+ uint32_t RESERVED7[9];
+ __IO uint32_t IER; /*!< Address offset: 0x180 */
+ __IO uint32_t ISReg; /*!< Address offset: 0x184 */
+ __IO uint32_t ICR; /*!< Address offset: 0x188 */
+ uint32_t RESERVED8[29];
+ __IO uint32_t CSQCR; /*!< Address offset: 0x200 */
+ __IO uint32_t CSQCFGR1; /*!< Address offset: 0x204 */
+ __IO uint32_t CSQCFGR2; /*!< Address offset: 0x208 */
+ __IO uint32_t CSQCFGR3; /*!< Address offset: 0x20c */
+ __IO uint32_t CSQAR1; /*!< Address offset: 0x210 */
+ __IO uint32_t CSQAR2; /*!< Address offset: 0x214 */
+ uint32_t RESERVED9[2];
+ __IO uint32_t CSQIER; /*!< Address offset: 0x220 */
+ __IO uint32_t CSQISR; /*!< Address offset: 0x224 */
+ __IO uint32_t CSQICR; /*!< Address offset: 0x228 */
+ uint32_t RESERVED10;
+ __IO uint32_t CSQEMSR; /*!< Address offset: 0x230 */
+ uint32_t RESERVED11[7];
+ __IO uint32_t BCHIER; /*!< Address offset: 0x250 */
+ __IO uint32_t BCHISR; /*!< Address offset: 0x254 */
+ __IO uint32_t BCHICR; /*!< Address offset: 0x258 */
+ __IO uint32_t BCHSR; /*!< Address offset: 0x25c */
+ __IO uint32_t BCHPBR1; /*!< Address offset: 0x260 */
+ __IO uint32_t BCHPBR2; /*!< Address offset: 0x264 */
+ __IO uint32_t BCHPBR3; /*!< Address offset: 0x268 */
+ __IO uint32_t BCHPBR4; /*!< Address offset: 0x26c */
+ uint32_t RESERVED12[3];
+ __IO uint32_t BCHDSR0; /*!< Address offset: 0x27c */
+ __IO uint32_t BCHDSR1; /*!< Address offset: 0x280 */
+ __IO uint32_t BCHDSR2; /*!< Address offset: 0x284 */
+ __IO uint32_t BCHDSR3; /*!< Address offset: 0x288 */
+ __IO uint32_t BCHDSR4; /*!< Address offset: 0x28c */
+ uint32_t RESERVED13[347];
+ __IO uint32_t HWCFGR2; /*!< Address offset: 0x3ec */
+ __IO uint32_t HWCFGR1; /*!< Address offset: 0x3f0 */
+ __IO uint32_t VER; /*!< Address offset: 0x3f4 */
+ __IO uint32_t ID; /*!< Address offset: 0x3f8 */
+ __IO uint32_t SID; /*!< Address offset: 0x3fc */
+} FMC_TypeDef;
+
+#define __HAL_LOCK(__HANDLE__) \
+ do{ \
+ if((__HANDLE__)->Lock == HAL_LOCKED) \
+ { \
+ return HAL_BUSY; \
+ } \
+ else \
+ { \
+ (__HANDLE__)->Lock = HAL_LOCKED; \
+ } \
+ }while (0)
+
+ #define __HAL_UNLOCK(__HANDLE__) \
+ do{ \
+ (__HANDLE__)->Lock = HAL_UNLOCKED; \
+ }while (0)
+
+#endif /*__STM32_HAL_H*/
diff --git a/include/drivers/st/stm32mp1xx_hal_uart.h b/include/drivers/st/stm32mp1xx_hal_uart.h
new file mode 100644
index 0000000..b6af232
--- /dev/null
+++ b/include/drivers/st/stm32mp1xx_hal_uart.h
@@ -0,0 +1,1586 @@
+/**
+ ******************************************************************************
+ * @file stm32mp1xx_hal_uart.h
+ * @author MCD Application Team
+ * @version V0.3.0
+ * @date 14-January-2015
+ * @brief Header file of UART HAL module.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32MP1xx_HAL_UART_H
+#define __STM32MP1xx_HAL_UART_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define HAL_UART_MODULE_ENABLED
+
+/* Includes ------------------------------------------------------------------*/
+#include <stm32mp1xx_hal.h>
+#include <stm32_uart_regs.h>
+
+/**
+ * @brief UART Init Structure definition
+ */
+typedef struct
+{
+ uint32_t BaudRate; /*!< This member configures the UART communication baud rate.
+ The baud rate register is computed using the following formula:
+ - If oversampling is 16 or in LIN mode,
+ Baud Rate Register = ((PCLKx) / ((huart->Init.BaudRate)))
+ - If oversampling is 8,
+ Baud Rate Register[15:4] = ((2 * PCLKx) / ((huart->Init.BaudRate)))[15:4]
+ Baud Rate Register[3] = 0
+ Baud Rate Register[2:0] = (((2 * PCLKx) / ((huart->Init.BaudRate)))[3:0]) >> 1 */
+
+ uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.
+ This parameter can be a value of @ref UARTEx_Word_Length. */
+
+ uint32_t StopBits; /*!< Specifies the number of stop bits transmitted.
+ This parameter can be a value of @ref UART_Stop_Bits. */
+
+ uint32_t Parity; /*!< Specifies the parity mode.
+ This parameter can be a value of @ref UART_Parity
+ @note When parity is enabled, the computed parity is inserted
+ at the MSB position of the transmitted data (9th bit when
+ the word length is set to 9 data bits; 8th bit when the
+ word length is set to 8 data bits). */
+
+ uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
+ This parameter can be a value of @ref UART_Mode. */
+
+ uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled
+ or disabled.
+ This parameter can be a value of @ref UART_Hardware_Flow_Control. */
+
+ uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to f_PCLK/8).
+ This parameter can be a value of @ref UART_Over_Sampling. */
+
+ uint32_t OneBitSampling; /*!< Specifies whether a single sample or three samples' majority vote is selected.
+ Selecting the single sample method increases the receiver tolerance to clock
+ deviations. This parameter can be a value of @ref UART_OneBit_Sampling. */
+
+ uint32_t Prescaler; /*!< Specifies the prescaler value used to divide the UART clock source.
+ This parameter can be a value of @ref UART_Prescaler. */
+
+ uint32_t FIFOMode; /*!< Specifies if the FIFO mode will be used. This parameter can be a value
+ of @ref UART_FIFO_mode. */
+
+ uint32_t TXFIFOThreshold; /*!< Specifies the TXFIFO threshold level.
+ This parameter can be a value of @ref UART_TXFIFO_threshold_level. */
+
+ uint32_t RXFIFOThreshold; /*!< Specifies the RXFIFO threshold level.
+ This parameter can be a value of @ref UART_RXFIFO_threshold_level. */
+
+} UART_InitTypeDef;
+
+/**
+ * @brief UART Advanced Features initalization structure definition
+ */
+typedef struct
+{
+ uint32_t AdvFeatureInit; /*!< Specifies which advanced UART features is initialized. Several
+ Advanced Features may be initialized at the same time .
+ This parameter can be a value of @ref UART_Advanced_Features_Initialization_Type. */
+
+ uint32_t TxPinLevelInvert; /*!< Specifies whether the TX pin active level is inverted.
+ This parameter can be a value of @ref UART_Tx_Inv. */
+
+ uint32_t RxPinLevelInvert; /*!< Specifies whether the RX pin active level is inverted.
+ This parameter can be a value of @ref UART_Rx_Inv. */
+
+ uint32_t DataInvert; /*!< Specifies whether data are inverted (positive/direct logic
+ vs negative/inverted logic).
+ This parameter can be a value of @ref UART_Data_Inv. */
+
+ uint32_t Swap; /*!< Specifies whether TX and RX pins are swapped.
+ This parameter can be a value of @ref UART_Rx_Tx_Swap. */
+
+ uint32_t OverrunDisable; /*!< Specifies whether the reception overrun detection is disabled.
+ This parameter can be a value of @ref UART_Overrun_Disable. */
+
+ uint32_t DMADisableonRxError; /*!< Specifies whether the DMA is disabled in case of reception error.
+ This parameter can be a value of @ref UART_DMA_Disable_on_Rx_Error. */
+
+ uint32_t AutoBaudRateEnable; /*!< Specifies whether auto Baud rate detection is enabled.
+ This parameter can be a value of @ref UART_AutoBaudRate_Enable */
+
+ uint32_t AutoBaudRateMode; /*!< If auto Baud rate detection is enabled, specifies how the rate
+ detection is carried out.
+ This parameter can be a value of @ref UART_AutoBaud_Rate_Mode. */
+
+ uint32_t MSBFirst; /*!< Specifies whether MSB is sent first on UART line.
+ This parameter can be a value of @ref UART_MSB_First. */
+} UART_AdvFeatureInitTypeDef;
+
+
+
+/**
+ * @brief HAL UART State structures definition
+ * @note HAL UART State value is a combination of 2 different substates: gState and RxState.
+ * - gState contains UART state information related to global Handle management
+ * and also information related to Tx operations.
+ * gState value coding follow below described bitmap :
+ * b7-b6 Error information
+ * 00 : No Error
+ * 01 : (Not Used)
+ * 10 : Timeout
+ * 11 : Error
+ * b5 IP initilisation status
+ * 0 : Reset (IP not initialized)
+ * 1 : Init done (IP not initialized. HAL UART Init function already called)
+ * b4-b3 (not used)
+ * xx : Should be set to 00
+ * b2 Intrinsic process state
+ * 0 : Ready
+ * 1 : Busy (IP busy with some configuration or internal operations)
+ * b1 (not used)
+ * x : Should be set to 0
+ * b0 Tx state
+ * 0 : Ready (no Tx operation ongoing)
+ * 1 : Busy (Tx operation ongoing)
+ * - RxState contains information related to Rx operations.
+ * RxState value coding follow below described bitmap :
+ * b7-b6 (not used)
+ * xx : Should be set to 00
+ * b5 IP initilisation status
+ * 0 : Reset (IP not initialized)
+ * 1 : Init done (IP not initialized)
+ * b4-b2 (not used)
+ * xxx : Should be set to 000
+ * b1 Rx state
+ * 0 : Ready (no Rx operation ongoing)
+ * 1 : Busy (Rx operation ongoing)
+ * b0 (not used)
+ * x : Should be set to 0.
+ */
+typedef enum {
+ HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not initialized
+ Value is allowed for gState and RxState */
+ HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use
+ Value is allowed for gState and RxState */
+ HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing
+ Value is allowed for gState only */
+ HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing
+ Value is allowed for gState only */
+ HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing
+ Value is allowed for RxState only */
+ HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing
+ Not to be used for neither gState nor RxState.
+ Value is result of combination (Or) between gState and RxState values */
+ HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state
+ Value is allowed for gState only */
+ HAL_UART_STATE_ERROR = 0xE0U /*!< Error
+ Value is allowed for gState only */
+} HAL_UART_StateTypeDef;
+
+/**
+ * @brief HAL UART Error Code structure definition
+ */
+typedef enum
+{
+ HAL_UART_ERROR_NONE = 0x00U, /*!< No error */
+ HAL_UART_ERROR_PE = 0x01U, /*!< Parity error */
+ HAL_UART_ERROR_NE = 0x02U, /*!< Noise error */
+ HAL_UART_ERROR_FE = 0x04U, /*!< frame error */
+ HAL_UART_ERROR_ORE = 0x08U, /*!< Overrun error */
+ HAL_UART_ERROR_DMA = 0x10U /*!< DMA transfer error */
+} HAL_UART_ErrorTypeDef;
+
+/**
+ * @brief UART clock sources definition
+ */
+typedef enum {
+ UART_CLOCKSOURCE_PCLK1 = 0x00U, /*!< PCLK1 clock source */
+ UART_CLOCKSOURCE_PCLK2 = 0x01U, /*!< PCLK2 clock source */
+ UART_CLOCKSOURCE_PCLK5 = 0x02U, /*!< PCLK5 clock source (only used by UART1) */
+ UART_CLOCKSOURCE_PLL3Q = 0x04U, /*!< PLL3Q clock source (only used by UART1) */
+ UART_CLOCKSOURCE_PLL4Q = 0x08U, /*!< PLL4Q clock source */
+ UART_CLOCKSOURCE_HSI = 0x10U, /*!< HSI clock source */
+ UART_CLOCKSOURCE_CSI = 0x20U, /*!< CSI clock source */
+ UART_CLOCKSOURCE_HSE = 0x40U, /*!< HSE clock source */
+ UART_CLOCKSOURCE_UNDEFINED = 0x80U /*!< Undefined clock source */
+} UART_ClockSourceTypeDef;
+
+/**
+ * @brief UART handle Structure definition
+ */
+typedef struct {
+ USART_TypeDef *Instance; /*!< UART registers base address */
+
+ UART_InitTypeDef Init; /*!< UART communication parameters */
+
+ UART_AdvFeatureInitTypeDef AdvancedInit; /*!< UART Advanced Features initialization parameters */
+
+ uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */
+
+ uint16_t TxXferSize; /*!< UART Tx Transfer size */
+
+ __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */
+
+ uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */
+
+ uint16_t RxXferSize; /*!< UART Rx Transfer size */
+
+ __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */
+
+ uint16_t Mask; /*!< UART Rx RDR register mask */
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */
+
+ DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */
+#endif
+#if defined(HAL_MDMA_MODULE_ENABLED)
+ MDMA_HandleTypeDef *hmdmatx; /*!< UART Tx MDMA Handle parameters */
+
+ MDMA_HandleTypeDef *hmdmarx; /*!< UART Rx MDMA Handle parameters */
+#endif /* HAL_MDMA_MODULE_ENABLED */
+
+ HAL_LockTypeDef Lock; /*!< Locking object */
+
+ __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management
+ and also related to Tx operations.
+ This parameter can be a value of @ref HAL_UART_StateTypeDef */
+
+ __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations.
+ This parameter can be a value of @ref HAL_UART_StateTypeDef */
+
+ __IO uint32_t ErrorCode; /*!< UART Error code */
+
+} UART_HandleTypeDef;
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup UART_Exported_Constants UART Exported Constants
+ * @{
+ */
+
+/** @defgroup UART_Stop_Bits UART Number of Stop Bits
+ * @{
+ */
+#define UART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< UART frame with 0.5 stop bit */
+#define UART_STOPBITS_1 ((uint32_t)0x00000000U) /*!< UART frame with 1 stop bit */
+#define UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< UART frame with 1.5 stop bits */
+#define UART_STOPBITS_2 USART_CR2_STOP_1 /*!< UART frame with 2 stop bits */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Parity UART Parity
+ * @{
+ */
+#define UART_PARITY_NONE ((uint32_t)0x00000000U) /*!< No parity */
+#define UART_PARITY_EVEN ((uint32_t)USART_CR1_PCE) /*!< Even parity */
+#define UART_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) /*!< Odd parity */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control
+ * @{
+ */
+#define UART_HWCONTROL_NONE ((uint32_t)0x00000000U) /*!< No hardware control */
+#define UART_HWCONTROL_RTS ((uint32_t)USART_CR3_RTSE) /*!< Request To Send */
+#define UART_HWCONTROL_CTS ((uint32_t)USART_CR3_CTSE) /*!< Clear To Send */
+#define UART_HWCONTROL_RTS_CTS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE)) /*!< Request and Clear To Send */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Mode UART Transfer Mode
+ * @{
+ */
+#define UART_MODE_RX ((uint32_t)USART_CR1_RE) /*!< RX mode */
+#define UART_MODE_TX ((uint32_t)USART_CR1_TE) /*!< TX mode */
+#define UART_MODE_TX_RX ((uint32_t)(USART_CR1_TE | USART_CR1_RE)) /*!< RX and TX mode */
+/**
+ * @}
+ */
+
+/** @defgroup UART_State UART State
+ * @{
+ */
+#define UART_STATE_DISABLE ((uint32_t)0x00000000U) /*!< UART disabled */
+#define UART_STATE_ENABLE ((uint32_t)USART_CR1_UE) /*!< UART enabled */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Over_Sampling UART Over Sampling
+ * @{
+ */
+#define UART_OVERSAMPLING_16 ((uint32_t)0x00000000U) /*!< Oversampling by 16 */
+#define UART_OVERSAMPLING_8 ((uint32_t)USART_CR1_OVER8) /*!< Oversampling by 8 */
+/**
+ * @}
+ */
+
+/** @defgroup UART_OneBit_Sampling UART One Bit Sampling Method
+ * @{
+ */
+#define UART_ONE_BIT_SAMPLE_DISABLE ((uint32_t)0x00000000U) /*!< One-bit sampling disable */
+#define UART_ONE_BIT_SAMPLE_ENABLE ((uint32_t)USART_CR3_ONEBIT) /*!< One-bit sampling enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Prescaler UART Prescaler
+ * @{
+ */
+#define UART_PRESCALER_DIV1 ((uint32_t)0x00000000U) /*!< UART clock /1 */
+#define UART_PRESCALER_DIV2 ((uint32_t)0x00000001U) /*!< UART clock /2 */
+#define UART_PRESCALER_DIV4 ((uint32_t)0x00000002U) /*!< UART clock /4 */
+#define UART_PRESCALER_DIV6 ((uint32_t)0x00000003U) /*!< UART clock /6 */
+#define UART_PRESCALER_DIV8 ((uint32_t)0x00000004U) /*!< UART clock /8 */
+#define UART_PRESCALER_DIV10 ((uint32_t)0x00000005U) /*!< UART clock /10 */
+#define UART_PRESCALER_DIV12 ((uint32_t)0x00000006U) /*!< UART clock /12 */
+#define UART_PRESCALER_DIV16 ((uint32_t)0x00000007U) /*!< UART clock /16 */
+#define UART_PRESCALER_DIV32 ((uint32_t)0x00000008U) /*!< UART clock /32 */
+#define UART_PRESCALER_DIV64 ((uint32_t)0x00000009U) /*!< UART clock /64 */
+#define UART_PRESCALER_DIV128 ((uint32_t)0x0000000AU) /*!< UART clock /128 */
+#define UART_PRESCALER_DIV256 ((uint32_t)0x0000000BU) /*!< UART clock /256 */
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_FIFO_mode UART FIFO mode
+ * @brief UART FIFO mode
+ * @{
+ */
+#define UART_FIFOMODE_DISABLE ((uint32_t)0x00000000U) /*!< FIFO mode disable */
+#define UART_FIFOMODE_ENABLE ((uint32_t)USART_CR1_FIFOEN) /*!< FIFO mode enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_TXFIFO_threshold_level UART TXFIFO threshold level
+ * @brief UART TXFIFO level
+ * @{
+ */
+#define UART_TXFIFO_THRESHOLD_1EIGHTHFULL ((uint32_t)0x00000000U) /*!< TXFIFO reaches 1/8 of its depth */
+#define UART_TXFIFO_THRESHOLD_1QUARTERFULL ((uint32_t)USART_CR3_TXFTCFG_0) /*!< TXFIFO reaches 1/4 of its depth */
+#define UART_TXFIFO_THRESHOLD_HALFFULL ((uint32_t)USART_CR3_TXFTCFG_1) /*!< TXFIFO reaches 1/2 of its depth */
+#define UART_TXFIFO_THRESHOLD_3QUARTERSFULL ((uint32_t)(USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1)) /*!< TXFIFO reaches 3/4 of its depth */
+#define UART_TXFIFO_THRESHOLD_7EIGHTHFULL ((uint32_t)USART_CR3_TXFTCFG_2) /*!< TXFIFO reaches 7/8 of its depth */
+#define UART_TXFIFO_THRESHOLD_EMPTY ((uint32_t)(USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0)) /*!< TXFIFO becomes empty */
+/**
+ * @}
+ */
+
+/** @defgroup UART_RXFIFO_threshold_level UART RXFIFO threshold level
+ * @brief UART RXFIFO level
+ * @{
+ */
+#define UART_RXFIFO_THRESHOLD_1EIGHTHFULL ((uint32_t)0x00000000U) /*!< RXFIFO reaches 1/8 of its depth */
+#define UART_RXFIFO_THRESHOLD_1QUARTERFULL ((uint32_t)USART_CR3_RXFTCFG_0) /*!< RXFIFO reaches 1/4 of its depth */
+#define UART_RXFIFO_THRESHOLD_HALFFULL ((uint32_t)USART_CR3_RXFTCFG_1) /*!< RXFIFO reaches 1/2 of its depth */
+#define UART_RXFIFO_THRESHOLD_3QUARTERSFULL ((uint32_t)(USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1)) /*!< RXFIFO reaches 3/4 of its depth */
+#define UART_RXFIFO_THRESHOLD_7EIGHTHFULL ((uint32_t)USART_CR3_RXFTCFG_2) /*!< RXFIFO reaches 7/8 of its depth */
+#define UART_RXFIFO_THRESHOLD_FULL ((uint32_t)(USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0)) /*!< RXFIFO becomes full */
+/**
+ * @}
+ */
+
+/** @defgroup UART_AutoBaud_Rate_Mode UART Advanced Feature AutoBaud Rate Mode
+ * @{
+ */
+#define UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT ((uint32_t)0x00000000U) /*!< Auto Baud rate detection on start bit */
+#define UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE ((uint32_t)USART_CR2_ABRMODE_0) /*!< Auto Baud rate detection on falling edge */
+#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME ((uint32_t)USART_CR2_ABRMODE_1) /*!< Auto Baud rate detection on 0x7F frame detection */
+#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME ((uint32_t)USART_CR2_ABRMODE) /*!< Auto Baud rate detection on 0x55 frame detection */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Receiver_TimeOut UART Receiver TimeOut
+ * @{
+ */
+#define UART_RECEIVER_TIMEOUT_DISABLE ((uint32_t)0x00000000U) /*!< UART receiver timeout disable */
+#define UART_RECEIVER_TIMEOUT_ENABLE ((uint32_t)USART_CR2_RTOEN) /*!< UART receiver timeout enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_LIN UART Local Interconnection Network mode
+ * @{
+ */
+#define UART_LIN_DISABLE ((uint32_t)0x00000000U) /*!< Local Interconnect Network disable */
+#define UART_LIN_ENABLE ((uint32_t)USART_CR2_LINEN) /*!< Local Interconnect Network enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_LIN_Break_Detection UART LIN Break Detection
+ * @{
+ */
+#define UART_LINBREAKDETECTLENGTH_10B ((uint32_t)0x00000000U) /*!< LIN 10-bit break detection length */
+#define UART_LINBREAKDETECTLENGTH_11B ((uint32_t)USART_CR2_LBDL) /*!< LIN 11-bit break detection length */
+/**
+ * @}
+ */
+
+/** @defgroup UART_DMA_Tx UART DMA Tx
+ * @{
+ */
+#define UART_DMA_TX_DISABLE ((uint32_t)0x00000000U) /*!< UART DMA TX disabled */
+#define UART_DMA_TX_ENABLE ((uint32_t)USART_CR3_DMAT) /*!< UART DMA TX enabled */
+/**
+ * @}
+ */
+
+/** @defgroup UART_DMA_Rx UART DMA Rx
+ * @{
+ */
+#define UART_DMA_RX_DISABLE ((uint32_t)0x00000000U) /*!< UART DMA RX disabled */
+#define UART_DMA_RX_ENABLE ((uint32_t)USART_CR3_DMAR) /*!< UART DMA RX enabled */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Half_Duplex_Selection UART Half Duplex Selection
+ * @{
+ */
+#define UART_HALF_DUPLEX_DISABLE ((uint32_t)0x00000000U) /*!< UART half-duplex disabled */
+#define UART_HALF_DUPLEX_ENABLE ((uint32_t)USART_CR3_HDSEL) /*!< UART half-duplex enabled */
+/**
+ * @}
+ */
+
+/** @defgroup UART_WakeUp_Methods UART WakeUp Methods
+ * @{
+ */
+#define UART_WAKEUPMETHOD_IDLELINE ((uint32_t)0x00000000U) /*!< UART wake-up on idle line */
+#define UART_WAKEUPMETHOD_ADDRESSMARK ((uint32_t)USART_CR1_WAKE) /*!< UART wake-up on address mark */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Request_Parameters UART Request Parameters
+ * @{
+ */
+#define UART_AUTOBAUD_REQUEST ((uint32_t)USART_RQR_ABRRQ) /*!< Auto-Baud Rate Request */
+#define UART_SENDBREAK_REQUEST ((uint32_t)USART_RQR_SBKRQ) /*!< Send Break Request */
+#define UART_MUTE_MODE_REQUEST ((uint32_t)USART_RQR_MMRQ) /*!< Mute Mode Request */
+#define UART_RXDATA_FLUSH_REQUEST ((uint32_t)USART_RQR_RXFRQ) /*!< Receive Data flush Request */
+#define UART_TXDATA_FLUSH_REQUEST ((uint32_t)USART_RQR_TXFRQ) /*!< Transmit data flush Request */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Advanced_Features_Initialization_Type UART Advanced Feature Initialization Type
+ * @{
+ */
+#define UART_ADVFEATURE_NO_INIT ((uint32_t)0x00000000U) /*!< No advanced feature initialization */
+#define UART_ADVFEATURE_TXINVERT_INIT ((uint32_t)0x00000001U) /*!< TX pin active level inversion */
+#define UART_ADVFEATURE_RXINVERT_INIT ((uint32_t)0x00000002U) /*!< RX pin active level inversion */
+#define UART_ADVFEATURE_DATAINVERT_INIT ((uint32_t)0x00000004U) /*!< Binary data inversion */
+#define UART_ADVFEATURE_SWAP_INIT ((uint32_t)0x00000008U) /*!< TX/RX pins swap */
+#define UART_ADVFEATURE_RXOVERRUNDISABLE_INIT ((uint32_t)0x00000010U) /*!< RX overrun disable */
+#define UART_ADVFEATURE_DMADISABLEONERROR_INIT ((uint32_t)0x00000020U) /*!< DMA disable on Reception Error */
+#define UART_ADVFEATURE_AUTOBAUDRATE_INIT ((uint32_t)0x00000040U) /*!< Auto Baud rate detection initialization */
+#define UART_ADVFEATURE_MSBFIRST_INIT ((uint32_t)0x00000080U) /*!< Most significant bit sent/received first */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Tx_Inv UART Advanced Feature TX Pin Active Level Inversion
+ * @{
+ */
+#define UART_ADVFEATURE_TXINV_DISABLE ((uint32_t)0x00000000U) /*!< TX pin active level inversion disable */
+#define UART_ADVFEATURE_TXINV_ENABLE ((uint32_t)USART_CR2_TXINV) /*!< TX pin active level inversion enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Rx_Inv UART Advanced Feature RX Pin Active Level Inversion
+ * @{
+ */
+#define UART_ADVFEATURE_RXINV_DISABLE ((uint32_t)0x00000000U) /*!< RX pin active level inversion disable */
+#define UART_ADVFEATURE_RXINV_ENABLE ((uint32_t)USART_CR2_RXINV) /*!< RX pin active level inversion enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Data_Inv UART Advanced Feature Binary Data Inversion
+ * @{
+ */
+#define UART_ADVFEATURE_DATAINV_DISABLE ((uint32_t)0x00000000U) /*!< Binary data inversion disable */
+#define UART_ADVFEATURE_DATAINV_ENABLE ((uint32_t)USART_CR2_DATAINV) /*!< Binary data inversion enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Rx_Tx_Swap UART Advanced Feature RX TX Pins Swap
+ * @{
+ */
+#define UART_ADVFEATURE_SWAP_DISABLE ((uint32_t)0x00000000U) /*!< TX/RX pins swap disable */
+#define UART_ADVFEATURE_SWAP_ENABLE ((uint32_t)USART_CR2_SWAP) /*!< TX/RX pins swap enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Overrun_Disable UART Advanced Feature Overrun Disable
+ * @{
+ */
+#define UART_ADVFEATURE_OVERRUN_ENABLE ((uint32_t)0x00000000U) /*!< RX overrun enable */
+#define UART_ADVFEATURE_OVERRUN_DISABLE ((uint32_t)USART_CR3_OVRDIS) /*!< RX overrun disable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_AutoBaudRate_Enable UART Advanced Feature Auto BaudRate Enable
+ * @{
+ */
+#define UART_ADVFEATURE_AUTOBAUDRATE_DISABLE ((uint32_t)0x00000000U) /*!< RX Auto Baud rate detection enable */
+#define UART_ADVFEATURE_AUTOBAUDRATE_ENABLE ((uint32_t)USART_CR2_ABREN) /*!< RX Auto Baud rate detection disable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_DMA_Disable_on_Rx_Error UART Advanced Feature DMA Disable On Rx Error
+ * @{
+ */
+#define UART_ADVFEATURE_DMA_ENABLEONRXERROR ((uint32_t)0x00000000U) /*!< DMA enable on Reception Error */
+#define UART_ADVFEATURE_DMA_DISABLEONRXERROR ((uint32_t)USART_CR3_DDRE) /*!< DMA disable on Reception Error */
+/**
+ * @}
+ */
+
+/** @defgroup UART_MSB_First UART Advanced Feature MSB First
+ * @{
+ */
+#define UART_ADVFEATURE_MSBFIRST_DISABLE ((uint32_t)0x00000000U) /*!< Most significant bit sent/received first disable */
+#define UART_ADVFEATURE_MSBFIRST_ENABLE ((uint32_t)USART_CR2_MSBFIRST) /*!< Most significant bit sent/received first enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Stop_Mode_Enable UART Advanced Feature Stop Mode Enable
+ * @{
+ */
+#define UART_ADVFEATURE_STOPMODE_DISABLE ((uint32_t)0x00000000U) /*!< UART stop mode disable */
+#define UART_ADVFEATURE_STOPMODE_ENABLE ((uint32_t)USART_CR1_UESM) /*!< UART stop mode enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Mute_Mode UART Advanced Feature Mute Mode Enable
+ * @{
+ */
+#define UART_ADVFEATURE_MUTEMODE_DISABLE ((uint32_t)0x00000000U) /*!< UART mute mode disable */
+#define UART_ADVFEATURE_MUTEMODE_ENABLE ((uint32_t)USART_CR1_MME) /*!< UART mute mode enable */
+/**
+ * @}
+ */
+
+/** @defgroup UART_CR2_ADDRESS_LSB_POS UART Address-matching LSB Position In CR2 Register
+ * @{
+ */
+#define UART_CR2_ADDRESS_LSB_POS ((uint32_t)24U) /*!< UART address-matching LSB position in CR2 register */
+/**
+ * @}
+ */
+
+/** @defgroup UART_WakeUp_from_Stop_Selection UART WakeUp From Stop Selection
+ * @{
+ */
+#define UART_WAKEUP_ON_ADDRESS ((uint32_t)0x00000000U) /*!< UART wake-up on address */
+#define UART_WAKEUP_ON_STARTBIT ((uint32_t)USART_CR3_WUS_1) /*!< UART wake-up on start bit */
+#define UART_WAKEUP_ON_READDATA_NONEMPTY ((uint32_t)USART_CR3_WUS) /*!< UART wake-up on receive data register not empty */
+#define UART_WAKEUP_ON_RXFIFO_THRESHOLD ((uint32_t)USART_CR3_RXFTIE) /*!< UART wake-up when the RXFIFO reaches threshold */
+#define UART_WAKEUP_ON_RXFIFO_FULL ((uint32_t)USART_CR1_RXFFIE) /*!< UART wake-up when the RXFIFO is full */
+#define UART_WAKEUP_ON_TXFIFO_THRESHOLD ((uint32_t)USART_CR3_TXFTIE) /*!< UART wake-up when the TXFIFO reaches threshold */
+#define UART_WAKEUP_ON_TXFIFO_EMPTY ((uint32_t)USART_CR1_TXFEIE) /*!< UART wake-up when the TXFIFO is empty */
+/**
+ * @}
+ */
+
+/** @defgroup UART_DriverEnable_Polarity UART DriverEnable Polarity
+ * @{
+ */
+#define UART_DE_POLARITY_HIGH ((uint32_t)0x00000000U) /*!< Driver enable signal is active high */
+#define UART_DE_POLARITY_LOW ((uint32_t)USART_CR3_DEP) /*!< Driver enable signal is active low */
+/**
+ * @}
+ */
+
+/** @defgroup UART_CR1_DEAT_ADDRESS_LSB_POS UART Driver Enable Assertion Time LSB Position In CR1 Register
+ * @{
+ */
+#define UART_CR1_DEAT_ADDRESS_LSB_POS ((uint32_t)21U) /*!< UART Driver Enable assertion time LSB position in CR1 register */
+/**
+ * @}
+ */
+
+/** @defgroup UART_CR1_DEDT_ADDRESS_LSB_POS UART Driver Enable DeAssertion Time LSB Position In CR1 Register
+ * @{
+ */
+#define UART_CR1_DEDT_ADDRESS_LSB_POS ((uint32_t)16U) /*!< UART Driver Enable de-assertion time LSB position in CR1 register */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Interruption_Mask UART Interruptions Flag Mask
+ * @{
+ */
+#define UART_IT_MASK ((uint32_t)0x001FU) /*!< UART interruptions flags mask */
+/**
+ * @}
+ */
+
+/** @defgroup UART_TimeOut_Value UART polling-based communications time-out value
+ * @{
+ */
+#define HAL_UART_TIMEOUT_VALUE 0x1FFFFFFU /*!< UART polling-based communications time-out value */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Flags UART Status Flags
+ * Elements values convention: 0xXXXX
+ * - 0xXXXX : Flag mask in the ISR register
+ * @{
+ */
+#define UART_FLAG_TXFT USART_ISR_TXFT /*!< UART TXFIFO threshold flag */
+#define UART_FLAG_RXFT USART_ISR_RXFT /*!< UART RXFIFO threshold flag */
+#define UART_FLAG_RXFF USART_ISR_RXFF /*!< UART RXFIFO Full flag */
+#define UART_FLAG_TXFE USART_ISR_TXFE /*!< UART TXFIFO Empty flag */
+#define UART_FLAG_REACK USART_ISR_REACK /*!< UART receive enable acknowledge flag */
+#define UART_FLAG_TEACK USART_ISR_TEACK /*!< UART transmit enable acknowledge flag */
+#define UART_FLAG_WUF USART_ISR_WUF /*!< UART wake-up from stop mode flag */
+#define UART_FLAG_RWU USART_ISR_RWU /*!< UART receiver wake-up from mute mode flag */
+#define UART_FLAG_SBKF USART_ISR_SBKF /*!< UART send break flag */
+#define UART_FLAG_CMF USART_ISR_CMF /*!< UART character match flag */
+#define UART_FLAG_BUSY USART_ISR_BUSY /*!< UART busy flag */
+#define UART_FLAG_ABRF USART_ISR_ABRF /*!< UART auto Baud rate flag */
+#define UART_FLAG_ABRE USART_ISR_ABRE /*!< UART uto Baud rate error */
+#define UART_FLAG_RTOF USART_ISR_RTOF /*!< UART receiver timeout flag */
+#define UART_FLAG_CTS USART_ISR_CTS /*!< UART clear to send flag */
+#define UART_FLAG_CTSIF USART_ISR_CTSIF /*!< UART clear to send interrupt flag */
+#define UART_FLAG_LBDF USART_ISR_LBDF /*!< UART LIN break detection flag */
+#define UART_FLAG_TXE USART_ISR_TXE /*!< UART transmit data register empty */
+#define UART_FLAG_TXFNF USART_ISR_TXE /*!< UART TXFIFO not full */
+#define UART_FLAG_TC USART_ISR_TC /*!< UART transmission complete */
+#define UART_FLAG_RXNE USART_ISR_RXNE /*!< UART read data register not empty */
+#define UART_FLAG_RXFNE USART_ISR_RXNE /*!< UART RXFIFO not empty */
+#define UART_FLAG_IDLE USART_ISR_IDLE /*!< UART idle flag */
+#define UART_FLAG_ORE USART_ISR_ORE /*!< UART overrun error */
+#define UART_FLAG_NE USART_ISR_NE /*!< UART noise error */
+#define UART_FLAG_FE USART_ISR_FE /*!< UART frame error */
+#define UART_FLAG_PE USART_ISR_PE /*!< UART parity error */
+/**
+ * @}
+ */
+
+/** @defgroup UART_Interrupt_definition UART Interrupts Definition
+ * Elements values convention: 000ZZZZZ0XXYYYYYb
+ * - YYYYY : Interrupt source position in the XX register (5bits)
+ * - XX : Interrupt source register (2bits)
+ * - 01: CR1 register
+ * - 10: CR2 register
+ * - 11: CR3 register
+ * - ZZZZZ : Flag position in the ISR register(5bits)
+ * @{
+ */
+#define UART_IT_PE ((uint32_t)0x0028U) /*!< UART parity error interruption */
+#define UART_IT_TXE ((uint32_t)0x0727U) /*!< UART transmit data register empty interruption */
+#define UART_IT_TC ((uint32_t)0x0626U) /*!< UART transmission complete interruption */
+#define UART_IT_RXNE ((uint32_t)0x0525U) /*!< UART read data register not empty interruption */
+#define UART_IT_LBD ((uint32_t)0x0846U) /*!< UART LIN break detection interruption */
+#define UART_IT_CTS ((uint32_t)0x096AU) /*!< UART CTS interruption */
+#define UART_IT_CM ((uint32_t)0x112EU) /*!< UART character match interruption */
+#define UART_IT_WUF ((uint32_t)0x1476U) /*!< UART wake-up from stop mode interruption */
+#define UART_IT_RXFF ((uint16_t)0x183FU)
+#define UART_IT_TXFE ((uint16_t)0x173EU)
+#define UART_IT_RXFT ((uint16_t)0x1A7CU)
+#define UART_IT_TXFT ((uint16_t)0x1B77U)
+
+
+/** Elements values convention: 000000000XXYYYYYb
+ * - YYYYY : Interrupt source position in the XX register (5bits)
+ * - XX : Interrupt source register (2bits)
+ * - 01: CR1 register
+ * - 10: CR2 register
+ * - 11: CR3 register
+ */
+#define UART_IT_ERR ((uint32_t)0x0060U) /*!< UART error interruption */
+
+/** Elements values convention: 0000ZZZZ00000000b
+ * - ZZZZ : Flag position in the ISR register(4bits)
+ */
+#define UART_IT_ORE ((uint32_t)0x0300U) /*!< UART overrun error interruption */
+#define UART_IT_NE ((uint32_t)0x0200U) /*!< UART noise error interruption */
+#define UART_IT_FE ((uint32_t)0x0100U) /*!< UART frame error interruption */
+/**
+ * @}
+ */
+
+/** @defgroup UART_IT_CLEAR_Flags UART Interruption Clear Flags
+ * @{
+ */
+#define UART_CLEAR_PEF USART_ICR_PECF /*!< Parity Error Clear Flag */
+#define UART_CLEAR_FEF USART_ICR_FECF /*!< Framing Error Clear Flag */
+#define UART_CLEAR_NEF USART_ICR_NCF /*!< Noise detected Clear Flag */
+#define UART_CLEAR_OREF USART_ICR_ORECF /*!< OverRun Error Clear Flag */
+#define UART_CLEAR_IDLEF USART_ICR_IDLECF /*!< IDLE line detected Clear Flag */
+#define UART_CLEAR_TXFECF USART_ICR_TXFECF /*!< TXFIFO empty clear flag */
+#define UART_CLEAR_TCF USART_ICR_TCCF /*!< Transmission Complete Clear Flag */
+#define UART_CLEAR_LBDF USART_ICR_LBDCF /*!< LIN Break Detection Clear Flag */
+#define UART_CLEAR_CTSF USART_ICR_CTSCF /*!< CTS Interrupt Clear Flag */
+#define UART_CLEAR_RTOF USART_ICR_RTOCF /*!< Receiver Time Out Clear Flag */
+#define UART_CLEAR_CMF USART_ICR_CMCF /*!< Character Match Clear Flag */
+#define UART_CLEAR_WUF USART_ICR_WUCF /*!< Wake Up from stop mode Clear Flag */
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup UART_Exported_Macros UART Exported Macros
+ * @{
+ */
+
+/** @brief Reset UART handle states.
+ * @param __HANDLE__: UART handle.
+ * @retval None
+ */
+#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) \
+ do { \
+ (__HANDLE__)->gState = HAL_UART_STATE_RESET; \
+ (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \
+ } while (0)
+
+/** @brief Flush the UART Data registers.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) \
+ do { \
+ SET_BIT((__HANDLE__)->Instance->RQR, \
+ UART_RXDATA_FLUSH_REQUEST); \
+ SET_BIT((__HANDLE__)->Instance->RQR, \
+ UART_TXDATA_FLUSH_REQUEST); \
+ } while (0)
+
+/** @brief Clear the specified UART pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __FLAG__: specifies the flag to check.
+ * This parameter can be any combination of the following values:
+ * @arg UART_FLAG_WUF: Wake up from stop mode flag
+ * @arg UART_FLAG_CMF: Character match flag
+ * @arg UART_FLAG_RTOF: Receiver timeout flag
+ * @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5)
+ * @arg UART_FLAG_LBD: LIN Break detection flag
+ * @arg UART_FLAG_TC: Transmission Complete flag
+ * @arg UART_FLAG_TXFE: TXFIFO Empty flag
+ * @arg UART_FLAG_IDLE: Idle Line detection flag
+ * @arg UART_FLAG_ORE: OverRun Error flag
+ * @arg UART_FLAG_NE: Noise Error flag
+ * @arg UART_FLAG_FE: Framing Error flag
+ * @arg UART_FLAG_PE: Parity Error flag
+ * @retval The new state of __FLAG__ (TRUE or FALSE).
+ */
+#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) \
+ ((__HANDLE__)->Instance->ICR = (__FLAG__))
+
+/** @brief Clear the UART PE pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_PEF)
+
+/** @brief Clear the UART FE pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_FEF)
+
+/** @brief Clear the UART NE pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_NEF)
+
+/** @brief Clear the UART ORE pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_OREF)
+
+/** @brief Clear the UART IDLE pending flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_IDLEF)
+
+/** @brief Clear the UART TX FIFO empty clear flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_TXFECF(__HANDLE__) \
+ __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_TXFECF)
+
+/** @brief Check whether the specified UART flag is set or not.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __FLAG__: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg UART_FLAG_TXFT: TXFIFO threshold flag
+ * @arg UART_FLAG_RXFT: RXFIFO threshold flag
+ * @arg UART_FLAG_RXFF: RXFIFO Full flag
+ * @arg UART_FLAG_TXFE: TXFIFO Empty flag
+ * @arg UART_FLAG_REACK: Receive enable acknowledge flag
+ * @arg UART_FLAG_TEACK: Transmit enable acknowledge flag
+ * @arg UART_FLAG_WUF: Wake up from stop mode flag
+ * @arg UART_FLAG_RWU: Receiver wake up flag (if the UART in mute mode)
+ * @arg UART_FLAG_SBKF: Send Break flag
+ * @arg UART_FLAG_CMF: Character match flag
+ * @arg UART_FLAG_BUSY: Busy flag
+ * @arg UART_FLAG_ABRF: Auto Baud rate detection flag
+ * @arg UART_FLAG_ABRE: Auto Baud rate detection error flag
+ * @arg UART_FLAG_RTOF: Receiver timeout flag
+ * @arg UART_FLAG_CTS: CTS Change flag
+ * @arg UART_FLAG_LBD: LIN Break detection flag
+ * @arg UART_FLAG_TXE: Transmit data register empty flag
+ * @arg UART_FLAG_TC: Transmission Complete flag
+ * @arg UART_FLAG_RXNE: Receive data register not empty flag
+ * @arg UART_FLAG_IDLE: Idle Line detection flag
+ * @arg UART_FLAG_ORE: OverRun Error flag
+ * @arg.UART_FLAG_NE: Noise Error flag
+ * @arg UART_FLAG_FE: Framing Error flag
+ * @arg UART_FLAG_PE: Parity Error flag
+ * @retval The new state of __FLAG__ (TRUE or FALSE).
+ */
+#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) \
+ (((__HANDLE__)->Instance->ISReg & (__FLAG__)) == (__FLAG__))
+
+/** @brief Enable the specified UART interrupt.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __INTERRUPT__: specifies the UART interrupt source to enable.
+ * This parameter can be one of the following values:
+ * @arg UART_IT_RXFF : RXFIFO Full interrupt
+ * @arg UART_IT_TXFE : TXFIFO Empty interrupt
+ * @arg UART_IT_RXFT : RXFIFO threshold interrupt
+ * @arg UART_IT_TXFT : TXFIFO threshold interrupt
+ * @arg UART_IT_WUF: Wakeup from stop mode interrupt
+ * @arg UART_IT_CM: Character match interrupt
+ * @arg UART_IT_CTS: CTS change interrupt
+ * @arg UART_IT_LBD: LIN Break detection interrupt
+ * @arg UART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg UART_IT_TC: Transmission complete interrupt
+ * @arg UART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg UART_IT_IDLE: Idle line detection interrupt
+ * @arg UART_IT_PE: Parity Error interrupt
+ * @arg UART_IT_ERR: Error interrupt (Frame error, noise error, overrun error)
+ * @retval None
+ */
+#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) \
+ (((((uint8_t)((__INTERRUPT__) & 0xFF)) >> 5U) == 1) ? \
+ ((__HANDLE__)->Instance->CR1 |= \
+ (1U << ((__INTERRUPT__) & UART_IT_MASK))) : \
+ ((((uint8_t)((__INTERRUPT__) & 0xFF)) >> 5U) == 2) ? \
+ ((__HANDLE__)->Instance->CR2 |= \
+ (1U << ((__INTERRUPT__) & UART_IT_MASK))) : \
+ ((__HANDLE__)->Instance->CR3 |= \
+ (1U << ((__INTERRUPT__) & UART_IT_MASK))))
+
+
+/** @brief Disable the specified UART interrupt.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __INTERRUPT__: specifies the UART interrupt source to disable.
+ * This parameter can be one of the following values:
+ * @arg UART_IT_RXFF : RXFIFO Full interrupt
+ * @arg UART_IT_TXFE : TXFIFO Empty interrupt
+ * @arg UART_IT_RXFT : RXFIFO threshold interrupt
+ * @arg UART_IT_TXFT : TXFIFO threshold interrupt
+ * @arg UART_IT_WUF: Wakeup from stop mode interrupt
+ * @arg UART_IT_CM: Character match interrupt
+ * @arg UART_IT_CTS: CTS change interrupt
+ * @arg UART_IT_LBD: LIN Break detection interrupt
+ * @arg UART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg UART_IT_TC: Transmission complete interrupt
+ * @arg UART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg UART_IT_IDLE: Idle line detection interrupt
+ * @arg UART_IT_PE: Parity Error interrupt
+ * @arg UART_IT_ERR: Error interrupt (Frame error, noise error, overrun error)
+ * @retval None
+ */
+#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) \
+ (((((uint8_t)((__INTERRUPT__) & 0xFF)) >> 5U) == 1) ? \
+ ((__HANDLE__)->Instance->CR1 &= \
+ ~(1U << ((__INTERRUPT__) & UART_IT_MASK))) : \
+ ((((uint8_t)((__INTERRUPT__) & 0xFF)) >> 5U) == 2) ? \
+ ((__HANDLE__)->Instance->CR2 &= \
+ ~(1U << ((__INTERRUPT__) & UART_IT_MASK))) : \
+ ((__HANDLE__)->Instance->CR3 &= \
+ ~(1U << ((__INTERRUPT__) & UART_IT_MASK))))
+
+/** @brief Check whether the specified UART interrupt has occurred or not.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __IT__: specifies the UART interrupt to check.
+ * This parameter can be one of the following values:
+ * @arg UART_IT_RXFF : RXFIFO Full interrupt
+ * @arg UART_IT_TXFE : TXFIFO Empty interrupt
+ * @arg UART_IT_RXFT : RXFIFO threshold interrupt
+ * @arg UART_IT_TXFT : TXFIFO threshold interrupt
+ * @arg UART_IT_WUF: Wakeup from stop mode interrupt
+ * @arg UART_IT_CM: Character match interrupt
+ * @arg UART_IT_CTS: CTS change interrupt
+ * @arg UART_IT_LBD: LIN Break detection interrupt
+ * @arg UART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg UART_IT_TC: Transmission complete interrupt
+ * @arg UART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg UART_IT_IDLE: Idle line detection interrupt
+ * @arg UART_IT_ORE: OverRun Error interrupt
+ * @arg UART_IT_NE: Noise Error interrupt
+ * @arg UART_IT_FE: Framing Error interrupt
+ * @arg UART_IT_PE: Parity Error interrupt
+ * @retval The new state of __IT__ (TRUE or FALSE).
+ */
+#define __HAL_UART_GET_IT(__HANDLE__, __IT__) \
+ ((__HANDLE__)->Instance->ISReg & ((uint32_t)1 << ((__IT__) >> 0x08)))
+
+/** @brief Check whether the specified UART interrupt source is enabled or not.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __IT__: specifies the UART interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg UART_IT_RXFF : RXFIFO Full interrupt
+ * @arg UART_IT_TXFE : TXFIFO Empty interrupt
+ * @arg UART_IT_RXFT : RXFIFO threshold interrupt
+ * @arg UART_IT_TXFT : TXFIFO threshold interrupt
+ * @arg UART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
+ * @arg UART_IT_LBD: LIN Break detection interrupt
+ * @arg UART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg UART_IT_TC: Transmission complete interrupt
+ * @arg UART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg UART_IT_IDLE: Idle line detection interrupt
+ * @arg UART_IT_ORE: OverRun Error interrupt
+ * @arg UART_IT_NE: Noise Error interrupt
+ * @arg UART_IT_FE: Framing Error interrupt
+ * @arg UART_IT_PE: Parity Error interrupt
+ * @retval The new state of __IT__ (TRUE or FALSE).
+ */
+#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __IT__) \
+ ((((((uint8_t)(__IT__)) >> 5U) == 1) ? \
+ (__HANDLE__)->Instance->CR1 : \
+ (((((uint8_t)(__IT__)) >> 5U) == 2) ? \
+ (__HANDLE__)->Instance->CR2 : \
+ (__HANDLE__)->Instance->CR3)) & \
+ ((uint32_t)1 << (((uint16_t)(__IT__)) & UART_IT_MASK)))
+
+/** @brief Clear the specified UART ISR flag, in setting the proper ICR register flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __IT_CLEAR__: specifies the interrupt clear register flag that needs to be set
+ * to clear the corresponding interrupt
+ * This parameter can be one of the following values:
+ * @arg UART_CLEAR_PEF: Parity Error Clear Flag
+ * @arg UART_CLEAR_FEF: Framing Error Clear Flag
+ * @arg UART_CLEAR_NEF: Noise detected Clear Flag
+ * @arg UART_CLEAR_OREF: OverRun Error Clear Flag
+ * @arg UART_CLEAR_IDLEF: IDLE line detected Clear Flag
+ * @arg UART_CLEAR_TCF: Transmission Complete Clear Flag
+ * @arg UART_CLEAR_LBDF: LIN Break Detection Clear Flag
+ * @arg UART_CLEAR_CTSF: CTS Interrupt Clear Flag
+ * @arg UART_CLEAR_RTOF: Receiver Time Out Clear Flag
+ * @arg UART_CLEAR_CMF: Character Match Clear Flag
+ * @arg UART_CLEAR_WUF: Wake Up from stop mode Clear Flag
+ * @arg UART_CLEAR_TXFECF: TXFIFO empty Clear Flag
+ * @retval None
+ */
+#define __HAL_UART_CLEAR_IT(__HANDLE__, __IT_CLEAR__) \
+ ((__HANDLE__)->Instance->ICR = (uint32_t)(__IT_CLEAR__))
+
+/** @brief Set a specific UART request flag.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @param __REQ__: specifies the request flag to set
+ * This parameter can be one of the following values:
+ * @arg UART_AUTOBAUD_REQUEST: Auto-Baud Rate Request
+ * @arg UART_SENDBREAK_REQUEST: Send Break Request
+ * @arg UART_MUTE_MODE_REQUEST: Mute Mode Request
+ * @arg UART_RXDATA_FLUSH_REQUEST: Receive Data flush Request
+ * @arg UART_TXDATA_FLUSH_REQUEST: Transmit data flush Request
+ * @retval None
+ */
+#define __HAL_UART_SEND_REQ(__HANDLE__, __REQ__) \
+ ((__HANDLE__)->Instance->RQR |= (uint32_t)(__REQ__))
+
+/** @brief Enable the UART one bit sample method.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR3 |= USART_CR3_ONEBIT)
+
+/** @brief Disable the UART one bit sample method.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_ONEBIT))
+
+/** @brief Enable UART.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_ENABLE(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE)
+
+/** @brief Disable UART.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_DISABLE(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE)
+
+/** @brief Enable TX UART
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_ENABLE_TX(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR1 |= USART_CR1_TE)
+
+/** @brief Disable TX UART
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_DISABLE_TX(__HANDLE__) \
+ ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_TE)
+
+/** @brief Enable CTS flow control
+ * This macro allows to enable CTS hardware flow control for a given UART instance,
+ * without need to call HAL_UART_Init() function.
+ * As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
+ * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need
+ * for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
+ * - UART instance should have already been initialised (through call of HAL_UART_Init() )
+ * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__))
+ * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)).
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \
+ do { \
+ SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \
+ (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \
+ } while (0)
+
+/** @brief Disable CTS flow control.
+ * @note This macro allows to disable CTS hardware flow control for a given UART instance,
+ * without need to call HAL_UART_Init() function.
+ * As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
+ * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need
+ * for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
+ * - UART instance should have already been initialised (through call of HAL_UART_Init() )
+ * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__))
+ * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)).
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \
+ do { \
+ CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \
+ (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \
+ } while (0)
+
+/** @brief Enable RTS flow control.
+ * @note This macro allows to enable RTS hardware flow control for a given UART instance,
+ * without need to call HAL_UART_Init() function.
+ * As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
+ * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need
+ * for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
+ * - UART instance should have already been initialised (through call of HAL_UART_Init() )
+ * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__))
+ * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)).
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \
+ do { \
+ SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \
+ (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \
+ } while (0)
+
+/** @brief Disable RTS flow control.
+ * @note This macro allows to disable RTS hardware flow control for a given UART instance,
+ * without need to call HAL_UART_Init() function.
+ * As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
+ * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need
+ * for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
+ * - UART instance should have already been initialised (through call of HAL_UART_Init() )
+ * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__))
+ * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)).
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None
+ */
+#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \
+ do { \
+ CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\
+ (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \
+ } while (0)
+
+/**
+ * @}
+ */
+
+/* Private variables -----------------------------------------------------*/
+/** @defgroup UART_Private_Variables UART Private Variables
+ * @{
+ */
+static const uint16_t presc_table[12] = {
+ 1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256
+};
+
+/** @brief BRR division operation to set BRR register in 8-bit oversampling
+ * mode.
+ * @param clockfreq: UART clock.
+ * @param baud_rate: Baud rate set by the user.
+ * @param prescaler: UART prescaler value.
+ * @retval Division result
+ */
+static inline uint32_t uart_div_sampling8(unsigned long clockfreq,
+ uint32_t baud_rate,
+ uint32_t prescaler)
+{
+ uint32_t scaled_freq = clockfreq / presc_table[prescaler];
+
+ return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate;
+
+}
+
+/** @brief BRR division operation to set BRR register in 16-bit oversampling
+ * mode.
+ * @param clockfreq: UART clock.
+ * @param baud_rate: Baud rate set by the user.
+ * @param prescaler: UART prescaler value.
+ * @retval Division result
+ */
+static inline uint32_t uart_div_sampling16(unsigned long clockfreq,
+ uint32_t baud_rate,
+ uint32_t prescaler)
+{
+ uint32_t scaled_freq = clockfreq / presc_table[prescaler];
+
+ return (scaled_freq + (baud_rate / 2)) / baud_rate;
+
+}
+
+/* Private macros --------------------------------------------------------*/
+/** @defgroup UART_Private_Macros UART Private Macros
+ * @{
+ */
+/** @brief Check UART Baud rate.
+ * @param __BAUDRATE__: Baudrate specified by the user.
+ * The maximum Baud Rate is derived from the maximum clock on MP1 (i.e. 100 MHz)
+ * divided by the smallest oversampling used on the USART (i.e. 8)
+ * @retval SET (__BAUDRATE__ is valid) or RESET (__BAUDRATE__ is invalid)
+ */
+#define IS_UART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) < 12500001U)
+
+/** @brief Check UART assertion time.
+ * @param __TIME__: 5-bit value assertion time.
+ * @retval Test result (TRUE or FALSE).
+ */
+#define IS_UART_ASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU)
+
+/** @brief Check UART deassertion time.
+ * @param __TIME__: 5-bit value deassertion time.
+ * @retval Test result (TRUE or FALSE).
+ */
+#define IS_UART_DEASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU)
+
+/**
+ * @brief Ensure that UART frame number of stop bits is valid.
+ * @param __STOPBITS__: UART frame number of stop bits.
+ * @retval SET (__STOPBITS__ is valid) or RESET (__STOPBITS__ is invalid)
+ */
+#define IS_UART_STOPBITS(__STOPBITS__) \
+ (((__STOPBITS__) == UART_STOPBITS_0_5) || \
+ ((__STOPBITS__) == UART_STOPBITS_1) || \
+ ((__STOPBITS__) == UART_STOPBITS_1_5) || \
+ ((__STOPBITS__) == UART_STOPBITS_2))
+
+/**
+ * @brief Ensure that UART frame parity is valid.
+ * @param __PARITY__: UART frame parity.
+ * @retval SET (__PARITY__ is valid) or RESET (__PARITY__ is invalid)
+ */
+#define IS_UART_PARITY(__PARITY__) \
+ (((__PARITY__) == UART_PARITY_NONE) || \
+ ((__PARITY__) == UART_PARITY_EVEN) || \
+ ((__PARITY__) == UART_PARITY_ODD))
+
+/**
+ * @brief Ensure that UART hardware flow control is valid.
+ * @param __CONTROL__: UART hardware flow control.
+ * @retval SET (__CONTROL__ is valid) or RESET (__CONTROL__ is invalid)
+ */
+#define IS_UART_HARDWARE_FLOW_CONTROL(__CONTROL__) \
+ (((__CONTROL__) == UART_HWCONTROL_NONE) || \
+ ((__CONTROL__) == UART_HWCONTROL_RTS) || \
+ ((__CONTROL__) == UART_HWCONTROL_CTS) || \
+ ((__CONTROL__) == UART_HWCONTROL_RTS_CTS))
+
+/**
+ * @brief Ensure that UART communication mode is valid.
+ * @param __MODE__: UART communication mode.
+ * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid)
+ */
+#define IS_UART_MODE(__MODE__) \
+ ((((__MODE__) & (~((uint32_t)(UART_MODE_TX_RX)))) == \
+ (uint32_t)0x00) && \
+ ((__MODE__) != (uint32_t)0x00))
+
+/**
+ * @brief Ensure that UART state is valid.
+ * @param __STATE__: UART state.
+ * @retval SET (__STATE__ is valid) or RESET (__STATE__ is invalid)
+ */
+#define IS_UART_STATE(__STATE__) (((__STATE__) == UART_STATE_DISABLE) || \
+ ((__STATE__) == UART_STATE_ENABLE))
+
+/**
+ * @brief Ensure that UART oversampling is valid.
+ * @param __SAMPLING__: UART oversampling.
+ * @retval SET (__SAMPLING__ is valid) or RESET (__SAMPLING__ is invalid)
+ */
+#define IS_UART_OVERSAMPLING(__SAMPLING__) \
+ (((__SAMPLING__) == UART_OVERSAMPLING_16) || \
+ ((__SAMPLING__) == UART_OVERSAMPLING_8))
+
+/**
+ * @brief Ensure that UART frame sampling is valid.
+ * @param __ONEBIT__: UART frame sampling.
+ * @retval SET (__ONEBIT__ is valid) or RESET (__ONEBIT__ is invalid)
+ */
+#define IS_UART_ONE_BIT_SAMPLE(__ONEBIT__) \
+ (((__ONEBIT__) == UART_ONE_BIT_SAMPLE_DISABLE) || \
+ ((__ONEBIT__) == UART_ONE_BIT_SAMPLE_ENABLE))
+
+/**
+ * @brief Ensure that UART auto Baud rate detection mode is valid.
+ * @param __MODE__: UART auto Baud rate detection mode.
+ * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(__MODE__) \
+ (((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT) || \
+ ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE) || \
+ ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME) || \
+ ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME))
+
+/**
+ * @brief Ensure that UART receiver timeout setting is valid.
+ * @param __TIMEOUT__: UART receiver timeout setting.
+ * @retval SET (__TIMEOUT__ is valid) or RESET (__TIMEOUT__ is invalid)
+ */
+#define IS_UART_RECEIVER_TIMEOUT(__TIMEOUT__) \
+ (((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_DISABLE) || \
+ ((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_ENABLE))
+
+/**
+ * @brief Ensure that UART LIN state is valid.
+ * @param __LIN__: UART LIN state.
+ * @retval SET (__LIN__ is valid) or RESET (__LIN__ is invalid)
+ */
+#define IS_UART_LIN(__LIN__) \
+ (((__LIN__) == UART_LIN_DISABLE) || \
+ ((__LIN__) == UART_LIN_ENABLE))
+
+/**
+ * @brief Ensure that UART LIN break detection length is valid.
+ * @param __LENGTH__: UART LIN break detection length.
+ * @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid)
+ */
+#define IS_UART_LIN_BREAK_DETECT_LENGTH(__LENGTH__) \
+ (((__LENGTH__) == UART_LINBREAKDETECTLENGTH_10B) || \
+ ((__LENGTH__) == UART_LINBREAKDETECTLENGTH_11B))
+
+/**
+ * @brief Ensure that UART DMA TX state is valid.
+ * @param __DMATX__: UART DMA TX state.
+ * @retval SET (__DMATX__ is valid) or RESET (__DMATX__ is invalid)
+ */
+#define IS_UART_DMA_TX(__DMATX__) \
+ (((__DMATX__) == UART_DMA_TX_DISABLE) || \
+ ((__DMATX__) == UART_DMA_TX_ENABLE))
+
+/**
+ * @brief Ensure that UART DMA RX state is valid.
+ * @param __DMARX__: UART DMA RX state.
+ * @retval SET (__DMARX__ is valid) or RESET (__DMARX__ is invalid)
+ */
+#define IS_UART_DMA_RX(__DMARX__) \
+ (((__DMARX__) == UART_DMA_RX_DISABLE) || \
+ ((__DMARX__) == UART_DMA_RX_ENABLE))
+
+/**
+ * @brief Ensure that UART half-duplex state is valid.
+ * @param __HDSEL__: UART half-duplex state.
+ * @retval SET (__HDSEL__ is valid) or RESET (__HDSEL__ is invalid)
+ */
+#define IS_UART_HALF_DUPLEX(__HDSEL__) \
+ (((__HDSEL__) == UART_HALF_DUPLEX_DISABLE) || \
+ ((__HDSEL__) == UART_HALF_DUPLEX_ENABLE))
+
+/**
+ * @brief Ensure that UART wake-up method is valid.
+ * @param __WAKEUP__: UART wake-up method .
+ * @retval SET (__WAKEUP__ is valid) or RESET (__WAKEUP__ is invalid)
+ */
+#define IS_UART_WAKEUPMETHOD(__WAKEUP__) \
+ (((__WAKEUP__) == UART_WAKEUPMETHOD_IDLELINE) || \
+ ((__WAKEUP__) == UART_WAKEUPMETHOD_ADDRESSMARK))
+
+/**
+ * @brief Ensure that UART request parameter is valid.
+ * @param __PARAM__: UART request parameter.
+ * @retval SET (__PARAM__ is valid) or RESET (__PARAM__ is invalid)
+ */
+#define IS_UART_REQUEST_PARAMETER(__PARAM__) \
+ (((__PARAM__) == UART_AUTOBAUD_REQUEST) || \
+ ((__PARAM__) == UART_SENDBREAK_REQUEST) || \
+ ((__PARAM__) == UART_MUTE_MODE_REQUEST) || \
+ ((__PARAM__) == UART_RXDATA_FLUSH_REQUEST) || \
+ ((__PARAM__) == UART_TXDATA_FLUSH_REQUEST))
+
+/**
+ * @brief Ensure that UART advanced features initialization is valid.
+ * @param __INIT__: UART advanced features initialization.
+ * @retval SET (__INIT__ is valid) or RESET (__INIT__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_INIT(__INIT__) \
+ ((__INIT__) <= (UART_ADVFEATURE_NO_INIT | \
+ UART_ADVFEATURE_TXINVERT_INIT | \
+ UART_ADVFEATURE_RXINVERT_INIT | \
+ UART_ADVFEATURE_DATAINVERT_INIT | \
+ UART_ADVFEATURE_SWAP_INIT | \
+ UART_ADVFEATURE_RXOVERRUNDISABLE_INIT | \
+ UART_ADVFEATURE_DMADISABLEONERROR_INIT | \
+ UART_ADVFEATURE_AUTOBAUDRATE_INIT | \
+ UART_ADVFEATURE_MSBFIRST_INIT))
+
+/**
+ * @brief Ensure that UART frame TX inversion setting is valid.
+ * @param __TXINV__: UART frame TX inversion setting.
+ * @retval SET (__TXINV__ is valid) or RESET (__TXINV__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_TXINV(__TXINV__) \
+ (((__TXINV__) == UART_ADVFEATURE_TXINV_DISABLE) || \
+ ((__TXINV__) == UART_ADVFEATURE_TXINV_ENABLE))
+
+/**
+ * @brief Ensure that UART frame RX inversion setting is valid.
+ * @param __RXINV__: UART frame RX inversion setting.
+ * @retval SET (__RXINV__ is valid) or RESET (__RXINV__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_RXINV(__RXINV__) \
+ (((__RXINV__) == UART_ADVFEATURE_RXINV_DISABLE) || \
+ ((__RXINV__) == UART_ADVFEATURE_RXINV_ENABLE))
+
+/**
+ * @brief Ensure that UART frame data inversion setting is valid.
+ * @param __DATAINV__: UART frame data inversion setting.
+ * @retval SET (__DATAINV__ is valid) or RESET (__DATAINV__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_DATAINV(__DATAINV__) \
+ (((__DATAINV__) == UART_ADVFEATURE_DATAINV_DISABLE) || \
+ ((__DATAINV__) == UART_ADVFEATURE_DATAINV_ENABLE))
+
+/**
+ * @brief Ensure that UART frame RX/TX pins swap setting is valid.
+ * @param __SWAP__: UART frame RX/TX pins swap setting.
+ * @retval SET (__SWAP__ is valid) or RESET (__SWAP__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_SWAP(__SWAP__) \
+ (((__SWAP__) == UART_ADVFEATURE_SWAP_DISABLE) || \
+ ((__SWAP__) == UART_ADVFEATURE_SWAP_ENABLE))
+
+/**
+ * @brief Ensure that UART frame overrun setting is valid.
+ * @param __OVERRUN__: UART frame overrun setting.
+ * @retval SET (__OVERRUN__ is valid) or RESET (__OVERRUN__ is invalid)
+ */
+#define IS_UART_OVERRUN(__OVERRUN__) \
+ (((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_ENABLE) || \
+ ((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_DISABLE))
+
+/**
+ * @brief Ensure that UART auto Baud rate state is valid.
+ * @param __AUTOBAUDRATE__: UART auto Baud rate state.
+ * @retval SET (__AUTOBAUDRATE__ is valid) or RESET (__AUTOBAUDRATE__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_AUTOBAUDRATE(__AUTOBAUDRATE__) \
+ (((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_DISABLE) || \
+ ((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE))
+
+/**
+ * @brief Ensure that UART DMA enabling or disabling on error setting is valid.
+ * @param __DMA__: UART DMA enabling or disabling on error setting.
+ * @retval SET (__DMA__ is valid) or RESET (__DMA__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_DMAONRXERROR(__DMA__) \
+ (((__DMA__) == UART_ADVFEATURE_DMA_ENABLEONRXERROR) || \
+ ((__DMA__) == UART_ADVFEATURE_DMA_DISABLEONRXERROR))
+
+/**
+ * @brief Ensure that UART frame MSB first setting is valid.
+ * @param __MSBFIRST__: UART frame MSB first setting.
+ * @retval SET (__MSBFIRST__ is valid) or RESET (__MSBFIRST__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_MSBFIRST(__MSBFIRST__) \
+ (((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_DISABLE) || \
+ ((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_ENABLE))
+
+/**
+ * @brief Ensure that UART stop mode state is valid.
+ * @param __STOPMODE__: UART stop mode state.
+ * @retval SET (__STOPMODE__ is valid) or RESET (__STOPMODE__ is invalid)
+ */
+#define IS_UART_ADVFEATURE_STOPMODE(__STOPMODE__) \
+ (((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_DISABLE) || \
+ ((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_ENABLE))
+
+/**
+ * @brief Ensure that UART mute mode state is valid.
+ * @param __MUTE__: UART mute mode state.
+ * @retval SET (__MUTE__ is valid) or RESET (__MUTE__ is invalid)
+ */
+#define IS_UART_MUTE_MODE(__MUTE__) \
+ (((__MUTE__) == UART_ADVFEATURE_MUTEMODE_DISABLE) || \
+ ((__MUTE__) == UART_ADVFEATURE_MUTEMODE_ENABLE))
+
+/**
+ * @brief Ensure that UART wake-up selection is valid.
+ * @param __WAKE__: UART wake-up selection.
+ * @retval SET (__WAKE__ is valid) or RESET (__WAKE__ is invalid)
+ */
+#define IS_UART_WAKEUP_SELECTION(__WAKE__) \
+ (((__WAKE__) == UART_WAKEUP_ON_ADDRESS) || \
+ ((__WAKE__) == UART_WAKEUP_ON_STARTBIT) || \
+ ((__WAKE__) == UART_WAKEUP_ON_READDATA_NONEMPTY) || \
+ ((__WAKE__) == UART_WAKEUP_ON_RXFIFO_THRESHOLD) || \
+ ((__WAKE__) == UART_WAKEUP_ON_RXFIFO_FULL) || \
+ ((__WAKE__) == UART_WAKEUP_ON_TXFIFO_THRESHOLD) || \
+ ((__WAKE__) == UART_WAKEUP_ON_TXFIFO_EMPTY))
+
+/**
+ * @brief Ensure that UART driver enable polarity is valid.
+ * @param __POLARITY__: UART driver enable polarity.
+ * @retval SET (__POLARITY__ is valid) or RESET (__POLARITY__ is invalid)
+ */
+#define IS_UART_DE_POLARITY(__POLARITY__) \
+ (((__POLARITY__) == UART_DE_POLARITY_HIGH) || \
+ ((__POLARITY__) == UART_DE_POLARITY_LOW))
+
+/**
+ * @brief Ensure that UART Prescaler is valid.
+ * @param __PRESCALER__: UART Prescaler value.
+ * @retval SET (__PRESCALER__ is valid) or RESET (__PRESCALER__ is invalid)
+ */
+#define IS_UART_PRESCALER(__PRESCALER__) \
+ (((__PRESCALER__) == UART_PRESCALER_DIV1) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV2) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV4) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV6) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV8) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV10) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV12) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV16) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV32) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV64) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV128) || \
+ ((__PRESCALER__) == UART_PRESCALER_DIV256))
+
+/**
+ * @brief Ensure that UART FIFO mode is valid.
+ * @param __STATE__: UART FIFO mode.
+ * @retval SET (__STATE__ is valid) or RESET (__STATE__ is invalid)
+ */
+#define IS_UART_FIFO_MODE_STATE(__STATE__) \
+ (((__STATE__) == UART_FIFOMODE_DISABLE) || \
+ ((__STATE__) == UART_FIFOMODE_ENABLE))
+
+/**
+ * @brief Ensure that UART TXFIFO threshold level is valid.
+ * @param __THRESHOLD__: UART TXFIFO threshold level.
+ * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid)
+ */
+#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) \
+ ((((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1EIGHTHFULL) || \
+ ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1QUARTERFULL) || \
+ ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_HALFFULL) || \
+ ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3QUARTERSFULL) || \
+ ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7EIGHTHFULL)) || \
+ ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_EMPTY))
+
+/**
+ * @brief Ensure that UART RXFIFO threshold level is valid.
+ * @param __THRESHOLD__: UART RXFIFO threshold level.
+ * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid)
+ */
+#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) \
+ ((((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1EIGHTHFULL) || \
+ ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1QUARTERFULL) || \
+ ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_HALFFULL) || \
+ ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3QUARTERSFULL) || \
+ ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7EIGHTHFULL)) || \
+ ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_FULL))
+
+/* Include UART HAL Extension module */
+#include "stm32mp1xx_hal_uart_ex.h"
+
+/* Initialization and de-initialization functions ****************************/
+HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
+
+/* IO operation functions *****************************************************/
+HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout);
+HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout);
+
+/* Peripheral State and Errors functions **************************************************/
+HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart);
+uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart);
+
+/* Private functions -----------------------------------------------------------*/
+/** @addtogroup UART_Private_Functions UART Private Functions
+ * @{
+ */
+
+HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart);
+HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart);
+HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart,
+ uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart,
+ uint32_t Timeout);
+void UART_AdvFeatureConfig(UART_HandleTypeDef *huart);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32MP1xx_HAL_UART_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/include/drivers/st/stm32mp1xx_hal_uart_ex.h b/include/drivers/st/stm32mp1xx_hal_uart_ex.h
new file mode 100644
index 0000000..193f870
--- /dev/null
+++ b/include/drivers/st/stm32mp1xx_hal_uart_ex.h
@@ -0,0 +1,87 @@
+/**
+ ******************************************************************************
+ * @file stm32mp1xx_hal_uart_ex.h
+ * @author MCD Application Team
+ * @version $VERSION$
+ * @date $DATE$
+ * @brief Header file of UART HAL Extended module.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015-2017 STMicroelectronics</center></h2>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32MP1xx_HAL_UART_EX_H
+#define __STM32MP1xx_HAL_UART_EX_H
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup UARTEx_Exported_Constants UARTEx Exported Constants
+ * @{
+ */
+
+/** @defgroup UARTEx_Word_Length UART Word Length
+ * @{
+ */
+#define UART_WORDLENGTH_7B ((uint32_t)USART_CR1_M1) /*!< 7-bit long UART frame */
+#define UART_WORDLENGTH_8B ((uint32_t)0x00000000U) /*!< 8-bit long UART frame */
+#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M0) /*!< 9-bit long UART frame */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup UARTEx_Private_Macros UARTEx Private Macros
+ * @{
+ */
+
+/** @brief Report the UART mask to apply to retrieve the received data
+ * according to the word length and to the parity bits activation.
+ * @note If PCE = 1, the parity bit is not included in the data extracted
+ * by the reception API().
+ * This masking operation is not carried out in the case of
+ * DMA transfers.
+ * @param __HANDLE__: specifies the UART Handle.
+ * @retval None, the mask to apply to UART RDR register is stored in (__HANDLE__)->Mask field.
+ */
+#define UART_MASK_COMPUTATION(__HANDLE__) \
+ do { \
+ if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_9B) \
+ { \
+ if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
+ { \
+ (__HANDLE__)->Mask = 0x01FF ; \
+ } \
+ else \
+ { \
+ (__HANDLE__)->Mask = 0x00FF ; \
+ } \
+ } \
+ else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_8B) \
+ { \
+ if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
+ { \
+ (__HANDLE__)->Mask = 0x00FF ; \
+ } \
+ else \
+ { \
+ (__HANDLE__)->Mask = 0x007F ; \
+ } \
+ } \
+ else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_7B) \
+ { \
+ if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
+ { \
+ (__HANDLE__)->Mask = 0x007F ; \
+ } \
+ else \
+ { \
+ (__HANDLE__)->Mask = 0x003F ; \
+ } \
+ } \
+} while(0)
+
+#endif /* __STM32MP1xx_HAL_UART_EX_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h
new file mode 100644
index 0000000..c77c0b5
--- /dev/null
+++ b/include/drivers/st/stm32mp_clkfunc.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_CLKFUNC_H
+#define STM32MP_CLKFUNC_H
+
+#include <libfdt.h>
+#include <stdbool.h>
+
+int fdt_get_rcc_node(void *fdt);
+uint32_t fdt_rcc_read_addr(void);
+int fdt_rcc_read_uint32_array(const char *prop_name,
+ uint32_t *array, uint32_t count);
+uint32_t fdt_rcc_read_uint32_default(const char *prop_name,
+ uint32_t dflt_value);
+int fdt_rcc_subnode_offset(const char *name);
+const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp);
+bool fdt_get_rcc_secure_status(void);
+
+uintptr_t fdt_get_stgen_base(void);
+int fdt_get_clock_id(int node);
+int fdt_get_clock_id_by_name(int node, const char *name);
+unsigned long fdt_get_uart_clock_freq(uintptr_t instance);
+
+#endif /* STM32MP_CLKFUNC_H */
diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h
new file mode 100644
index 0000000..39c80e4
--- /dev/null
+++ b/include/drivers/st/stm32mp_pmic.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_PMIC_H
+#define STM32MP_PMIC_H
+
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+int dt_pmic_status(void);
+int dt_pmic_configure_boot_on_regulators(void);
+int dt_pmic_set_lp_config(const char *node_name);
+bool initialize_pmic_i2c(void);
+void initialize_pmic(void);
+#if STM32MP1_DEBUG_ENABLE
+int pmic_keep_debug_unit(void);
+#endif
+int pmic_ddr_power_init(enum ddr_type ddr_type);
+
+#endif /* STM32MP_PMIC_H */
diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h
new file mode 100644
index 0000000..5bd159f
--- /dev/null
+++ b/include/drivers/st/stm32mp_reset.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_RESET_H
+#define STM32MP_RESET_H
+
+#include <stdint.h>
+
+void stm32mp_reset_assert(uint32_t reset_id);
+void stm32mp_reset_deassert(uint32_t reset_id);
+
+#endif /* STM32MP_RESET_H */
diff --git a/include/drivers/st/stpmic1.h b/include/drivers/st/stpmic1.h
new file mode 100644
index 0000000..803a69e
--- /dev/null
+++ b/include/drivers/st/stpmic1.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STPMIC1_H
+#define STPMIC1_H
+
+#include <stm32_i2c.h>
+#include <utils_def.h>
+
+#define TURN_ON_REG 0x1U
+#define TURN_OFF_REG 0x2U
+#define ICC_LDO_TURN_OFF_REG 0x3U
+#define ICC_BUCK_TURN_OFF_REG 0x4U
+#define RESET_STATUS_REG 0x5U
+#define VERSION_STATUS_REG 0x6U
+#define MAIN_CONTROL_REG 0x10U
+#define PADS_PULL_REG 0x11U
+#define BUCK_PULL_DOWN_REG 0x12U
+#define LDO14_PULL_DOWN_REG 0x13U
+#define LDO56_PULL_DOWN_REG 0x14U
+#define VIN_CONTROL_REG 0x15U
+#define PONKEY_TIMER_REG 0x16U
+#define MASK_RANK_BUCK_REG 0x17U
+#define MASK_RESET_BUCK_REG 0x18U
+#define MASK_RANK_LDO_REG 0x19U
+#define MASK_RESET_LDO_REG 0x1AU
+#define WATCHDOG_CONTROL_REG 0x1BU
+#define WATCHDOG_TIMER_REG 0x1CU
+#define BUCK_ICC_TURNOFF_REG 0x1DU
+#define LDO_ICC_TURNOFF_REG 0x1EU
+#define BUCK_APM_CONTROL_REG 0x1FU
+#define BUCK1_CONTROL_REG 0x20U
+#define BUCK2_CONTROL_REG 0x21U
+#define BUCK3_CONTROL_REG 0x22U
+#define BUCK4_CONTROL_REG 0x23U
+#define VREF_DDR_CONTROL_REG 0x24U
+#define LDO1_CONTROL_REG 0x25U
+#define LDO2_CONTROL_REG 0x26U
+#define LDO3_CONTROL_REG 0x27U
+#define LDO4_CONTROL_REG 0x28U
+#define LDO5_CONTROL_REG 0x29U
+#define LDO6_CONTROL_REG 0x2AU
+#define BUCK1_PWRCTRL_REG 0x30U
+#define BUCK2_PWRCTRL_REG 0x31U
+#define BUCK3_PWRCTRL_REG 0x32U
+#define BUCK4_PWRCTRL_REG 0x33U
+#define VREF_DDR_PWRCTRL_REG 0x34U
+#define LDO1_PWRCTRL_REG 0x35U
+#define LDO2_PWRCTRL_REG 0x36U
+#define LDO3_PWRCTRL_REG 0x37U
+#define LDO4_PWRCTRL_REG 0x38U
+#define LDO5_PWRCTRL_REG 0x39U
+#define LDO6_PWRCTRL_REG 0x3AU
+#define FREQUENCY_SPREADING_REG 0x3BU
+#define USB_CONTROL_REG 0x40U
+#define ITLATCH1_REG 0x50U
+#define ITLATCH2_REG 0x51U
+#define ITLATCH3_REG 0x52U
+#define ITLATCH4_REG 0x53U
+#define ITSETLATCH1_REG 0x60U
+#define ITSETLATCH2_REG 0x61U
+#define ITSETLATCH3_REG 0x62U
+#define ITSETLATCH4_REG 0x63U
+#define ITCLEARLATCH1_REG 0x70U
+#define ITCLEARLATCH2_REG 0x71U
+#define ITCLEARLATCH3_REG 0x72U
+#define ITCLEARLATCH4_REG 0x73U
+#define ITMASK1_REG 0x80U
+#define ITMASK2_REG 0x81U
+#define ITMASK3_REG 0x82U
+#define ITMASK4_REG 0x83U
+#define ITSETMASK1_REG 0x90U
+#define ITSETMASK2_REG 0x91U
+#define ITSETMASK3_REG 0x92U
+#define ITSETMASK4_REG 0x93U
+#define ITCLEARMASK1_REG 0xA0U
+#define ITCLEARMASK2_REG 0xA1U
+#define ITCLEARMASK3_REG 0xA2U
+#define ITCLEARMASK4_REG 0xA3U
+#define ITSOURCE1_REG 0xB0U
+#define ITSOURCE2_REG 0xB1U
+#define ITSOURCE3_REG 0xB2U
+#define ITSOURCE4_REG 0xB3U
+
+/* Registers masks */
+#define LDO_VOLTAGE_MASK 0x7CU
+#define BUCK_VOLTAGE_MASK 0xFCU
+#define LDO_BUCK_VOLTAGE_SHIFT 2
+#define LDO_BUCK_ENABLE_MASK 0x01U
+#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U
+#define LDO_BUCK_HPLP_SHIFT 1
+#define LDO_BUCK_RANK_MASK 0x01U
+#define LDO_BUCK_RESET_MASK 0x01U
+#define LDO_BUCK_PULL_DOWN_MASK 0x03U
+
+/* Pull down register */
+#define BUCK1_PULL_DOWN_SHIFT 0
+#define BUCK2_PULL_DOWN_SHIFT 2
+#define BUCK3_PULL_DOWN_SHIFT 4
+#define BUCK4_PULL_DOWN_SHIFT 6
+#define VREF_DDR_PULL_DOWN_SHIFT 4
+
+/* Buck Mask reset register */
+#define BUCK1_MASK_RESET 0
+#define BUCK2_MASK_RESET 1
+#define BUCK3_MASK_RESET 2
+#define BUCK4_MASK_RESET 3
+
+/* LDO Mask reset register */
+#define LDO1_MASK_RESET 0
+#define LDO2_MASK_RESET 1
+#define LDO3_MASK_RESET 2
+#define LDO4_MASK_RESET 3
+#define LDO5_MASK_RESET 4
+#define LDO6_MASK_RESET 5
+#define VREF_DDR_MASK_RESET 6
+
+/* Main PMIC Control Register (MAIN_CONTROL_REG) */
+#define ICC_EVENT_ENABLED BIT(4)
+#define PWRCTRL_POLARITY_HIGH BIT(3)
+#define PWRCTRL_PIN_VALID BIT(2)
+#define RESTART_REQUEST_ENABLED BIT(1)
+#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
+
+/* Main PMIC PADS Control Register (PADS_PULL_REG) */
+#define WAKEUP_DETECTOR_DISABLED BIT(4)
+#define PWRCTRL_PD_ACTIVE BIT(3)
+#define PWRCTRL_PU_ACTIVE BIT(2)
+#define WAKEUP_PD_ACTIVE BIT(1)
+#define PONKEY_PU_ACTIVE BIT(0)
+
+/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */
+#define SWIN_DETECTOR_ENABLED BIT(7)
+#define SWOUT_DETECTOR_ENABLED BIT(6)
+#define VINLOW_HYST_MASK 0x3
+#define VINLOW_HYST_SHIFT 4
+#define VINLOW_THRESHOLD_MASK 0x7
+#define VINLOW_THRESHOLD_SHIFT 1
+#define VINLOW_ENABLED 0x01
+#define VINLOW_CTRL_REG_MASK 0xFF
+
+/* USB Control Register */
+#define BOOST_OVP_DISABLED BIT(7)
+#define VBUS_OTG_DETECTION_DISABLED BIT(6)
+#define OCP_LIMIT_HIGH BIT(3)
+#define SWIN_SWOUT_ENABLED BIT(2)
+#define USBSW_OTG_SWITCH_ENABLED BIT(1)
+
+int stpmic1_powerctrl_on(void);
+int stpmic1_switch_off(void);
+int stpmic1_register_read(uint8_t register_id, uint8_t *value);
+int stpmic1_register_write(uint8_t register_id, uint8_t value);
+int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
+int stpmic1_regulator_enable(const char *name);
+int stpmic1_regulator_disable(const char *name);
+uint8_t stpmic1_is_regulator_enabled(const char *name);
+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts);
+int stpmic1_regulator_voltage_get(const char *name);
+int stpmic1_regulator_pull_down_set(const char *name);
+int stpmic1_regulator_mask_reset_set(const char *name);
+int stpmic1_lp_copy_reg(const char *name);
+int stpmic1_lp_reg_on_off(const char *name, uint8_t enable);
+int stpmic1_lp_set_mode(const char *name, uint8_t hplp);
+int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts);
+void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
+
+int stpmic1_get_version(unsigned long *version);
+void stpmic1_dump_regulators(void);
+
+#endif /* STPMIC1_H */
diff --git a/include/drivers/st/stpmu1.h b/include/drivers/st/stpmu1.h
deleted file mode 100644
index 1b93ab2..0000000
--- a/include/drivers/st/stpmu1.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-
-#ifndef __STPMU1_H__
-#define __STPMU1_H__
-
-#include <stm32_i2c.h>
-#include <utils_def.h>
-
-#define TURN_ON_REG 0x1U
-#define TURN_OFF_REG 0x2U
-#define ICC_LDO_TURN_OFF_REG 0x3U
-#define ICC_BUCK_TURN_OFF_REG 0x4U
-#define RESET_STATUS_REG 0x5U
-#define VERSION_STATUS_REG 0x6U
-#define MAIN_CONTROL_REG 0x10U
-#define PADS_PULL_REG 0x11U
-#define BUCK_PULL_DOWN_REG 0x12U
-#define LDO14_PULL_DOWN_REG 0x13U
-#define LDO56_PULL_DOWN_REG 0x14U
-#define VIN_CONTROL_REG 0x15U
-#define PONKEY_TIMER_REG 0x16U
-#define MASK_RANK_BUCK_REG 0x17U
-#define MASK_RESET_BUCK_REG 0x18U
-#define MASK_RANK_LDO_REG 0x19U
-#define MASK_RESET_LDO_REG 0x1AU
-#define WATCHDOG_CONTROL_REG 0x1BU
-#define WATCHDOG_TIMER_REG 0x1CU
-#define BUCK_ICC_TURNOFF_REG 0x1DU
-#define LDO_ICC_TURNOFF_REG 0x1EU
-#define BUCK_APM_CONTROL_REG 0x1FU
-#define BUCK1_CONTROL_REG 0x20U
-#define BUCK2_CONTROL_REG 0x21U
-#define BUCK3_CONTROL_REG 0x22U
-#define BUCK4_CONTROL_REG 0x23U
-#define VREF_DDR_CONTROL_REG 0x24U
-#define LDO1_CONTROL_REG 0x25U
-#define LDO2_CONTROL_REG 0x26U
-#define LDO3_CONTROL_REG 0x27U
-#define LDO4_CONTROL_REG 0x28U
-#define LDO5_CONTROL_REG 0x29U
-#define LDO6_CONTROL_REG 0x2AU
-#define BUCK1_PWRCTRL_REG 0x30U
-#define BUCK2_PWRCTRL_REG 0x31U
-#define BUCK3_PWRCTRL_REG 0x32U
-#define BUCK4_PWRCTRL_REG 0x33U
-#define VREF_DDR_PWRCTRL_REG 0x34U
-#define LDO1_PWRCTRL_REG 0x35U
-#define LDO2_PWRCTRL_REG 0x36U
-#define LDO3_PWRCTRL_REG 0x37U
-#define LDO4_PWRCTRL_REG 0x38U
-#define LDO5_PWRCTRL_REG 0x39U
-#define LDO6_PWRCTRL_REG 0x3AU
-#define FREQUENCY_SPREADING_REG 0x3BU
-#define USB_CONTROL_REG 0x40U
-#define ITLATCH1_REG 0x50U
-#define ITLATCH2_REG 0x51U
-#define ITLATCH3_REG 0x52U
-#define ITLATCH4_REG 0x53U
-#define ITSETLATCH1_REG 0x60U
-#define ITSETLATCH2_REG 0x61U
-#define ITSETLATCH3_REG 0x62U
-#define ITSETLATCH4_REG 0x63U
-#define ITCLEARLATCH1_REG 0x70U
-#define ITCLEARLATCH2_REG 0x71U
-#define ITCLEARLATCH3_REG 0x72U
-#define ITCLEARLATCH4_REG 0x73U
-#define ITMASK1_REG 0x80U
-#define ITMASK2_REG 0x81U
-#define ITMASK3_REG 0x82U
-#define ITMASK4_REG 0x83U
-#define ITSETMASK1_REG 0x90U
-#define ITSETMASK2_REG 0x91U
-#define ITSETMASK3_REG 0x92U
-#define ITSETMASK4_REG 0x93U
-#define ITCLEARMASK1_REG 0xA0U
-#define ITCLEARMASK2_REG 0xA1U
-#define ITCLEARMASK3_REG 0xA2U
-#define ITCLEARMASK4_REG 0xA3U
-#define ITSOURCE1_REG 0xB0U
-#define ITSOURCE2_REG 0xB1U
-#define ITSOURCE3_REG 0xB2U
-#define ITSOURCE4_REG 0xB3U
-#define LDO_VOLTAGE_MASK 0x7CU
-#define BUCK_VOLTAGE_MASK 0xFCU
-#define LDO_BUCK_VOLTAGE_SHIFT 2
-#define LDO_ENABLE_MASK 0x01U
-#define BUCK_ENABLE_MASK 0x01U
-#define BUCK_HPLP_ENABLE_MASK 0x02U
-#define LDO_HPLP_ENABLE_MASK 0x02U
-#define LDO_BUCK_HPLP_SHIFT 1
-#define LDO_BUCK_RANK_MASK 0x01U
-#define LDO_BUCK_RESET_MASK 0x01U
-#define LDO_BUCK_PULL_DOWN_MASK 0x03U
-
-/* Main PMIC Control Register (MAIN_CONTROL_REG) */
-#define ICC_EVENT_ENABLED BIT(4)
-#define PWRCTRL_POLARITY_HIGH BIT(3)
-#define PWRCTRL_PIN_VALID BIT(2)
-#define RESTART_REQUEST_ENABLED BIT(1)
-#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
-
-/* Main PMIC PADS Control Register (PADS_PULL_REG) */
-#define WAKEUP_DETECTOR_DISABLED BIT(4)
-#define PWRCTRL_PD_ACTIVE BIT(3)
-#define PWRCTRL_PU_ACTIVE BIT(2)
-#define WAKEUP_PD_ACTIVE BIT(1)
-#define PONKEY_PU_ACTIVE BIT(0)
-
-/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */
-#define SWIN_DETECTOR_ENABLED BIT(7)
-#define SWOUT_DETECTOR_ENABLED BIT(6)
-#define VINLOW_HYST_MASK 0x3
-#define VINLOW_HYST_SHIFT 4
-#define VINLOW_THRESHOLD_MASK 0x7
-#define VINLOW_THRESHOLD_SHIFT 1
-#define VINLOW_ENABLED 0x01
-#define VINLOW_CTRL_REG_MASK 0xFF
-
-/* USB Control Register */
-#define BOOST_OVP_DISABLED BIT(7)
-#define VBUS_OTG_DETECTION_DISABLED BIT(6)
-#define OCP_LIMIT_HIGH BIT(3)
-#define SWIN_SWOUT_ENABLED BIT(2)
-#define USBSW_OTG_SWITCH_ENABLED BIT(1)
-
-int stpmu1_switch_off(void);
-int stpmu1_register_read(uint8_t register_id, uint8_t *value);
-int stpmu1_register_write(uint8_t register_id, uint8_t value);
-int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
-int stpmu1_regulator_enable(const char *name);
-int stpmu1_regulator_disable(const char *name);
-uint8_t stpmu1_is_regulator_enabled(const char *name);
-int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts);
-void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
-
-#endif /* __STPMU1_H__ */
diff --git a/include/drivers/st/usb_dwc2.h b/include/drivers/st/usb_dwc2.h
new file mode 100644
index 0000000..85628f1
--- /dev/null
+++ b/include/drivers/st/usb_dwc2.h
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USB_DWC2_H
+#define __USB_DWC2_H
+
+#include <usb_core.h>
+
+/* define value use in register */
+
+#define USB_OTG_MODE_DEVICE 0
+#define USB_OTG_MODE_HOST 1
+#define USB_OTG_MODE_DRD 2
+
+#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ (0 << 1)
+#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ (1 << 1)
+#define DSTS_ENUMSPD_LS_PHY_6MHZ (2 << 1)
+#define DSTS_ENUMSPD_FS_PHY_48MHZ (3 << 1)
+
+#define EP_TYPE_CTRL 0
+#define EP_TYPE_ISOC 1
+#define EP_TYPE_BULK 2
+#define EP_TYPE_INTR 3
+
+#define STS_GOUT_NAK 1
+#define STS_DATA_UPDT 2
+#define STS_XFER_COMP 3
+#define STS_SETUP_COMP 4
+#define STS_SETUP_UPDT 6
+
+#define USBD_HS_TRDT_VALUE 9
+
+#define USB_OTG_DEVICE_BASE ((uint32_t)0x800)
+#define USB_OTG_IN_ENDPOINT_BASE ((uint32_t)0x900)
+#define USB_OTG_OUT_ENDPOINT_BASE ((uint32_t)0xB00)
+#define USB_OTG_FIFO_BASE ((uint32_t)0x1000)
+#define USB_OTG_FIFO_SIZE ((uint32_t)0x1000)
+#define USB_MAX_ENDPOINT_NB 0x10
+
+/* Bit definition for register */
+/* USB_OTG_GRSTCTL register */
+/* Core soft reset */
+#define USB_OTG_GRSTCTL_CSRST ((uint32_t)0x00000001)
+/* HCLK soft reset */
+#define USB_OTG_GRSTCTL_HSRST ((uint32_t)0x00000002)
+/* Host frame counter reset */
+#define USB_OTG_GRSTCTL_FCRST ((uint32_t)0x00000004)
+/* RxFIFOflush */
+#define USB_OTG_GRSTCTL_RXFFLSH ((uint32_t)0x00000010)
+/* TxFIFOflush */
+#define USB_OTG_GRSTCTL_TXFFLSH ((uint32_t)0x00000020)
+
+/* USB_OTG_DIEPCTLregister */
+/* Maximum packet size */
+#define USB_OTG_DIEPCTL_MPSIZ ((uint32_t)0x000007FF)
+/* USB active endpoint */
+#define USB_OTG_DIEPCTL_USBAEP ((uint32_t)0x00008000)
+/* Even/odd frame */
+#define USB_OTG_DIEPCTL_EONUM_DPID ((uint32_t)0x00010000)
+/* NAK status */
+#define USB_OTG_DIEPCTL_NAKSTS ((uint32_t)0x00020000)
+/* Endpoint type */
+#define USB_OTG_DIEPCTL_EPTYP ((uint32_t)0x000C0000)
+/* Bit0 */
+#define USB_OTG_DIEPCTL_EPTYP_0 ((uint32_t)0x00040000)
+/* Bit1 */
+#define USB_OTG_DIEPCTL_EPTYP_1 ((uint32_t)0x00080000)
+/* STALL handshake */
+#define USB_OTG_DIEPCTL_STALL ((uint32_t)0x00200000)
+/* TxFIFO number */
+#define USB_OTG_DIEPCTL_TXFNUM ((uint32_t)0x03C00000)
+/* Bit0 */
+#define USB_OTG_DIEPCTL_TXFNUM_0 ((uint32_t)0x00400000)
+/* Bit1 */
+#define USB_OTG_DIEPCTL_TXFNUM_1 ((uint32_t)0x00800000)
+/* Bit2 */
+#define USB_OTG_DIEPCTL_TXFNUM_2 ((uint32_t)0x01000000)
+/* Bit3 */
+#define USB_OTG_DIEPCTL_TXFNUM_3 ((uint32_t)0x02000000)
+/* Clear NAK */
+#define USB_OTG_DIEPCTL_CNAK ((uint32_t)0x04000000)
+/* Set NAK */
+#define USB_OTG_DIEPCTL_SNAK ((uint32_t)0x08000000)
+/* Set DATA0 PID */
+#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM ((uint32_t)0x10000000)
+/* Set odd frame */
+#define USB_OTG_DIEPCTL_SODDFRM ((uint32_t)0x20000000)
+/* Endpoint disable */
+#define USB_OTG_DIEPCTL_EPDIS ((uint32_t)0x40000000)
+/* Endpoint enable */
+#define USB_OTG_DIEPCTL_EPENA ((uint32_t)0x80000000)
+
+/* USB_OTG_DOEPCTL register */
+/* Maximum packet size */
+#define USB_OTG_DOEPCTL_MPSIZ ((uint32_t)0x000007FF)
+/* USB active endpoint */
+#define USB_OTG_DOEPCTL_USBAEP ((uint32_t)0x00008000)
+/* NAK status */
+#define USB_OTG_DOEPCTL_NAKSTS ((uint32_t)0x00020000)
+/* Set DATA0 PID */
+#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM ((uint32_t)0x10000000)
+/* Set odd frame */
+#define USB_OTG_DOEPCTL_SODDFRM ((uint32_t)0x20000000)
+/* Endpoint type */
+#define USB_OTG_DOEPCTL_EPTYP ((uint32_t)0x000C0000)
+/* Bit0 */
+#define USB_OTG_DOEPCTL_EPTYP_0 ((uint32_t)0x00040000)
+/* Bit1 */
+#define USB_OTG_DOEPCTL_EPTYP_1 ((uint32_t)0x00080000)
+/* Snoop mode */
+#define USB_OTG_DOEPCTL_SNPM ((uint32_t)0x00100000)
+/* STALL handshake */
+#define USB_OTG_DOEPCTL_STALL ((uint32_t)0x00200000)
+/* Clear NAK */
+#define USB_OTG_DOEPCTL_CNAK ((uint32_t)0x04000000)
+/* Set NAK */
+#define USB_OTG_DOEPCTL_SNAK ((uint32_t)0x08000000)
+/* Endpoint disable */
+#define USB_OTG_DOEPCTL_EPDIS ((uint32_t)0x40000000)
+/* Endpoint enable */
+#define USB_OTG_DOEPCTL_EPENA ((uint32_t)0x80000000)
+
+/* USB_OTG_DSTSregister */
+/* Suspend status */
+#define USB_OTG_DSTS_SUSPSTS ((uint32_t)0x00000001)
+/* Enumerated speed */
+#define USB_OTG_DSTS_ENUMSPD ((uint32_t)0x00000006)
+/* Bit0 */
+#define USB_OTG_DSTS_ENUMSPD_0 ((uint32_t)0x00000002)
+/* Bit1 */
+#define USB_OTG_DSTS_ENUMSPD_1 ((uint32_t)0x00000004)
+/* Erratic error */
+#define USB_OTG_DSTS_EERR ((uint32_t)0x00000008)
+/* Frame number of the received SOF */
+#define USB_OTG_DSTS_FNSOF ((uint32_t)0x003FFF00)
+
+/* USB_OTG_DCTLregister */
+/* Remote wakeup signaling */
+#define USB_OTG_DCTL_RWUSIG ((uint32_t)0x00000001)
+/* Soft disconnect */
+#define USB_OTG_DCTL_SDIS ((uint32_t)0x00000002)
+/* Global IN NAK status */
+#define USB_OTG_DCTL_GINSTS ((uint32_t)0x00000004)
+/* Global OUT NAK status */
+#define USB_OTG_DCTL_GONSTS ((uint32_t)0x00000008)
+/* Test control */
+#define USB_OTG_DCTL_TCTL ((uint32_t)0x00000070)
+/* Bit0 */
+#define USB_OTG_DCTL_TCTL_0 ((uint32_t)0x00000010)
+/* Bit1 */
+#define USB_OTG_DCTL_TCTL_1 ((uint32_t)0x00000020)
+/* Bit2 */
+#define USB_OTG_DCTL_TCTL_2 ((uint32_t)0x00000040)
+/* Set global IN NAK */
+#define USB_OTG_DCTL_SGINAK ((uint32_t)0x00000080)
+/* Clear global IN NAK */
+#define USB_OTG_DCTL_CGINAK ((uint32_t)0x00000100)
+/* Set global OUT NAK */
+#define USB_OTG_DCTL_SGONAK ((uint32_t)0x00000200)
+/* Clear global OUT NAK */
+#define USB_OTG_DCTL_CGONAK ((uint32_t)0x00000400)
+/* Power-on programming done */
+#define USB_OTG_DCTL_POPRGDNE ((uint32_t)0x00000800)
+
+/* USB_OTG_GAHBCFG register */
+/* Global interrupt mask */
+#define USB_OTG_GAHBCFG_GINT ((uint32_t)0x00000001)
+
+/* USB_OTG_DOEPTSIZr egister */
+/* Transfer size */
+#define USB_OTG_DOEPTSIZ_XFRSIZ ((uint32_t)0x0007FFFF)
+/* Packet count */
+#define USB_OTG_DOEPTSIZ_PKTCNT ((uint32_t)0x1FF80000)
+/* SETUP packet count */
+#define USB_OTG_DOEPTSIZ_STUPCNT ((uint32_t)0x60000000)
+/* Bit0 */
+#define USB_OTG_DOEPTSIZ_STUPCNT_0 ((uint32_t)0x20000000)
+/* Bit1 */
+#define USB_OTG_DOEPTSIZ_STUPCNT_1 ((uint32_t)0x40000000)
+
+/* USB_OTG_DIEPTSIZ register */
+/* Transfer size */
+#define USB_OTG_DIEPTSIZ_XFRSIZ ((uint32_t)0x0007FFFF)
+/* Packet count */
+#define USB_OTG_DIEPTSIZ_PKTCNT ((uint32_t)0x1FF80000)
+/* Packet count */
+#define USB_OTG_DIEPTSIZ_MULCNT ((uint32_t)0x60000000)
+
+/* USB_OTG_DCFG register */
+/* Device address */
+#define USB_OTG_DCFG_DAD ((uint32_t)0x000007F0)
+
+/* USB_OTG_DTXFSTS register */
+/* IN endpoint Tx FIFO space available */
+#define USB_OTG_DTXFSTS_INEPTFSAV ((uint32_t)0x0000FFFF)
+
+/* USB_OTG_GINTSTS register */
+/* Current mode of operation */
+#define USB_OTG_GINTSTS_CMOD ((uint32_t)0x00000001)
+/* Modem is match interrupt */
+#define USB_OTG_GINTSTS_MMIS ((uint32_t)0x00000002)
+/* OTG interrupt */
+#define USB_OTG_GINTSTS_OTGINT ((uint32_t)0x00000004)
+/* Start offrame */
+#define USB_OTG_GINTSTS_SOF ((uint32_t)0x00000008)
+/* Rx FIFO nonempty */
+#define USB_OTG_GINTSTS_RXFLVL ((uint32_t)0x00000010)
+/* Non periodic Tx FIFO empty */
+#define USB_OTG_GINTSTS_NPTXFE ((uint32_t)0x00000020)
+/* Global IN non periodic NAK effective */
+#define USB_OTG_GINTSTS_GINAKEFF ((uint32_t)0x00000040)
+/* Global OUT NAK effective */
+#define USB_OTG_GINTSTS_BOUTNAKEFF ((uint32_t)0x00000080)
+/* Early suspend */
+#define USB_OTG_GINTSTS_ESUSP ((uint32_t)0x00000400)
+/* USB suspend */
+#define USB_OTG_GINTSTS_USBSUSP ((uint32_t)0x00000800)
+/* USB reset */
+#define USB_OTG_GINTSTS_USBRST ((uint32_t)0x00001000)
+/* Enumeration done */
+#define USB_OTG_GINTSTS_ENUMDNE ((uint32_t)0x00002000)
+/* Isochronous OUT packet dropped interrupt */
+#define USB_OTG_GINTSTS_ISOODRP ((uint32_t)0x00004000)
+/* End of periodic frame interrupt */
+#define USB_OTG_GINTSTS_EOPF ((uint32_t)0x00008000)
+/* IN endpoint interrupt */
+#define USB_OTG_GINTSTS_IEPINT ((uint32_t)0x00040000)
+/* OUT endpoint interrupt */
+#define USB_OTG_GINTSTS_OEPINT ((uint32_t)0x00080000)
+/* Incomplete isochronous IN transfer */
+#define USB_OTG_GINTSTS_IISOIXFR ((uint32_t)0x00100000)
+/* Incomplete periodic transfer */
+#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT ((uint32_t)0x00200000)
+/* Data fetch suspended */
+#define USB_OTG_GINTSTS_DATAFSUSP ((uint32_t)0x00400000)
+/* Reset detected interrupt */
+#define USB_OTG_GINTSTS_RSTDET ((uint32_t)0x00800000)
+/* Host port interrupt */
+#define USB_OTG_GINTSTS_HPRTINT ((uint32_t)0x01000000)
+/* Host channels interrupt */
+#define USB_OTG_GINTSTS_HCINT ((uint32_t)0x02000000)
+/* Periodic Tx FIFO empty */
+#define USB_OTG_GINTSTS_PTXFE ((uint32_t)0x04000000)
+/* LPM interrupt */
+#define USB_OTG_GINTSTS_LPMINT ((uint32_t)0x08000000)
+/* Connector ID status change */
+#define USB_OTG_GINTSTS_CIDSCHG ((uint32_t)0x10000000)
+/* Disconnect detected interrupt */
+#define USB_OTG_GINTSTS_DISCINT ((uint32_t)0x20000000)
+/* Session request/new session detected interrupt */
+#define USB_OTG_GINTSTS_SRQINT ((uint32_t)0x40000000)
+/* Resume/remote wakeup detected interrupt */
+#define USB_OTG_GINTSTS_WKUINT ((uint32_t)0x80000000)
+
+/* USB_OTG_DOEPINT register */
+/* Transfer completed interrupt */
+#define USB_OTG_DOEPINT_XFRC ((uint32_t)0x00000001)
+/* Endpoint disabled interrupt */
+#define USB_OTG_DOEPINT_EPDISD ((uint32_t)0x00000002)
+/* SETUP phase done */
+#define USB_OTG_DOEPINT_STUP ((uint32_t)0x00000008)
+/* OUT token received when endpoint disabled */
+#define USB_OTG_DOEPINT_OTEPDIS ((uint32_t)0x00000010)
+/* Back-to-back SETUP packets received */
+#define USB_OTG_DOEPINT_B2BSTUP ((uint32_t)0x00000040)
+/* NYET interrupt */
+#define USB_OTG_DOEPINT_NYET ((uint32_t)0x00004000)
+
+/* USB_OTG_DIEPINTregister */
+/* Transfer completed interrupt */
+#define USB_OTG_DIEPINT_XFRC ((uint32_t)0x00000001)
+/* Endpoint disabled interrupt */
+#define USB_OTG_DIEPINT_EPDISD ((uint32_t)0x00000002)
+/* Timeout condition */
+#define USB_OTG_DIEPINT_TOC ((uint32_t)0x00000008)
+/* IN token received when Tx FIFO is empty */
+#define USB_OTG_DIEPINT_ITTXFE ((uint32_t)0x00000010)
+/* IN endpoint NAK effective */
+#define USB_OTG_DIEPINT_INEPNE ((uint32_t)0x00000040)
+/* Transmit Fifo empty */
+#define USB_OTG_DIEPINT_TXFE ((uint32_t)0x00000080)
+/* Transmit Fifo Underrun */
+#define USB_OTG_DIEPINT_TXFIFOUDRN ((uint32_t)0x00000100)
+/* Buffer not available interrupt */
+#define USB_OTG_DIEPINT_BNA ((uint32_t)0x00000200)
+/* Packet dropped status */
+#define USB_OTG_DIEPINT_PKTDRPSTS ((uint32_t)0x00000800)
+/* Babble error interrupt */
+#define USB_OTG_DIEPINT_BERR ((uint32_t)0x00001000)
+/* NAK interrupt */
+#define USB_OTG_DIEPINT_NAK ((uint32_t)0x00002000)
+
+/* USB_OTG_GLPMCFG register */
+/* BESL value received with last ACKed LPM Token */
+#define USB_OTG_GLPMCFG_BESL ((uint32_t)0x0000003C)
+
+/* USB_OTG_GOTGINT register */
+/* Session end detected */
+#define USB_OTG_GOTGINT_SEDET ((uint32_t)0x00000004)
+
+/* USB_OTG_GRXSTSP register */
+/* IN EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_EPNUM ((uint32_t)0x0000000F)
+/* OUT EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_BCNT ((uint32_t)0x00007FF0)
+/* OUT EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_DPID ((uint32_t)0x00018000)
+/* OUT EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_PKTSTS ((uint32_t)0x001E0000)
+
+/* USB_OTG_GUSBCFG register */
+/* USB turn around time */
+#define USB_OTG_GUSBCFG_TRDT ((uint32_t)0x00003C00)
+
+/* USB_OTG_DOEPMSK register */
+/* Transfer completed interrupt mask */
+#define USB_OTG_DOEPMSK_XFRCM ((uint32_t)0x00000001)
+/* Endpoint disabled interrupt mask */
+#define USB_OTG_DOEPMSK_EPDM ((uint32_t)0x00000002)
+/* SETUP phase done mask */
+#define USB_OTG_DOEPMSK_STUPM ((uint32_t)0x00000008)
+/* OUT token received when endpoint disabled mask */
+#define USB_OTG_DOEPMSK_OTEPDM ((uint32_t)0x00000010)
+/* Back-to-back SETUP packets received mask */
+#define USB_OTG_DOEPMSK_B2BSTUP ((uint32_t)0x00000040)
+/* OUT packet error mask */
+#define USB_OTG_DOEPMSK_OPEM ((uint32_t)0x00000100)
+/* BNA interrupt mask */
+#define USB_OTG_DOEPMSK_BOIM ((uint32_t)0x00000200)
+
+/* USB_OTG_DIEPMSK register */
+/* Transfer completed interrupt mask */
+#define USB_OTG_DIEPMSK_XFRCM ((uint32_t)0x00000001)
+/* Endpoint disabled interrupt mask */
+#define USB_OTG_DIEPMSK_EPDM ((uint32_t)0x00000002)
+/* Timeout condition mask(non isochronous endpoints) */
+#define USB_OTG_DIEPMSK_TOM ((uint32_t)0x00000008)
+/* IN token received when Tx FIFO empty mask */
+#define USB_OTG_DIEPMSK_ITTXFEMSK ((uint32_t)0x00000010)
+/* IN token received with EP mismatch mask */
+#define USB_OTG_DIEPMSK_INEPNMM ((uint32_t)0x00000020)
+/* IN endpoint NAK effective mask */
+#define USB_OTG_DIEPMSK_INEPNEM ((uint32_t)0x00000040)
+/* FIFO under run mask */
+#define USB_OTG_DIEPMSK_TXFURM ((uint32_t)0x00000100)
+/* BNA interrupt mask */
+#define USB_OTG_DIEPMSK_BIM ((uint32_t)0x00000200)
+
+typedef struct {
+ uint32_t dcfg;/* dev Configuration Register */
+ uint32_t dctl;/* dev Control Register */
+ uint32_t dsts;/* dev Status Register(RO) */
+ uint32_t reserved1;/* reserved */
+ uint32_t diepmsk;/* dev IN Endpoint Mask */
+ uint32_t doepmsk;/* dev OUT Endpoint Mask */
+ uint32_t daint;/* dev All Endpoints Itr Reg */
+ uint32_t daintmsk;/* dev All Endpoints Itr Mask */
+ uint32_t reserved2;/* reserved */
+ uint32_t reserved3;/* reserved */
+ uint32_t dvbusdis;/* dev VBUS discharge Register */
+ uint32_t dvbuspulse;/* dev VBUS Pulse Register */
+ uint32_t dthrctl;/* dev threshold */
+ uint32_t diepempmsk;/* dev empty msk */
+ uint32_t deachint;/* dedicated EP interrupt */
+ uint32_t deachmsk;/* dedicated EP msk */
+ uint32_t reserved4;/* dedicated EP mask */
+ uint32_t dinep1msk;/* dedicated EP mask */
+ uint32_t reserved5[15];/* reserved */
+ uint32_t doutep1msk;/* dedicated EP msk */
+} usb_dwc2_device_t;
+
+typedef struct {
+ uint32_t epctl;/* dev IN Endpoint Control Reg */
+ uint32_t reserved1;/* reserved */
+ uint32_t epint;/* dev IN Endpoint Itr Reg */
+ uint32_t reserved2;/* reserved*/
+ uint32_t eptsiz;/* IN Endpoint Txfer Size */
+ uint32_t epdma;/* IN Endpoint DMA Address Reg */
+ uint32_t txfsts;/* IN Endpoint Tx FIFO Status Reg */
+ uint32_t reserved3;/* reserved */
+} usb_dwc2_endpoint_t;
+
+typedef struct {
+ uint32_t gotgctl;/* USB_OTG Control and Status Register */
+ uint32_t gotgint;/* USB_OTG Interrupt Register */
+ uint32_t gahbcfg;/* Core AHB Configuration Register */
+ uint32_t gusbcfg;/* Core USB Configuration Register */
+ uint32_t grstctl;/* Core Reset Register */
+ uint32_t gintsts;/* Core Interrupt Register */
+ uint32_t gintmsk;/* Core Interrupt Mask Register */
+ uint32_t grxstsr;/* Receive StsQ Read Register */
+ uint32_t grxstsp;/* Receive StsQ Read & POP Register */
+ uint32_t grxfsiz;/* Receive FIFO SizeRegister */
+ uint32_t dieptxfo;/* EP0/Non Periodic Tx FIFO Size Reg */
+ uint32_t hnptxsts;/* Non Periodic Tx FIFO / Queue Sts reg */
+ uint32_t reserved1[2];/* reserved */
+ uint32_t gccfg;/* General Purpose IO Register */
+ uint32_t cid;/* User ID Register */
+ uint32_t reserved2[3];/* reserved */
+ uint32_t ghwcfg3;/* User HW config */
+ uint32_t reserved3;/* reserved */
+ uint32_t glpmcfg;/* LPM Register */
+ uint32_t gpwrdn;/* Power Down Register */
+ uint32_t gdfifocfg;/* DFIFO Software Config Register */
+ uint32_t gadpctl;/* ADPTimer, Control and Status Register */
+ uint32_t reserved4[39];/* reserved */
+ uint32_t hptxfsiz;/* Host Periodic Tx FIFO Size Reg */
+ uint32_t dieptxf[0x0F];/* dev Periodic Transmit FIFO */
+} usb_dwc2_global_t;
+
+typedef struct {
+ usb_dwc2_global_t *usb_global;
+ usb_dwc2_device_t *usb_device;
+ usb_dwc2_endpoint_t *usb_in_endpoint[USB_MAX_ENDPOINT_NB];
+ usb_dwc2_endpoint_t *usb_out_endpoint[USB_MAX_ENDPOINT_NB];
+ uint32_t *usb_fifo[USB_MAX_ENDPOINT_NB];
+} usb_dwc2_t;
+
+usb_status_t usb_dwc2_disable_int(void *handle);
+usb_status_t usb_dwc2_ep0_out_start(void *handle);
+usb_status_t usb_dwc2_ep_start_xfer(void *handle, usb_otg_ep_t *ep);
+usb_status_t usb_dwc2_ep0_start_xfer(void *handle, usb_otg_ep_t *ep);
+usb_status_t usb_dwc2_write_packet(void *handle, uint8_t *src,
+ uint8_t ch_ep_num, uint16_t len);
+void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len);
+usb_status_t usb_dwc2_ep_set_stall(void *handle, usb_otg_ep_t *ep);
+usb_status_t usb_dwc2_stop_device(void *handle);
+usb_status_t usb_dwc2_set_address(void *handle, uint8_t address);
+usb_status_t usb_dwc2_dev_disconnect(void *handle);
+usb_status_t usb_dwc2_write_empty_tx_fifo(void *handle, uint32_t epnum,
+ uint32_t xfer_len,
+ uint32_t *xfer_count,
+ uint32_t maxpacket,
+ uint8_t **xfer_buff);
+usb_action_t usb_dwc2_it_handler(void *handle, uint32_t *param);
+void usb_dwc2_init_driver(usb_handle_t *usb_core_handle,
+ uint32_t *base_register);
+
+#endif /* __USB_DWC2_H */
+
diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h
new file mode 100644
index 0000000..aa9158c
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/arm-gic.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/*
+ * This header provides constants for the ARM GIC.
+ */
+
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
+
+/* interrupt specifier cell 0 */
+
+#define GIC_SPI 0
+#define GIC_PPI 1
+
+#define IRQ_TYPE_NONE 0
+#define IRQ_TYPE_EDGE_RISING 1
+#define IRQ_TYPE_EDGE_FALLING 2
+#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define IRQ_TYPE_LEVEL_LOW 8
+
+#endif
diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
index e2f1f1b..7f6e4b9 100644
--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -32,4 +32,10 @@
#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode))
+/* package information */
+#define STM32MP157CAA 0x1
+#define STM32MP157CAB 0x2
+#define STM32MP157CAC 0x4
+#define STM32MP157CAD 0x8
+
#endif /* _DT_BINDINGS_STM32_PINFUNC_H */
diff --git a/include/dt-bindings/power/stm32mp1-power.h b/include/dt-bindings/power/stm32mp1-power.h
new file mode 100644
index 0000000..bfb7f78
--- /dev/null
+++ b/include/dt-bindings/power/stm32mp1-power.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Yann Gautier <yann.gautier@st.com> for STMicroelectronics.
+ */
+
+#ifndef DT_BINDINGS_STM32MP1_POWER_H
+#define DT_BINDINGS_STM32MP1_POWER_H
+
+#define STM32_PM_CSLEEP_RUN 0
+#define STM32_PM_CSTOP_ALLOW_STOP 1
+#define STM32_PM_CSTOP_ALLOW_LP_STOP 2
+#define STM32_PM_CSTOP_ALLOW_LPLV_STOP 3
+#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR 4
+#define STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF 5
+#define STM32_PM_SHUTDOWN 6
+#define STM32_PM_MAX_SOC_MODE 7
+
+#endif /* DT_BINDINGS_STM32MP1_POWER_H */
diff --git a/include/dt-bindings/soc/st,stm32-etzpc.h b/include/dt-bindings/soc/st,stm32-etzpc.h
new file mode 100644
index 0000000..6678b8e
--- /dev/null
+++ b/include/dt-bindings/soc/st,stm32-etzpc.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
+ */
+
+#ifndef _DT_BINDINGS_STM32_ETZPC_H
+#define _DT_BINDINGS_STM32_ETZPC_H
+
+/* define DECPROT modes */
+#define DECPROT_S_RW 0x0
+#define DECPROT_NS_R_S_W 0x1
+#define DECPROT_MCU_ISOLATION 0x2
+#define DECPROT_NS_RW 0x3
+
+/* define DECPROT lock */
+#define DECPROT_UNLOCK 0x0
+#define DECPROT_LOCK 0x1
+
+/* define ETZPC ID */
+#define STM32MP1_ETZPC_STGENC_ID 0
+#define STM32MP1_ETZPC_BKPSRAM_ID 1
+#define STM32MP1_ETZPC_IWDG1_ID 2
+#define STM32MP1_ETZPC_USART1_ID 3
+#define STM32MP1_ETZPC_SPI6_ID 4
+#define STM32MP1_ETZPC_I2C4_ID 5
+#define STM32MP1_ETZPC_RNG1_ID 7
+#define STM32MP1_ETZPC_HASH1_ID 8
+#define STM32MP1_ETZPC_CRYP1_ID 9
+#define STM32MP1_ETZPC_DDRCTRL_ID 10
+#define STM32MP1_ETZPC_DDRPHYC_ID 11
+#define STM32MP1_ETZPC_I2C6_ID 12
+#define STM32MP1_ETZPC_TIM2_ID 16
+#define STM32MP1_ETZPC_TIM3_ID 17
+#define STM32MP1_ETZPC_TIM4_ID 18
+#define STM32MP1_ETZPC_TIM5_ID 19
+#define STM32MP1_ETZPC_TIM6_ID 20
+#define STM32MP1_ETZPC_TIM7_ID 21
+#define STM32MP1_ETZPC_TIM12_ID 22
+#define STM32MP1_ETZPC_TIM13_ID 23
+#define STM32MP1_ETZPC_TIM14_ID 24
+#define STM32MP1_ETZPC_LPTIM1_ID 25
+#define STM32MP1_ETZPC_WWDG1_ID 26
+#define STM32MP1_ETZPC_SPI2_ID 27
+#define STM32MP1_ETZPC_SPI3_ID 28
+#define STM32MP1_ETZPC_SPDIFRX_ID 29
+#define STM32MP1_ETZPC_USART2_ID 30
+#define STM32MP1_ETZPC_USART3_ID 31
+#define STM32MP1_ETZPC_UART4_ID 32
+#define STM32MP1_ETZPC_UART5_ID 33
+#define STM32MP1_ETZPC_I2C1_ID 34
+#define STM32MP1_ETZPC_I2C2_ID 35
+#define STM32MP1_ETZPC_I2C3_ID 36
+#define STM32MP1_ETZPC_I2C5_ID 37
+#define STM32MP1_ETZPC_CEC_ID 38
+#define STM32MP1_ETZPC_DAC_ID 39
+#define STM32MP1_ETZPC_UART7_ID 40
+#define STM32MP1_ETZPC_UART8_ID 41
+#define STM32MP1_ETZPC_MDIOS_ID 44
+#define STM32MP1_ETZPC_TIM1_ID 48
+#define STM32MP1_ETZPC_TIM8_ID 49
+#define STM32MP1_ETZPC_USART6_ID 51
+#define STM32MP1_ETZPC_SPI1_ID 52
+#define STM32MP1_ETZPC_SPI4_ID 53
+#define STM32MP1_ETZPC_TIM15_ID 54
+#define STM32MP1_ETZPC_TIM16_ID 55
+#define STM32MP1_ETZPC_TIM17_ID 56
+#define STM32MP1_ETZPC_SPI5_ID 57
+#define STM32MP1_ETZPC_SAI1_ID 58
+#define STM32MP1_ETZPC_SAI2_ID 59
+#define STM32MP1_ETZPC_SAI3_ID 60
+#define STM32MP1_ETZPC_DFSDM_ID 61
+#define STM32MP1_ETZPC_TT_FDCAN_ID 62
+#define STM32MP1_ETZPC_LPTIM2_ID 64
+#define STM32MP1_ETZPC_LPTIM3_ID 65
+#define STM32MP1_ETZPC_LPTIM4_ID 66
+#define STM32MP1_ETZPC_LPTIM5_ID 67
+#define STM32MP1_ETZPC_SAI4_ID 68
+#define STM32MP1_ETZPC_VREFBUF_ID 69
+#define STM32MP1_ETZPC_DCMI_ID 70
+#define STM32MP1_ETZPC_CRC2_ID 71
+#define STM32MP1_ETZPC_ADC_ID 72
+#define STM32MP1_ETZPC_HASH2_ID 73
+#define STM32MP1_ETZPC_RNG2_ID 74
+#define STM32MP1_ETZPC_CRYP2_ID 75
+#define STM32MP1_ETZPC_SRAM1_ID 80
+#define STM32MP1_ETZPC_SRAM2_ID 81
+#define STM32MP1_ETZPC_SRAM3_ID 82
+#define STM32MP1_ETZPC_SRAM4_ID 83
+#define STM32MP1_ETZPC_RETRAM_ID 84
+#define STM32MP1_ETZPC_OTG_ID 85
+#define STM32MP1_ETZPC_SDMMC3_ID 86
+#define STM32MP1_ETZPC_DLYBSD3_ID 87
+#define STM32MP1_ETZPC_DMA1_ID 88
+#define STM32MP1_ETZPC_DMA2_ID 89
+#define STM32MP1_ETZPC_DMAMUX_ID 90
+#define STM32MP1_ETZPC_FMC_ID 91
+#define STM32MP1_ETZPC_QSPI_ID 92
+#define STM32MP1_ETZPC_DLYBQ_ID 93
+#define STM32MP1_ETZPC_ETH_ID 94
+
+#define STM32MP1_ETZPC_MAX_ID 96
+
+#define DECPROT(id, mode, lock) (((id) << 16) | ((mode) << 8) | (lock))
+
+#endif /* _DT_BINDINGS_STM32_ETZPC_H */
+
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 3536d20..aa34b9c 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -61,6 +61,9 @@
* Generic timer memory mapped registers & offsets
******************************************************************************/
#define CNTCR_OFF U(0x000)
+#define CNTSR_OFF U(0x004)
+#define CNTCVL_OFF U(0x008)
+#define CNTCVU_OFF U(0x00C)
#define CNTFID_OFF U(0x020)
#define CNTCR_EN (U(1) << 0)
@@ -457,6 +460,8 @@
#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 VPIDR p15, 4, c0, c0, 0
#define VMPIDR p15, 4, c0, c0, 5
#define ISR p15, 0, c12, c1, 0
@@ -466,6 +471,7 @@
#define HTCR p15, 4, c2, c0, 2
#define HMAIR0 p15, 4, c10, c2, 0
#define ATS1CPR p15, 0, c7, c8, 0
+#define ATS1CPW p15, 0, c7, c8, 1
#define ATS1HR p15, 4, c7, c8, 0
#define DBGOSDLR p14, 0, c1, c3, 4
@@ -514,6 +520,12 @@
#define ICC_ASGI1R_EL1_64 p15, 1, c12
#define ICC_SGI0R_EL1_64 p15, 2, c12
+/* Fault registers. The format is: coproc, opt1, CRn, CRm, opt2 */
+#define DFSR p15, 0, c5, c0, 0
+#define IFSR p15, 0, c5, c0, 1
+#define DFAR p15, 0, c6, c0, 0
+#define IFAR p15, 0, c6, c0, 2
+
/*******************************************************************************
* Definitions of MAIR encodings for device and normal memory
******************************************************************************/
@@ -567,6 +579,8 @@
/* PAR fields */
#define PAR_F_SHIFT U(0)
#define PAR_F_MASK ULL(0x1)
+#define PAR_NS_SHIFT U(9)
+#define PAR_NS_MASK U(0x1)
#define PAR_ADDR_SHIFT U(12)
#define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 5d9c1c1..e48123c 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -261,6 +261,8 @@ 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(icc_sre_el1, ICC_SRE)
DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE)
@@ -282,6 +284,7 @@ DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
DEFINE_COPROCR_RW_FUNCS(ats1cpr, ATS1CPR)
+DEFINE_COPROCR_RW_FUNCS(ats1cpw, ATS1CPW)
DEFINE_COPROCR_RW_FUNCS(ats1hr, ATS1HR)
DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64)
diff --git a/include/lib/cpus/aarch32/cortex_a9.h b/include/lib/cpus/aarch32/cortex_a9.h
index be85f9b..ea8412f 100644
--- a/include/lib/cpus/aarch32/cortex_a9.h
+++ b/include/lib/cpus/aarch32/cortex_a9.h
@@ -18,6 +18,11 @@
#define CORTEX_A9_ACTLR_SMP_BIT (1 << 6)
#define CORTEX_A9_ACTLR_FLZW_BIT (1 << 3)
+#if defined(ARMV7_CORTEX_A_ACTLR_FLZW_BIT) && \
+ ARMV7_CORTEX_A_ACTLR_FLZW_BIT != CORTEX_A9_ACTLR_FLZW_BIT
+#error Cortex-A9 ACTLR field FLZW does not match
+#endif
+
/*******************************************************************************
* CPU Power Control Register
******************************************************************************/
diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h
index 3d35b19..96c90bd 100644
--- a/include/lib/optee_utils.h
+++ b/include/lib/optee_utils.h
@@ -8,6 +8,7 @@
#include <bl_common.h>
+int get_optee_header_ep(entry_point_info_t *header_ep, uintptr_t *pc);
int parse_optee_header(entry_point_info_t *header_ep,
image_info_t *pager_image_info,
image_info_t *paged_image_info);
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index b27e481..b7febc3 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -302,10 +302,10 @@ typedef struct plat_psci_ops {
void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
void (*pwr_domain_suspend_finish)(
const psci_power_state_t *target_state);
- void (*pwr_domain_pwr_down_wfi)(
- const psci_power_state_t *target_state) __dead2;
- void (*system_off)(void) __dead2;
- void (*system_reset)(void) __dead2;
+ void __dead2 (*pwr_domain_pwr_down_wfi)(
+ const psci_power_state_t *target_state);
+ void __dead2 (*system_off)(void);
+ void __dead2 (*system_reset)(void);
int (*validate_power_state)(unsigned int power_state,
psci_power_state_t *req_state);
int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint);
diff --git a/include/lib/usb/usb_core.h b/include/lib/usb/usb_core.h
new file mode 100644
index 0000000..eb0e87a
--- /dev/null
+++ b/include/lib/usb/usb_core.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USBD_CORE_H
+#define __USBD_CORE_H
+
+#include <stdint.h>
+#include <utils_def.h>
+
+#define USBD_MAX_NUM_INTERFACES 1
+#define USBD_MAX_NUM_CONFIGURATION 1
+
+#define USB_LEN_DEV_QUALIFIER_DESC 0x0A
+#define USB_LEN_DEV_DESC 0x12
+#define USB_LEN_CFG_DESC 0x09
+#define USB_LEN_IF_DESC 0x09
+#define USB_LEN_EP_DESC 0x07
+#define USB_LEN_OTG_DESC 0x03
+#define USB_LEN_LANGID_STR_DESC 0x04
+#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09
+
+#define USBD_IDX_LANGID_STR 0x00
+#define USBD_IDX_MFC_STR 0x01
+#define USBD_IDX_PRODUCT_STR 0x02
+#define USBD_IDX_SERIAL_STR 0x03
+#define USBD_IDX_CONFIG_STR 0x04
+#define USBD_IDX_INTERFACE_STR 0x05
+
+#define USB_REQ_TYPE_STANDARD 0x00
+#define USB_REQ_TYPE_CLASS 0x20
+#define USB_REQ_TYPE_VENDOR 0x40
+#define USB_REQ_TYPE_MASK 0x60
+
+#define USB_REQ_RECIPIENT_DEVICE 0x00
+#define USB_REQ_RECIPIENT_INTERFACE 0x01
+#define USB_REQ_RECIPIENT_ENDPOINT 0x02
+#define USB_REQ_RECIPIENT_MASK 0x03
+
+#define USB_REQ_GET_STATUS 0x00
+#define USB_REQ_CLEAR_FEATURE 0x01
+#define USB_REQ_SET_FEATURE 0x03
+#define USB_REQ_SET_ADDRESS 0x05
+#define USB_REQ_GET_DESCRIPTOR 0x06
+#define USB_REQ_SET_DESCRIPTOR 0x07
+#define USB_REQ_GET_CONFIGURATION 0x08
+#define USB_REQ_SET_CONFIGURATION 0x09
+#define USB_REQ_GET_INTERFACE 0x0A
+#define USB_REQ_SET_INTERFACE 0x0B
+#define USB_REQ_SYNCH_FRAME 0x0C
+
+#define USB_DESC_TYPE_DEVICE 0x01
+#define USB_DESC_TYPE_CONFIGURATION 0x02
+#define USB_DESC_TYPE_STRING 0x03
+#define USB_DESC_TYPE_INTERFACE 0x04
+#define USB_DESC_TYPE_ENDPOINT 0x05
+#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06
+#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07
+#define USB_DESC_TYPE_BOS 0x0F
+
+#define USB_CONFIG_REMOTE_WAKEUP 2
+#define USB_CONFIG_SELF_POWERED 1
+
+#define USB_FEATURE_EP_HALT 0
+#define USB_FEATURE_REMOTE_WAKEUP 1
+#define USB_FEATURE_TEST_MODE 2
+
+#define USB_DEVICE_CAPABITY_TYPE 0x10
+
+#define USB_HS_MAX_PACKET_SIZE 512
+#define USB_FS_MAX_PACKET_SIZE 64
+#define USB_MAX_EP0_SIZE 64
+
+/* Device Status */
+#define USBD_STATE_DEFAULT 1
+#define USBD_STATE_ADDRESSED 2
+#define USBD_STATE_CONFIGURED 3
+#define USBD_STATE_SUSPENDED 4
+
+/* EP0 State */
+#define USBD_EP0_IDLE 0
+#define USBD_EP0_SETUP 1
+#define USBD_EP0_DATA_IN 2
+#define USBD_EP0_DATA_OUT 3
+#define USBD_EP0_STATUS_IN 4
+#define USBD_EP0_STATUS_OUT 5
+#define USBD_EP0_STALL 6
+
+#define USBD_EP_TYPE_CTRL 0
+#define USBD_EP_TYPE_ISOC 1
+#define USBD_EP_TYPE_BULK 2
+#define USBD_EP_TYPE_INTR 3
+
+#define USB_OTG_SPEED_HIGH 0
+#define USB_OTG_SPEED_HIGH_IN_FULL 1
+#define USB_OTG_SPEED_LOW 2
+#define USB_OTG_SPEED_FULL 3
+
+#define USB_OTG_HS_MAX_PACKET_SIZE 512
+#define USB_OTG_FS_MAX_PACKET_SIZE 64
+#define USB_OTG_MAX_EP0_SIZE 64
+
+#define USB_OTG_OUT_EPNUM_MASK 0x0000FFFF
+#define USB_OTG_OUT_COUNT_MASK 0xFFFF0000
+
+#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
+ (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8))
+
+#define LOBYTE(x) ((uint8_t)((x) & 0x00FF))
+#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00) >> 8))
+
+typedef struct {
+ uint8_t bm_request;
+ uint8_t b_request;
+ uint16_t value;
+ uint16_t index;
+ uint16_t length;
+} usb_setup_req_t;
+
+struct usb_handle;
+
+typedef struct {
+ uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx);
+ uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx);
+ /* Control Endpoints*/
+ uint8_t (*setup)(struct usb_handle *pdev, usb_setup_req_t *req);
+ uint8_t (*ep0_tx_sent)(struct usb_handle *pdev);
+ uint8_t (*ep0_rx_ready)(struct usb_handle *pdev);
+ /* Class Specific Endpoints*/
+ uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum);
+ uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum);
+ uint8_t (*sof)(struct usb_handle *pdev);
+ uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum);
+ uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum);
+ uint32_t reserved;
+} usb_class_t;
+
+/* Following USB Device status */
+typedef enum {
+ USBD_OK = 0,
+ USBD_BUSY,
+ USBD_FAIL,
+ USBD_TIMEOUT
+} usb_status_t;
+
+/* Action to do after IT handling */
+typedef enum {
+ USB_NOTHING = 0,
+ USB_DATA_OUT,
+ USB_DATA_IN,
+ USB_SETUP,
+ USB_ENUM_DONE,
+ USB_READ_DATA_PACKET,
+ USB_READ_SETUP_PACKET,
+ USB_RESUME,
+ USB_SUSPEND,
+ USB_LPM,
+ USB_SOF,
+ USB_DISCONNECT,
+ USB_WRITE_EMPTY
+} usb_action_t;
+
+/* USB Device descriptors structure */
+typedef struct {
+ uint8_t *(*get_device_desc)(uint16_t *length);
+ uint8_t *(*get_lang_id_desc)(uint16_t *length);
+ uint8_t *(*get_manufacturer_desc)(uint16_t *length);
+ uint8_t *(*get_product_desc)(uint16_t *length);
+ uint8_t *(*get_serial_desc)(uint16_t *length);
+ uint8_t *(*get_configuration_desc)(uint16_t *length);
+ uint8_t *(*get_interface_desc)(uint16_t *length);
+ uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length);
+ uint8_t *(*get_hs_config_desc)(uint16_t *length);
+ uint8_t *(*get_fs_config_desc)(uint16_t *length);
+ uint8_t *(*get_other_speed_config_desc)(uint16_t *length);
+ uint8_t *(*get_device_qualifier_desc)(uint16_t *length);
+ uint8_t *(*get_dfu_desc)(uint16_t *length);
+} usb_desc_t;
+
+/* USB Device handle structure */
+typedef struct {
+ uint32_t status;
+ uint32_t total_length;
+ uint32_t rem_length;
+ uint32_t maxpacket;
+} usb_endpoint_t;
+
+typedef struct {
+ uint32_t dev_endpoints; /* Device Endpoints number.
+ * This parameter depends on the used USB core.
+ * This This parameter must be a number between
+ * This Min_Data = 1 and Max_Data = 15
+ */
+ uint32_t host_channels; /* Host Channels number.
+ * This parameter Depends on the used USB core.
+ * This parameter must be a number between
+ * Min_Data = 1 and Max_Data = 15
+ */
+ uint32_t speed; /* USB Core speed. */
+ uint32_t can_be_deleted; /* Enable or disable of the
+ * USB embedded DMA.
+ */
+ uint32_t ep0_mps; /* Set the Endpoint 0 Max Packet size. */
+ uint32_t phy_itface; /* Select the used PHY interface. */
+ uint32_t sof_enable; /* Enable or disable the output of
+ * the SOF signal.
+ */
+ uint32_t low_power_enable; /* Enable or disable the low power mode. */
+ uint32_t lpm_enable; /* Enable or disable Link Power Management.*/
+ uint32_t vbus_sensing_enable; /* Enable or disable the VBUS
+ * Sensing feature.
+ */
+ uint32_t use_dedicated_ep1; /* Enable or disable the use of the
+ * dedicated EP1 interrupt.
+ */
+ uint32_t use_external_vbus; /* Enable or disable the use of
+ * the external VBUS.
+ */
+} usb_otg_cfg_t;
+
+typedef struct {
+ uint8_t num;/* Endpoint number
+ * This parameter must be a number between Min_Data = 1
+ * and Max_Data = 15
+ */
+ uint8_t is_in; /* Endpoint direction
+ * This parameter must be a number between
+ * Min_Data = 0 and Max_Data = 1
+ */
+ uint8_t is_stall; /* Endpoint stall condition
+ * This parameter must be a number between
+ * Min_Data = 0 and Max_Data = 1
+ */
+ uint8_t type; /* Endpoint type */
+ uint8_t data_pid_start; /* Initial data PID
+ * This parameter must be a number between
+ * Min_Data = 0 and Max_Data = 1
+ */
+ uint8_t even_odd_frame; /* IFrame parity
+ * This parameter must be a number between
+ * Min_Data = 0 and Max_Data = 1
+ */
+ uint16_t tx_fifo_num; /* Transmission FIFO number
+ * This parameter must be a number between
+ * Min_Data = 1 and Max_Data = 15
+ */
+ uint32_t maxpacket; /* Endpoint Max packet size
+ * This parameter must be a number between
+ * Min_Data = 0 and Max_Data = 64KB
+ */
+ uint8_t *xfer_buff; /* Pointer to transfer buffer */
+ uint32_t dma_addr; /* 32 bits aligned transfer buffer address */
+ uint32_t xfer_len; /* Current transfer length */
+ uint32_t xfer_count; /* Partial transfer length in case of multi
+ * packet transfer
+ */
+} usb_otg_ep_t;
+
+typedef enum {
+ HAL_PCD_STATE_RESET = 0x00,
+ HAL_PCD_STATE_READY = 0x01,
+ HAL_PCD_STATE_ERROR = 0x02,
+ HAL_PCD_STATE_BUSY = 0x03,
+ HAL_PCD_STATE_TIMEOUT = 0x04
+} pcd_state_t;
+
+typedef enum {
+ LPM_L0 = 0x00, /* on */
+ LPM_L1 = 0x01, /* LPM L1 sleep */
+ LPM_L2 = 0x02, /* suspend */
+ LPM_L3 = 0x03, /* off */
+} pcd_lpm_state_t;
+
+/* USB Device descriptors structure */
+typedef struct {
+ usb_status_t (*disable_int)(void *handle);
+ usb_status_t (*ep0_out_start)(void *handle);
+ usb_status_t (*ep_start_xfer)(void *handle, usb_otg_ep_t *ep);
+ usb_status_t (*ep0_start_xfer)(void *handle, usb_otg_ep_t *ep);
+ usb_status_t (*write_packet)(void *handle, uint8_t *src,
+ uint8_t ch_ep_num, uint16_t len);
+ void * (*read_packet)(void *handle, uint8_t *dest, uint16_t len);
+ usb_status_t (*ep_set_stall)(void *handle, usb_otg_ep_t *ep);
+ usb_status_t (*stop_device)(void *handle);
+ usb_status_t (*set_address)(void *handle, uint8_t address);
+ usb_status_t (*dev_disconnect)(void *handle);
+ usb_status_t (*write_empty_tx_fifo)(void *handle,
+ uint32_t epnum, uint32_t xfer_len,
+ uint32_t *xfer_count,
+ uint32_t maxpacket,
+ uint8_t **xfer_buff);
+ usb_action_t (*it_handler)(void *handle, uint32_t *param);
+} usb_driver_t;
+
+typedef struct {
+ void *instance; /* Register base address */
+ usb_otg_cfg_t init; /* PCD required parameters */
+ usb_otg_ep_t in_ep[15]; /* IN endpoint parameters */
+ usb_otg_ep_t out_ep[15]; /* OUT endpoint parameters */
+ pcd_state_t state; /* PCD communication state */
+ uint32_t setup[12]; /* Setup packet buffer */
+ pcd_lpm_state_t lpm_state; /* LPM State */
+ uint32_t besl;
+ uint32_t lpm_active; /* Enable or disable the Link Power Management.
+ * This parameter can be set to ENABLE or DISABLE
+ */
+ void *p_data; /* Pointer to upper stack Handler*/
+ uint32_t RESERVED[4]; /* For future use */
+} pcd_handle_t;
+
+/* USB Device handle structure */
+typedef struct usb_handle {
+ uint8_t id;
+ uint32_t dev_config;
+ uint32_t dev_default_config;
+ uint32_t dev_config_status;
+ uint32_t dev_speed;
+ usb_endpoint_t ep_in[15];
+ usb_endpoint_t ep_out[15];
+ uint32_t ep0_state;
+ uint32_t ep0_data_len;
+ uint8_t dev_state;
+ uint8_t dev_old_state;
+ uint8_t dev_address;
+ uint8_t dev_connection_status;
+ uint8_t dev_test_mode;
+ uint32_t dev_remote_wakeup;
+ usb_setup_req_t request;
+ const usb_desc_t *desc;
+ usb_class_t *class;
+ void *class_data;
+ void *user_data;
+ pcd_handle_t *data;
+ const usb_driver_t *driver;
+ uint32_t RESERVED[3];
+} usb_handle_t;
+
+usb_status_t usb_core_handle_it(usb_handle_t *pdev);
+usb_status_t usb_core_receive(usb_handle_t *pdev, uint8_t ep_addr,
+ uint8_t *p_buf, uint32_t len);
+usb_status_t usb_core_transmit(usb_handle_t *pdev, uint8_t ep_addr,
+ uint8_t *p_buf, uint32_t len);
+void usb_core_ctl_error(usb_handle_t *pdev);
+usb_status_t usb_core_stop(usb_handle_t *pdev);
+usb_status_t register_usb_driver(usb_handle_t *pdev, const usb_driver_t *driver,
+ void *driver_handle);
+usb_status_t register_platform(usb_handle_t *pdev,
+ const usb_desc_t *plat_call_back);
+
+#endif /* __USBD_CORE_H */
diff --git a/include/lib/usb/usb_st_dfu.h b/include/lib/usb/usb_st_dfu.h
new file mode 100644
index 0000000..3709683
--- /dev/null
+++ b/include/lib/usb/usb_st_dfu.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USB_DFU_H
+#define __USB_DFU_H
+
+#include <stdint.h>
+#include <usb_core.h>
+
+#define DFU_DESCRIPTOR_TYPE 0x21
+
+/* bmAttribute :
+ * bitCanDnload = 1(bit 0)
+ * bitCanUpload = 1(bit 1)
+ * bitManifestationTolerant = 1 (bit 2)
+ * bitWillDetach = 1(bit 3)
+ * Reserved (bit4-6)
+ * bitAcceleratedST = 0(bit 7)
+ */
+#define DFU_BM_ATTRIBUTE 0x0F
+
+#define DFU_GET_PHASE 0x5
+
+/* DFU Requests DFU states */
+#define APP_STATE_IDLE 0
+#define APP_STATE_DETACH 1
+#define DFU_STATE_IDLE 2
+#define DFU_STATE_DNLOAD_SYNC 3
+#define DFU_STATE_DNLOAD_BUSY 4
+#define DFU_STATE_DNLOAD_IDLE 5
+#define DFU_STATE_MANIFEST_SYNC 6
+#define DFU_STATE_MANIFEST 7
+#define DFU_STATE_MANIFEST_WAIT_RESET 8
+#define DFU_STATE_UPLOAD_IDLE 9
+#define DFU_STATE_ERROR 10
+
+/* DFU errors */
+#define DFU_ERROR_NONE 0x00
+#define DFU_ERROR_TARGET 0x01
+#define DFU_ERROR_FILE 0x02
+#define DFU_ERROR_WRITE 0x03
+#define DFU_ERROR_ERASE 0x04
+#define DFU_ERROR_CHECK_ERASED 0x05
+#define DFU_ERROR_PROG 0x06
+#define DFU_ERROR_VERIFY 0x07
+#define DFU_ERROR_ADDRESS 0x08
+#define DFU_ERROR_NOTDONE 0x09
+#define DFU_ERROR_FIRMWARE 0x0A
+#define DFU_ERROR_VENDOR 0x0B
+#define DFU_ERROR_USB 0x0C
+#define DFU_ERROR_POR 0x0D
+#define DFU_ERROR_UNKNOWN 0x0E
+#define DFU_ERROR_STALLEDPKT 0x0F
+
+/* DFU Manifestation State */
+#define DFU_MANIFEST_COMPLETE 0x00
+#define DFU_MANIFEST_IN_PROGRESS 0x01
+
+/* Special Commands with Download Request */
+#define DFU_CMD_GETCOMMANDS 0x00
+#define DFU_CMD_SETADDRESSPOINTER 0x21
+#define DFU_CMD_ERASE 0x41
+
+#define DFU_MEDIA_STATE_READY 0x00
+#define DFU_MEDIA_STATE_WRITTEN 0x01
+#define DFU_MEDIA_STATE_ERROR 0x02
+
+/* Bit Detach capable = bit 3 in bmAttributes field */
+#define DFU_DETACH_MASK (uint8_t)(1 << 4)
+#define DFU_STATUS_DEPTH (6)
+
+/* Undefined download address */
+#define UNDEFINE_DOWN_ADDR 0xFFFFFFFF
+
+typedef enum {
+ DFU_DETACH = 0,
+ DFU_DNLOAD,
+ DFU_UPLOAD,
+ DFU_GETSTATUS,
+ DFU_CLRSTATUS,
+ DFU_GETSTATE,
+ DFU_ABORT
+} dfu_request_t;
+
+typedef void (*p_function)(void);
+
+typedef struct {
+ uint8_t buffer[10];
+ uint8_t dev_state;
+ uint8_t dev_status[DFU_STATUS_DEPTH];
+ uint8_t manif_state;
+ uint32_t wblock_num;
+ uint32_t wlength;
+ uintptr_t data_ptr;
+ uint32_t alt_setting;
+} usb_dfu_handle_t;
+
+typedef struct {
+ uint16_t (*write_done)(uint32_t *written_in, uint32_t len);
+ uint8_t* (*read)(uint8_t *src, uint8_t *dest, uint32_t len);
+ uint16_t (*get_status)(void);
+} usb_dfu_media_t;
+
+void usb_dfu_register_callback(usb_handle_t *pdev);
+void usb_dfu_set_phase_id(uint32_t phase_id);
+void usb_dfu_set_download_addr(uintptr_t addr);
+uint32_t usb_dfu_download_is_completed(void);
+uint32_t usb_dfu_get_current_req(void);
+uint32_t usb_dfu_detach_req(void);
+void usb_dfu_request_detach(void);
+
+#endif /* __USB_DFU_H */
diff --git a/include/lib/utils.h b/include/lib/utils.h
index d46d846..b6ab26e 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -4,8 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __UTILS_H__
-#define __UTILS_H__
+#ifndef UTILS_H
+#define UTILS_H
/*
* C code should be put in this part of the header to avoid breaking ASM files
@@ -67,6 +67,29 @@ void zero_normalmem(void *mem, u_register_t length);
* zeroing.
*/
void zeromem(void *mem, u_register_t length);
+
+/*
+ * Utility function to return the address of a symbol. By default, the
+ * compiler generates adr/adrp instruction pair to return the reference
+ * to the symbol and this utility is used to override this compiler
+ * generated to code to use `ldr` instruction.
+ *
+ * This helps when Position Independent Executable needs to reference a symbol
+ * which is constant and does not depend on the execute address of the binary.
+ */
+#define DEFINE_LOAD_SYM_ADDR(_name) \
+static inline u_register_t load_addr_## _name(void) \
+{ \
+ u_register_t v; \
+ /* Create a void reference to silence compiler */ \
+ (void) _name; \
+ __asm__ volatile ("ldr %0, =" #_name : "=r" (v)); \
+ return v; \
+}
+
+/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
+#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name()
+
#endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */
-#endif /* __UTILS_H__ */
+#endif /* UTILS_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 5b4fd78..51863d8 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -30,11 +30,19 @@
* position @h. For example
* GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
+#if defined(__LINKER__) || defined(__ASSEMBLY__)
+#define GENMASK_32(h, l) \
+ (((0xFFFFFFFF) << (l)) & (0xFFFFFFFF >> (32 - 1 - (h))))
+
+#define GENMASK_64(h, l) \
+ ((~0 << (l)) & (~0 >> (64 - 1 - (h))))
+#else
#define GENMASK_32(h, l) \
(((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h))))
#define GENMASK_64(h, l) \
(((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h))))
+#endif
#ifdef AARCH32
#define GENMASK GENMASK_32
@@ -50,7 +58,17 @@
#define div_round_up(val, div) __extension__ ({ \
__typeof__(div) _div = (div); \
- ((val) + _div - 1) / _div; \
+ ((val) + _div - (__typeof__(div)) 1) / _div; \
+})
+
+/*
+ * Macro for unsigned integer division with nearest rounding variant.
+ * Default integer division rounds down.
+ */
+#define udiv_round_nearest(x, y) __extension__ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(y) _y = (y); \
+ (_x + (_y / 2)) / _y; \
})
#define MIN(x, y) __extension__ ({ \
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index fa89958..c9504b3 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -120,6 +120,37 @@ struct xlat_ctx {
/* do nothing */
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+#ifdef PLAT_XLAT_BASE
+#define tf_xlat_tables (void *)PLAT_XLAT_BASE
+
+#define XLAT_TABLES(_ctx_name, _xlat_tables_count, _section_name) \
+ CASSERT(!(PLAT_XLAT_BASE & (XLAT_TABLE_SIZE - 1)), \
+ invalid_plat_xlat_base); \
+ CASSERT(PLAT_XLAT_SIZE >= (sizeof(uint64_t) * \
+ XLAT_TABLE_ENTRIES * _xlat_tables_count), \
+ invalid_plat_xlat_size);
+
+#else
+#define XLAT_TABLES(_ctx_name, _xlat_tables_count, _section_name) \
+ static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count][XLAT_TABLE_ENTRIES] \
+ __aligned(XLAT_TABLE_SIZE) __section(_section_name);
+#endif
+
+#ifdef PLAT_BASE_XLAT_BASE
+#define tf_base_xlat_table (void *)PLAT_BASE_XLAT_BASE
+
+#define BASE_XLAT_TABLE(_ctx_name, _virt_addr_space_size) \
+ CASSERT(!(PLAT_BASE_XLAT_BASE & \
+ ((GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size) * \
+ sizeof(uint64_t)) - 1)), invalid_plat_base_xlat_cfg);
+#else
+#define BASE_XLAT_TABLE(_ctx_name, _virt_addr_space_size) \
+ static uint64_t _ctx_name##_base_xlat_table \
+ [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \
+ __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size) * \
+ sizeof(uint64_t));
+#endif
+
#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
_xlat_tables_count, _virt_addr_space_size, \
_phy_addr_space_size, _xlat_regime, _section_name)\
@@ -131,14 +162,8 @@ struct xlat_ctx {
\
static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \
\
- static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \
- [XLAT_TABLE_ENTRIES] \
- __aligned(XLAT_TABLE_SIZE) __section(_section_name); \
- \
- static uint64_t _ctx_name##_base_xlat_table \
- [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \
- __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
- * sizeof(uint64_t)); \
+ XLAT_TABLES(_ctx_name, _xlat_tables_count, _section_name) \
+ BASE_XLAT_TABLE(_ctx_name, _virt_addr_space_size) \
\
XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \
\
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index a30b579..1a6161e 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -93,6 +93,11 @@ unsigned int plat_ic_get_interrupt_id(unsigned int raw);
******************************************************************************/
uintptr_t plat_get_my_stack(void);
void plat_report_exception(unsigned int exception_type);
+#if AARCH32_EXCEPTION_DEBUG
+void plat_report_undef_inst(unsigned int fault_address);
+void plat_report_prefetch_abort(unsigned int fault_address);
+void plat_report_data_abort(unsigned int fault_address);
+#endif
int plat_crash_console_init(void);
int plat_crash_console_putc(int c);
int plat_crash_console_flush(void);
diff --git a/lib/compiler-rt/builtins/int_lib.h b/lib/compiler-rt/builtins/int_lib.h
index 787777a..80a7c41 100644
--- a/lib/compiler-rt/builtins/int_lib.h
+++ b/lib/compiler-rt/builtins/int_lib.h
@@ -27,27 +27,28 @@
#if defined(__ELF__)
#define FNALIAS(alias_name, original_name) \
- void alias_name() __attribute__((alias(#original_name)))
+ void alias_name() __attribute__((__alias__(#original_name)))
+#define COMPILER_RT_ALIAS(aliasee) __attribute__((__alias__(#aliasee)))
#else
#define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")")
+#define COMPILER_RT_ALIAS(aliasee) _Pragma("GCC error(\"alias unsupported on this file format\")")
#endif
/* ABI macro definitions */
#if __ARM_EABI__
-# define ARM_EABI_FNALIAS(aeabi_name, name) \
- void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
# ifdef COMPILER_RT_ARMHF_TARGET
# define COMPILER_RT_ABI
# else
-# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+# define COMPILER_RT_ABI __attribute__((__pcs__("aapcs")))
# endif
#else
-# define ARM_EABI_FNALIAS(aeabi_name, name)
# define COMPILER_RT_ABI
#endif
-#ifdef _MSC_VER
+#define AEABI_RTABI __attribute__((__pcs__("aapcs")))
+
+#if defined(_MSC_VER) && !defined(__clang__)
#define ALWAYS_INLINE __forceinline
#define NOINLINE __declspec(noinline)
#define NORETURN __declspec(noreturn)
diff --git a/lib/compiler-rt/builtins/lshrdi3.c b/lib/compiler-rt/builtins/lshrdi3.c
new file mode 100644
index 0000000..67b2a76
--- /dev/null
+++ b/lib/compiler-rt/builtins/lshrdi3.c
@@ -0,0 +1,45 @@
+/* ===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __lshrdi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Returns: logical a >> b */
+
+/* Precondition: 0 <= b < bits_in_dword */
+
+COMPILER_RT_ABI di_int
+__lshrdi3(di_int a, si_int b)
+{
+ const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
+ udwords input;
+ udwords result;
+ input.all = a;
+ if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */
+ {
+ result.s.high = 0;
+ result.s.low = input.s.high >> (b - bits_in_word);
+ }
+ else /* 0 <= b < bits_in_word */
+ {
+ if (b == 0)
+ return a;
+ result.s.high = input.s.high >> b;
+ result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b);
+ }
+ return result.all;
+}
+
+#if defined(__ARM_EABI__)
+AEABI_RTABI di_int __aeabi_llsr(di_int a, si_int b) COMPILER_RT_ALIAS(__lshrdi3);
+#endif
diff --git a/lib/compiler-rt/compiler-rt.mk b/lib/compiler-rt/compiler-rt.mk
index cb5ab31..49e497e 100644
--- a/lib/compiler-rt/compiler-rt.mk
+++ b/lib/compiler-rt/compiler-rt.mk
@@ -31,5 +31,6 @@
ifeq (${ARCH},aarch32)
COMPILER_RT_SRCS := lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \
lib/compiler-rt/builtins/udivmoddi4.c \
- lib/compiler-rt/builtins/ctzdi2.c
+ lib/compiler-rt/builtins/ctzdi2.c \
+ lib/compiler-rt/builtins/lshrdi3.c
endif
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 0459098..88aeb59 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -597,7 +597,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
- return -length;
+ return length;
len = strlen(string) + 1;
end = list + length;
diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c
index 34d095b..0f1e560 100644
--- a/lib/optee/optee_utils.c
+++ b/lib/optee/optee_utils.c
@@ -132,6 +132,36 @@ static int parse_optee_image(image_info_t *image_info,
}
/*******************************************************************************
+ * Parse the OPTEE header for an executable entry point address.
+ * Return 1 on success, 0 on failure.
+ ******************************************************************************/
+int get_optee_header_ep(entry_point_info_t *header_ep, uintptr_t *pc)
+{
+ optee_header_t *optee_header;
+ int num;
+
+ assert(pc && header_ep && header_ep->pc);
+ optee_header = (optee_header_t *)header_ep->pc;
+
+ if (!tee_validate_header(optee_header))
+ return 0;
+
+ for (num = 0; num < optee_header->nb_images; num++) {
+ optee_image_t *optee_image =
+ &optee_header->optee_image_list[num];
+
+ if (optee_image->image_id != OPTEE_PAGER_IMAGE_ID)
+ continue;
+
+ *pc = ((uint64_t)optee_image->load_addr_hi << 32) |
+ optee_image->load_addr_lo;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
* Parse the OPTEE header
* Return 0 on success or a negative error code otherwise.
******************************************************************************/
diff --git a/lib/usb/usb_core.c b/lib/usb/usb_core.c
new file mode 100644
index 0000000..240c1c1
--- /dev/null
+++ b/lib/usb/usb_core.c
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <debug.h>
+#include "usb_core.h"
+
+/*
+ * @brief Set a STALL condition over an endpoint
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval HAL status
+ */
+static usb_status_t usb_core_set_stall(usb_handle_t *pdev, uint8_t ep_addr)
+{
+ usb_otg_ep_t *ep;
+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data;
+
+ if ((0x80 & ep_addr) == 0x80)
+ ep = &hpcd->in_ep[ep_addr & 0x7F];
+ else
+ ep = &hpcd->out_ep[ep_addr];
+
+ ep->is_stall = 1;
+ ep->num = ep_addr & 0x7F;
+ ep->is_in = ((ep_addr & 0x80) == 0x80);
+
+ pdev->driver->ep_set_stall(hpcd->instance, ep);
+ if ((ep_addr & 0x7F) == 0)
+ pdev->driver->ep0_out_start(hpcd->instance);
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_get_desc
+ * Handle Get Descriptor requests
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static void usb_core_get_desc(usb_handle_t *pdev,
+ usb_setup_req_t *req)
+{
+ uint16_t len;
+ uint8_t *pbuf;
+
+ switch (req->value >> 8) {
+ case USB_DESC_TYPE_DEVICE:
+ pbuf = pdev->desc->get_device_desc(&len);
+ break;
+
+ case USB_DESC_TYPE_CONFIGURATION:
+ pbuf = (uint8_t *)pdev->desc->get_hs_config_desc(&len);
+ pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+ break;
+
+ case USB_DESC_TYPE_STRING:
+ switch ((uint8_t)(req->value)) {
+ case USBD_IDX_LANGID_STR:
+ pbuf = pdev->desc->get_lang_id_desc(&len);
+ break;
+
+ case USBD_IDX_MFC_STR:
+ pbuf = pdev->desc->get_manufacturer_desc(&len);
+ break;
+
+ case USBD_IDX_PRODUCT_STR:
+ pbuf = pdev->desc->get_product_desc(&len);
+ break;
+
+ case USBD_IDX_SERIAL_STR:
+ pbuf = pdev->desc->get_serial_desc(&len);
+ break;
+
+ case USBD_IDX_CONFIG_STR:
+ pbuf = pdev->desc->get_configuration_desc(&len);
+ break;
+
+ case USBD_IDX_INTERFACE_STR:
+ pbuf = pdev->desc->get_interface_desc(&len);
+ break;
+
+ default:
+ pbuf = pdev->desc->get_usr_desc(req->value, &len);
+ break;
+ }
+ break;
+
+ case USB_DESC_TYPE_DEVICE_QUALIFIER:
+ pbuf = (uint8_t *)pdev->desc->get_device_qualifier_desc(&len);
+ break;
+
+ case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
+ pbuf = (uint8_t *)pdev->desc->get_other_speed_config_desc(&len);
+ pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
+ break;
+
+ default:
+ ERROR("Unknown request %i\n", req->value >> 8);
+ usb_core_ctl_error(pdev);
+ return;
+ }
+
+ if ((len != 0) && (req->length != 0)) {
+ len = MIN(len, req->length);
+
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = len;
+ pdev->ep_in[0].rem_length = len;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00, pbuf, len);
+ }
+}
+
+/*
+ * usb_core_set_config
+ * Handle Set device configuration request
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static void usb_core_set_config(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ static uint8_t cfgidx;
+
+ cfgidx = (uint8_t)(req->value);
+
+ if (cfgidx > USBD_MAX_NUM_CONFIGURATION) {
+ usb_core_ctl_error(pdev);
+ } else {
+ switch (pdev->dev_state) {
+ case USBD_STATE_ADDRESSED:
+ if (cfgidx) {
+ pdev->dev_config = cfgidx;
+ pdev->dev_state = USBD_STATE_CONFIGURED;
+ if (!pdev->class) {
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ /* Set configuration and Start the Class*/
+ if (pdev->class->init(pdev, cfgidx) != 0) {
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ }
+ break;
+
+ case USBD_STATE_CONFIGURED:
+ if (cfgidx == 0) {
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ pdev->dev_config = cfgidx;
+ pdev->class->de_init(pdev, cfgidx);
+ } else if (cfgidx != pdev->dev_config) {
+ if (!pdev->class) {
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ /* Clear old configuration */
+ pdev->class->de_init(pdev, pdev->dev_config);
+
+ /* set new configuration */
+ pdev->dev_config = cfgidx;
+ /* Set configuration and Start the Class*/
+ if (pdev->class->init(pdev, cfgidx) != 0) {
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ }
+ break;
+
+ default:
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+ /* Send status */
+ usb_core_transmit(pdev, 0, NULL, 0);
+ }
+}
+
+/*
+ * usb_core_get_status
+ * Handle Get Status request
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static void usb_core_get_status(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ if ((pdev->dev_state == USBD_STATE_ADDRESSED) ||
+ (pdev->dev_state == USBD_STATE_CONFIGURED)) {
+ pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
+
+ if (pdev->dev_remote_wakeup)
+ pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
+
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = 2;
+ pdev->ep_in[0].rem_length = 2;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00,
+ (uint8_t *)&pdev->dev_config_status, 2);
+ return;
+ }
+
+ usb_core_ctl_error(pdev);
+}
+
+/*
+ * usb_core_set_address
+ * Set device address
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static void usb_core_set_address(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ if ((req->index == 0) && (req->length == 0)) {
+ uint8_t dev_addr = (uint8_t)(req->value) & 0x7F;
+
+ if (pdev->dev_state == USBD_STATE_CONFIGURED) {
+ usb_core_ctl_error(pdev);
+ } else {
+ pdev->dev_address = dev_addr;
+ pdev->driver->set_address(((pcd_handle_t *)
+ (pdev->data))->instance,
+ dev_addr);
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+ /* Send status */
+ usb_core_transmit(pdev, 0, NULL, 0);
+
+ if (dev_addr != 0)
+ pdev->dev_state = USBD_STATE_ADDRESSED;
+ else
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ }
+ } else {
+ usb_core_ctl_error(pdev);
+ }
+}
+
+/*
+ * usb_core_dev_req
+ * Handle standard usb device requests
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static usb_status_t usb_core_dev_req(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ INFO("receive request %i\n", req->b_request);
+ switch (req->b_request) {
+ case USB_REQ_GET_DESCRIPTOR:
+ usb_core_get_desc(pdev, req);
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ usb_core_set_config(pdev, req);
+ break;
+
+ case USB_REQ_GET_STATUS:
+ usb_core_get_status(pdev, req);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ usb_core_set_address(pdev, req);
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ case USB_REQ_SET_FEATURE:
+ case USB_REQ_CLEAR_FEATURE:
+ default:
+ ERROR("NOT SUPPORTED %i\n", req->b_request);
+ usb_core_ctl_error(pdev);
+ break;
+ }
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_itf_req
+ * Handle standard usb interface requests
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static usb_status_t usb_core_itf_req(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ switch (pdev->dev_state) {
+ case USBD_STATE_CONFIGURED:
+ if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) {
+ pdev->class->setup(pdev, req);
+
+ if (req->length == 0) {
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+
+ usb_core_transmit(pdev, 0, NULL, 0);
+ }
+ } else {
+ usb_core_ctl_error(pdev);
+ }
+ break;
+
+ default:
+ usb_core_ctl_error(pdev);
+ break;
+ }
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_ParseSetupRequest
+ * Copy buffer into setup structure
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+static void usb_core_parse_req(usb_setup_req_t *req, uint8_t *pdata)
+{
+ req->bm_request = *(uint8_t *)(pdata);
+ req->b_request = *(uint8_t *)(pdata + 1);
+ req->value = SWAPBYTE(pdata + 2);
+ req->index = SWAPBYTE(pdata + 4);
+ req->length = SWAPBYTE(pdata + 6);
+}
+
+/*
+ * usb_core_setup_stage
+ * Handle the setup stage
+ * pdev: device instance
+ * return : status
+ */
+static usb_status_t usb_core_setup_stage(usb_handle_t *pdev, uint8_t *psetup)
+{
+ usb_core_parse_req(&pdev->request, psetup);
+
+ pdev->ep0_state = USBD_EP0_SETUP;
+ pdev->ep0_data_len = pdev->request.length;
+
+ switch (pdev->request.bm_request & 0x1F) {
+ case USB_REQ_RECIPIENT_DEVICE:
+ usb_core_dev_req(pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ usb_core_itf_req(pdev, &pdev->request);
+ break;
+
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ default:
+ ERROR("receive unsupported request %i",
+ pdev->request.bm_request & 0x1F);
+ usb_core_set_stall(pdev, pdev->request.bm_request & 0x80);
+ return USBD_FAIL;
+ }
+ return USBD_OK;
+}
+
+/*
+ * usb_core_data_out
+ * Handle data OUT stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return : status
+ */
+static usb_status_t usb_core_data_out(usb_handle_t *pdev, uint8_t epnum,
+ uint8_t *pdata)
+{
+ usb_endpoint_t *pep;
+
+ if (epnum == 0) {
+ pep = &pdev->ep_out[0];
+ if (pdev->ep0_state == USBD_EP0_DATA_OUT) {
+ if (pep->rem_length > pep->maxpacket) {
+ pep->rem_length -= pep->maxpacket;
+
+ usb_core_receive(pdev, 0, pdata,
+ MIN(pep->rem_length,
+ pep->maxpacket));
+ } else {
+ if (pdev->class->ep0_rx_ready &&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ pdev->class->ep0_rx_ready(pdev);
+
+ pdev->ep0_state = USBD_EP0_STATUS_IN;
+ usb_core_transmit(pdev, 0x00, NULL, 0);
+ }
+ }
+ } else if (pdev->class->data_out &&
+ (pdev->dev_state == USBD_STATE_CONFIGURED))
+ pdev->class->data_out(pdev, epnum);
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_data_in
+ * Handle data in stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return : status
+ */
+static usb_status_t usb_core_data_in(usb_handle_t *pdev, uint8_t epnum,
+ uint8_t *pdata)
+{
+ if (epnum == 0) {
+ usb_endpoint_t *pep = &pdev->ep_in[0];
+
+ if (pdev->ep0_state == USBD_EP0_DATA_IN) {
+ if (pep->rem_length > pep->maxpacket) {
+ pep->rem_length -= pep->maxpacket;
+
+ usb_core_transmit(pdev, 0, pdata,
+ pep->rem_length);
+
+ /* Prepare endpoint for premature
+ * end of transfer
+ */
+ usb_core_receive(pdev, 0, NULL, 0);
+ } else {
+ /* last packet is MPS multiple,
+ * so send ZLP packet
+ */
+ if ((pep->total_length % pep->maxpacket == 0) &&
+ (pep->total_length >= pep->maxpacket) &&
+ (pep->total_length < pdev->ep0_data_len)) {
+ usb_core_transmit(pdev, 0, NULL, 0);
+
+ pdev->ep0_data_len = 0;
+
+ /* Prepare endpoint for premature
+ * end of transfer
+ */
+ usb_core_receive(pdev, 0, NULL, 0);
+ } else {
+ if (pdev->class->ep0_tx_sent &&
+ (pdev->dev_state ==
+ USBD_STATE_CONFIGURED))
+ pdev->class->ep0_tx_sent(pdev);
+
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_STATUS_OUT;
+
+ /* Start the transfer */
+ usb_core_receive(pdev, 0, NULL, 0);
+ }
+ }
+ }
+ if (pdev->dev_test_mode == 1) {
+ ERROR("Not supported");
+ pdev->dev_test_mode = 0;
+ return USBD_FAIL;
+ }
+ } else if (pdev->class->data_in &&
+ (pdev->dev_state == USBD_STATE_CONFIGURED)) {
+ pdev->class->data_in(pdev, epnum);
+ }
+ return USBD_OK;
+}
+
+/*
+ * usb_core_Suspend
+ * Handle Suspend event
+ * pdev : device instance
+ * return : status
+ */
+
+static usb_status_t usb_core_suspend(usb_handle_t *pdev)
+{
+ INFO("USB Suspend mode\n");
+
+ pdev->dev_old_state = pdev->dev_state;
+ pdev->dev_state = USBD_STATE_SUSPENDED;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_resume
+ * Handle Resume event
+ * pdev : device instance
+ * return : status
+ */
+
+static usb_status_t usb_core_resume(usb_handle_t *pdev)
+{
+ INFO("USB Resume\n");
+ pdev->dev_state = pdev->dev_old_state;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_sof
+ * Handle SOF event
+ * pdev : device instance
+ * return : status
+ */
+
+static usb_status_t usb_core_sof(usb_handle_t *pdev)
+{
+ if (pdev->dev_state == USBD_STATE_CONFIGURED) {
+ if (pdev->class->sof)
+ pdev->class->sof(pdev);
+ }
+
+ return USBD_OK;
+}
+
+/*
+ * usb_core_DevDisconnected
+ * Handle device disconnection event
+ * pdev : device instance
+ * return : status
+ */
+static usb_status_t usb_core_disconnect(usb_handle_t *pdev)
+{
+ /* Free Class Resources */
+ pdev->dev_state = USBD_STATE_DEFAULT;
+ pdev->class->de_init(pdev, pdev->dev_config);
+
+ return USBD_OK;
+}
+
+usb_status_t usb_core_handle_it(usb_handle_t *pdev)
+{
+ uint32_t param = 0;
+ uint32_t len = 0;
+ usb_otg_ep_t *ep;
+
+ switch (pdev->driver->it_handler(pdev->data->instance, &param)) {
+ case USB_DATA_OUT:
+ usb_core_data_out(pdev, param,
+ pdev->data->out_ep[param].xfer_buff);
+ break;
+ case USB_DATA_IN:
+ usb_core_data_in(pdev, param,
+ pdev->data->in_ep[param].xfer_buff);
+ break;
+ case USB_SETUP:
+ usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup);
+ break;
+ case USB_ENUM_DONE:
+ pdev->data->init.speed = USB_OTG_SPEED_HIGH;
+ pdev->data->init.ep0_mps = USB_OTG_HS_MAX_PACKET_SIZE;
+ break;
+ case USB_READ_DATA_PACKET:
+ ep = &pdev->data->out_ep[param & USB_OTG_OUT_EPNUM_MASK];
+ len = (param & USB_OTG_OUT_COUNT_MASK) >> 0x10;
+ pdev->driver->read_packet(pdev->data->instance,
+ ep->xfer_buff, len);
+ ep->xfer_buff += len;
+ ep->xfer_count += len;
+ break;
+ case USB_READ_SETUP_PACKET:
+ ep = &pdev->data->out_ep[param & USB_OTG_OUT_EPNUM_MASK];
+ len = (param & USB_OTG_OUT_COUNT_MASK) >> 0x10;
+ pdev->driver->read_packet(pdev->data->instance,
+ (uint8_t *)pdev->data->setup, 8);
+ ep->xfer_count += len;
+ break;
+ case USB_RESUME:
+ if (pdev->data->lpm_state == LPM_L1)
+ pdev->data->lpm_state = LPM_L0;
+ else
+ usb_core_resume(pdev);
+ break;
+ case USB_SUSPEND:
+ usb_core_suspend(pdev);
+ break;
+ case USB_LPM:
+ if (pdev->data->lpm_state == LPM_L0) {
+ pdev->data->lpm_state = LPM_L1;
+ pdev->data->besl = param;
+ } else {
+ usb_core_suspend(pdev);
+ }
+ break;
+ case USB_SOF:
+ usb_core_sof(pdev);
+ break;
+ case USB_DISCONNECT:
+ usb_core_disconnect(pdev);
+ break;
+ case USB_WRITE_EMPTY:
+ pdev->driver->write_empty_tx_fifo(pdev->data->instance, param,
+ pdev->data->in_ep[param].xfer_len,
+ (uint32_t *)
+ &pdev->data->in_ep[param].xfer_count,
+ pdev->data->in_ep[param].maxpacket,
+ &pdev->data->in_ep[param].xfer_buff);
+ break;
+ case USB_NOTHING:
+ default:
+ break;
+ }
+ return USBD_OK;
+}
+
+/**
+ * @brief Receive an amount of data
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @param pBuf: pointer to the reception buffer
+ * @param len: amount of data to be received
+ * @retval HAL status
+ */
+usb_status_t usb_core_receive(usb_handle_t *pdev, uint8_t ep_addr,
+ uint8_t *buf, uint32_t len)
+{
+ usb_otg_ep_t *ep;
+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data;
+
+ ep = &hpcd->out_ep[ep_addr & 0x7F];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = buf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0;
+ ep->is_in = 0;
+ ep->num = ep_addr & 0x7F;
+
+ if ((ep_addr & 0x7F) == 0)
+ pdev->driver->ep0_start_xfer(hpcd->instance, ep);
+ else
+ pdev->driver->ep_start_xfer(hpcd->instance, ep);
+
+ return USBD_OK;
+}
+
+/*
+ * @brief Send an amount of data
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @param pBuf: pointer to the transmission buffer
+ * @param len: amount of data to be sent
+ * @retval HAL status
+ */
+usb_status_t usb_core_transmit(usb_handle_t *pdev, uint8_t ep_addr,
+ uint8_t *buf, uint32_t len)
+{
+ usb_otg_ep_t *ep;
+ pcd_handle_t *hpcd = (pcd_handle_t *)pdev->data;
+
+ ep = &hpcd->in_ep[ep_addr & 0x7F];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = buf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0;
+ ep->is_in = 1;
+ ep->num = ep_addr & 0x7F;
+
+ if ((ep_addr & 0x7F) == 0)
+ pdev->driver->ep0_start_xfer(hpcd->instance, ep);
+ else
+ pdev->driver->ep_start_xfer(hpcd->instance, ep);
+
+ return USBD_OK;
+}
+
+/*
+ * @brief usb_core_ctl_error
+ * Handle USB low level Error
+ * @param pdev: device instance
+ * @param req: usb request
+ * @retval None
+ */
+
+void usb_core_ctl_error(usb_handle_t *pdev)
+{
+ ERROR("%s : Send an ERROR\n", __func__);
+ usb_core_set_stall(pdev, 0x80);
+ usb_core_set_stall(pdev, 0);
+}
+
+/*
+ * usb_core_stop
+ * Stop the USB Device Core.
+ * pdev: Device Handle
+ * return : USBD Status
+ */
+usb_status_t usb_core_stop(usb_handle_t *pdev)
+{
+ /* Free Class Resources */
+ pdev->class->de_init(pdev, pdev->dev_config);
+
+ /* Stop the low level driver */
+ pdev->driver->disable_int(pdev->data->instance);
+ pdev->driver->stop_device(pdev->data->instance);
+ pdev->driver->dev_disconnect(pdev->data->instance);
+ return USBD_OK;
+}
+
+/*
+ * usb_core_stop
+ * Stop the USB Device Core.
+ * pdev: Device Handle
+ * return : USBD Status
+ */
+usb_status_t register_usb_driver(usb_handle_t *pdev, const usb_driver_t *driver,
+ void *driver_handle)
+{
+ /* Free Class Resources */
+ pdev->driver = driver;
+ pdev->data->instance = driver_handle;
+ return USBD_OK;
+}
+
+/*
+ * usb_core_stop
+ * Stop the USB Device Core.
+ * pdev: Device Handle
+ * return : USBD Status
+ */
+usb_status_t register_platform(usb_handle_t *pdev,
+ const usb_desc_t *plat_call_back)
+{
+ /* Free Class Resources */
+ pdev->desc = plat_call_back;
+ return USBD_OK;
+}
diff --git a/lib/usb/usb_st_dfu.c b/lib/usb/usb_st_dfu.c
new file mode 100644
index 0000000..2cf01f6
--- /dev/null
+++ b/lib/usb/usb_st_dfu.c
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <stm32mp1_usb_desc.h>
+#include <string.h>
+#include <usb_st_dfu.h>
+
+static uintptr_t usbd_dfu_download_address;
+static uint32_t usbd_dfu_phase_id;
+static uint32_t usbd_dfu_operation_complete;
+static uint32_t usbd_dfu_current_req;
+static uint32_t usbd_detach_req;
+
+/*
+ * @brief USBD_DFU_Init
+ * Initialize the DFU interface
+ * @param pdev: device instance
+ * @param cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t usb_dfu_init(usb_handle_t *pdev, uint8_t cfgidx)
+{
+ /* Nothing to do in this stage */
+ return USBD_OK;
+}
+
+/**
+ * @brief USBD_DFU_Init
+ * De-Initialize the DFU layer
+ * @param pdev: device instance
+ * @param cfgidx: Configuration index
+ * @retval status
+ */
+static uint8_t usb_dfu_de_init(usb_handle_t *pdev, uint8_t cfgidx)
+{
+ /* Nothing to do in this stage */
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_DataIn
+ * handle data IN Stage
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @retval status
+ */
+static uint8_t usb_dfu_data_in(usb_handle_t *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+
+ return USBD_OK;
+}
+
+/*
+ * @brief DFU_Leave
+ * Handles the sub-protocol DFU leave DFU mode request (leaves DFU mode
+ * and resets device to jump to user loaded code).
+ * @param pdev: device instance
+ * @retval None
+ */
+static void usb_dfu_leave(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ hdfu->manif_state = DFU_MANIFEST_COMPLETE;
+
+ if (DFU_BM_ATTRIBUTE & 0x04) {
+ hdfu->dev_state = DFU_STATE_MANIFEST_SYNC;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ } else {
+ hdfu->dev_state = DFU_STATE_MANIFEST_WAIT_RESET;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+
+ /* Disconnect the USB device */
+ usb_core_stop(pdev);
+ }
+}
+
+/*
+ * @brief USBD_DFU_EP0_RxReady
+ * handle EP0 Rx Ready event
+ * @param pdev: device instance
+ * @retval status
+ */
+static uint8_t usb_dfu_ep0_rx_ready(usb_handle_t *pdev)
+{
+ (void)pdev;
+
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_EP0_TxReady
+ * handle EP0 TRx Ready event
+ * @param pdev: device instance
+ * @retval status
+ */
+static uint8_t usb_dfu_ep0_tx_ready(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+ uint16_t len, dfu_version = 0;
+ uint8_t *serial = pdev->desc->get_dfu_desc(&len);
+
+ dfu_version = serial[len - 1] << 8 | serial[len - 2];
+
+ if (hdfu->dev_state == DFU_STATE_DNLOAD_BUSY) {
+ if (dfu_version == 0x011a) {
+ /* Decode the Special Command*/
+ if (hdfu->wblock_num == 0) {
+ if (hdfu->buffer[0] ==
+ DFU_CMD_SETADDRESSPOINTER &&
+ hdfu->wlength == 5) {
+ hdfu->data_ptr = hdfu->buffer[1];
+ hdfu->data_ptr +=
+ hdfu->buffer[2] << 8;
+ hdfu->data_ptr +=
+ hdfu->buffer[3] << 16;
+ hdfu->data_ptr +=
+ hdfu->buffer[4] << 24;
+ } else if (hdfu->buffer[0] ==
+ DFU_CMD_ERASE &&
+ hdfu->wlength == 5) {
+ hdfu->data_ptr = hdfu->buffer[1];
+ hdfu->data_ptr +=
+ hdfu->buffer[2] << 8;
+ hdfu->data_ptr +=
+ hdfu->buffer[3] << 16;
+ hdfu->data_ptr +=
+ hdfu->buffer[4] << 24;
+ } else {
+ /* Reset the global length and block number */
+ hdfu->wlength = 0;
+ hdfu->wblock_num = 0;
+ /* Call the error management function
+ * (command will be nacked)
+ */
+ usb_core_ctl_error(pdev);
+ }
+ }
+ }
+ if ((hdfu->wblock_num > 1 && dfu_version == 0x011a) ||
+ dfu_version != 0x011a) {
+ /* Perform the write operation */
+ if (((usb_dfu_media_t *)
+ pdev->user_data)->write_done((uint32_t *)
+ hdfu->data_ptr,
+ hdfu->wlength)
+ != USBD_OK)
+ return USBD_FAIL;
+ }
+
+ /* Reset the global length and block number */
+ hdfu->wlength = 0;
+ hdfu->wblock_num = 0;
+
+ /* Update the state machine */
+ hdfu->dev_state = DFU_STATE_DNLOAD_SYNC;
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ return USBD_OK;
+ } else if (hdfu->dev_state == DFU_STATE_MANIFEST) {
+ /* Manifestation in progress*/
+ /* Start leaving DFU mode */
+ usb_dfu_leave(pdev);
+ }
+
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_SOF
+ * handle SOF event
+ * @param pdev: device instance
+ * @retval status
+ */
+static uint8_t usb_dfu_sof(usb_handle_t *pdev)
+{
+ (void)pdev;
+
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_IsoINIncomplete
+ * handle data ISO IN Incomplete event
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @retval status
+ */
+static uint8_t usb_dfu_iso_in_incomplete(usb_handle_t *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_IsoOutIncomplete
+ * handle data ISO OUT Incomplete event
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @retval status
+ */
+static uint8_t usb_dfu_iso_out_incomplete(usb_handle_t *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+ return USBD_OK;
+}
+
+/*
+ * @brief USBD_DFU_DataOut
+ * handle data OUT Stage
+ * @param pdev: device instance
+ * @param epnum: endpoint index
+ * @retval status
+ */
+static uint8_t usb_dfu_data_out(usb_handle_t *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+ return USBD_OK;
+}
+
+/*
+ * @brief DFU_Detach
+ * Handles the DFU DETACH request.
+ * @param pdev: device instance
+ * @param req: pointer to the request structure.
+ * @retval None.
+ */
+static void usb_dfu_detach(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ INFO("Receive Detach\n");
+
+ if (hdfu->dev_state == DFU_STATE_IDLE ||
+ hdfu->dev_state == DFU_STATE_DNLOAD_SYNC ||
+ hdfu->dev_state == DFU_STATE_DNLOAD_IDLE ||
+ hdfu->dev_state == DFU_STATE_MANIFEST_SYNC ||
+ hdfu->dev_state == DFU_STATE_UPLOAD_IDLE) {
+ /* Update the state machine */
+ hdfu->dev_state = DFU_STATE_IDLE;
+ hdfu->dev_status[0] = DFU_ERROR_NONE;
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0; /*bwPollTimeout=0ms*/
+ hdfu->dev_status[4] = hdfu->dev_state;
+ hdfu->dev_status[5] = 0; /*iString*/
+ hdfu->wblock_num = 0;
+ }
+ hdfu->wlength = 0;
+
+ usbd_detach_req = 0;
+}
+
+/*
+ * @brief DFU_Download
+ * Handles the DFU DNLOAD request.
+ * @param pdev: device instance
+ * @param req: pointer to the request structure
+ * @retval None
+ */
+static void usb_dfu_download(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ /* Data setup request */
+ if (req->length > 0) {
+ if ((hdfu->dev_state == DFU_STATE_IDLE) ||
+ (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE)) {
+ /* Update the global length and block number */
+ hdfu->wblock_num = req->value;
+ hdfu->wlength = req->length;
+
+ /* Update the data address */
+ hdfu->data_ptr = usbd_dfu_download_address;
+
+ /* Update the state machine */
+ hdfu->dev_state = DFU_STATE_DNLOAD_SYNC;
+ hdfu->dev_status[4] = hdfu->dev_state;
+
+ /* Prepare the reception of the buffer over EP0 */
+ /* Set EP0 State */
+ pdev->ep0_state = USBD_EP0_DATA_OUT;
+ pdev->ep_out[0].total_length = hdfu->wlength;
+ pdev->ep_out[0].rem_length = hdfu->wlength;
+
+ /* Start the transfer */
+ usb_core_receive(pdev,
+ 0,
+ (uint8_t *)usbd_dfu_download_address,
+ hdfu->wlength);
+
+ usbd_dfu_download_address += hdfu->wlength;
+ } else {
+ /* Unsupported state */
+ /* Call the error management function
+ * (command will be nacked)
+ */
+ usb_core_ctl_error(pdev);
+ }
+ } else {
+ /* End of DNLOAD operation*/
+ if (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE ||
+ hdfu->dev_state == DFU_STATE_IDLE) {
+ hdfu->manif_state = DFU_MANIFEST_IN_PROGRESS;
+ hdfu->dev_state = DFU_STATE_MANIFEST_SYNC;
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ } else {
+ /* Call the error management function
+ * (command will be nacked)
+ */
+ usb_core_ctl_error(pdev);
+ }
+ }
+}
+
+/*
+ * @brief DFU_Upload
+ * Handles the DFU UPLOAD request.
+ * @param pdev: instance
+ * @param req: pointer to the request structure
+ * @retval status
+ */
+static void usb_dfu_upload(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ /* Data setup request */
+ if (req->length > 0) {
+ if ((hdfu->dev_state == DFU_STATE_IDLE) ||
+ (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) {
+ /* Update the global length and block number */
+ hdfu->wblock_num = req->value;
+ hdfu->wlength = req->length;
+
+ /* DFU GetPhase Command */
+ if (hdfu->wblock_num == 0) {
+ /* Update the state machine */
+ hdfu->dev_state = (hdfu->wlength > 3) ?
+ DFU_STATE_IDLE :
+ DFU_STATE_UPLOAD_IDLE;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+
+ INFO("UPLOAD :\n");
+ INFO("\t\tPhase ID : %i\n", usbd_dfu_phase_id);
+ INFO("\t\taddress 0x%lx\n",
+ usbd_dfu_download_address);
+
+ hdfu->buffer[0] = usbd_dfu_phase_id;
+ hdfu->buffer[1] = (uint8_t)
+ (usbd_dfu_download_address);
+ hdfu->buffer[2] = (uint8_t)
+ (usbd_dfu_download_address >>
+ 8);
+ hdfu->buffer[3] = (uint8_t)
+ (usbd_dfu_download_address >>
+ 16);
+ hdfu->buffer[4] = (uint8_t)
+ (usbd_dfu_download_address >>
+ 24);
+
+ hdfu->buffer[5] = 0x00;
+ hdfu->buffer[6] = 0x00;
+ hdfu->buffer[7] = 0x00;
+ hdfu->buffer[8] = 0x00;
+
+ if ((usbd_dfu_download_address ==
+ UNDEFINE_DOWN_ADDR) &&
+ (usbd_detach_req)) {
+ INFO("Send detach request\n");
+ hdfu->buffer[9] = 0x01;
+ pdev->ep_in[0].total_length = 10;
+ pdev->ep_in[0].rem_length = 10;
+ } else {
+ pdev->ep_in[0].total_length = 9;
+ pdev->ep_in[0].rem_length = 9;
+ }
+
+ /* Send the status data over EP0 */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00,
+ (uint8_t *)&hdfu->buffer[0],
+ pdev->ep_in[0].total_length);
+ } else {
+ /* unsupported hdfu->wblock_num */
+ ERROR("UPLOAD : Unsupported block : %i\n",
+ hdfu->wblock_num);
+
+ hdfu->dev_state = DFU_ERROR_STALLEDPKT;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+
+ /* Call the error management function
+ * (command will be nacked
+ */
+ usb_core_ctl_error(pdev);
+ }
+ } else {
+ /* Unsupported state */
+ ERROR("UPLOAD : Unsupported State\n");
+
+ hdfu->wlength = 0;
+ hdfu->wblock_num = 0;
+ /* Call the error management function
+ * (command will be nacked
+ */
+ usb_core_ctl_error(pdev);
+ }
+ } else {
+ /* No Data setup request */
+ INFO("USB : DFU : Nothing to do\n");
+ hdfu->dev_state = DFU_STATE_IDLE;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ }
+}
+
+/*
+ * @brief DFU_GetStatus
+ * Handles the DFU GETSTATUS request.
+ * @param pdev: instance
+ * @retval status
+ */
+static void usb_dfu_get_status(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+ uint16_t status;
+ uint8_t dfu_bm_attribute = DFU_BM_ATTRIBUTE;
+
+ switch (hdfu->dev_state) {
+ case DFU_STATE_DNLOAD_SYNC:
+ status = ((usb_dfu_media_t *)pdev->user_data)->get_status();
+
+ switch (status) {
+ case DFU_MEDIA_STATE_WRITTEN:
+ /* SRAM block writing is finished, checks if checksum
+ * error has been detected
+ */
+ hdfu->dev_state = DFU_STATE_DNLOAD_IDLE;
+ break;
+
+ case DFU_MEDIA_STATE_ERROR:
+ hdfu->dev_state = DFU_STATE_ERROR;
+ break;
+
+ case DFU_MEDIA_STATE_READY:
+ default:
+ /* SRAM is ready to be written */
+ hdfu->dev_state = DFU_STATE_DNLOAD_BUSY;
+ break;
+ }
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ break;
+
+ case DFU_STATE_MANIFEST_SYNC:
+ if (hdfu->manif_state == DFU_MANIFEST_IN_PROGRESS) {
+ hdfu->dev_state = DFU_STATE_MANIFEST;
+
+ hdfu->dev_status[1] = 1;/*bwPollTimeout = 1ms*/
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ } else if ((hdfu->manif_state == DFU_MANIFEST_COMPLETE) &&
+ (dfu_bm_attribute & 0x04)) {
+ INFO("USB : DFU : end of download partition : %i\n",
+ hdfu->alt_setting);
+ hdfu->dev_state = DFU_STATE_IDLE;
+ usbd_dfu_operation_complete = 1;
+
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0;
+ hdfu->dev_status[4] = hdfu->dev_state;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Send the status data over EP0 */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = 6;
+ pdev->ep_in[0].rem_length = 6;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00, (uint8_t *)&hdfu->dev_status[0], 6);
+}
+
+/*
+ * @brief DFU_ClearStatus
+ * Handles the DFU CLRSTATUS request.
+ * @param pdev: device instance
+ * @retval status
+ */
+static void usb_dfu_clear_status(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ if (hdfu->dev_state == DFU_STATE_ERROR) {
+ hdfu->dev_state = DFU_STATE_IDLE;
+ hdfu->dev_status[0] = DFU_ERROR_NONE;/*bStatus*/
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0; /*bwPollTimeout=0ms*/
+ hdfu->dev_status[4] = hdfu->dev_state;/*bState*/
+ hdfu->dev_status[5] = 0;/*iString*/
+ } else {
+ /*State Error*/
+ hdfu->dev_state = DFU_STATE_ERROR;
+ hdfu->dev_status[0] = DFU_ERROR_UNKNOWN;/*bStatus*/
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0; /*bwPollTimeout=0ms*/
+ hdfu->dev_status[4] = hdfu->dev_state;/*bState*/
+ hdfu->dev_status[5] = 0;/*iString*/
+ }
+}
+
+/*
+ * @brief DFU_GetState
+ * Handles the DFU GETSTATE request.
+ * @param pdev: device instance
+ * @retval None
+ */
+static void usb_dfu_get_state(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ /* Return the current state of the DFU interface */
+ /* Send the status data over EP0 */
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = 1;
+ pdev->ep_in[0].rem_length = 1;
+
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00, &hdfu->dev_state, 1);
+}
+
+/*
+ * @brief DFU_Abort
+ * Handles the DFU ABORT request.
+ * @param pdev: device instance
+ * @retval None
+ */
+static void usb_dfu_abort(usb_handle_t *pdev)
+{
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ if (hdfu->dev_state == DFU_STATE_IDLE ||
+ hdfu->dev_state == DFU_STATE_DNLOAD_SYNC ||
+ hdfu->dev_state == DFU_STATE_DNLOAD_IDLE ||
+ hdfu->dev_state == DFU_STATE_MANIFEST_SYNC ||
+ hdfu->dev_state == DFU_STATE_UPLOAD_IDLE) {
+ hdfu->dev_state = DFU_STATE_IDLE;
+ hdfu->dev_status[0] = DFU_ERROR_NONE;
+ hdfu->dev_status[1] = 0;
+ hdfu->dev_status[2] = 0;
+ hdfu->dev_status[3] = 0; /*bwPollTimeout=0ms*/
+ hdfu->dev_status[4] = hdfu->dev_state;
+ hdfu->dev_status[5] = 0; /*iString*/
+ hdfu->wblock_num = 0;
+ hdfu->wlength = 0;
+ }
+}
+
+/*
+ * @brief USBD_DFU_Setup
+ * Handle the DFU specific requests
+ * @param pdev: instance
+ * @param req: usb requests
+ * @retval status
+ */
+static uint8_t usb_dfu_setup(usb_handle_t *pdev, usb_setup_req_t *req)
+{
+ uint8_t *pbuf = NULL;
+ uint16_t len = 0;
+ uint8_t ret = USBD_OK;
+ usb_dfu_handle_t *hdfu = (usb_dfu_handle_t *)pdev->class_data;
+
+ VERBOSE("alt_setting %i, bmRequest : 0x%x, brequest : 0x%x\n",
+ hdfu->alt_setting, req->bm_request & USB_REQ_TYPE_MASK,
+ req->b_request);
+ switch (req->bm_request & USB_REQ_TYPE_MASK) {
+ case USB_REQ_TYPE_CLASS:
+ usbd_dfu_current_req = req->b_request;
+ if (hdfu->alt_setting == usbd_dfu_phase_id) {
+ switch (req->b_request) {
+ case DFU_DNLOAD:
+ usb_dfu_download(pdev, req);
+ break;
+
+ case DFU_UPLOAD:
+ usb_dfu_upload(pdev, req);
+ break;
+
+ case DFU_GETSTATUS:
+ usb_dfu_get_status(pdev);
+ break;
+
+ case DFU_CLRSTATUS:
+ usb_dfu_clear_status(pdev);
+ break;
+
+ case DFU_GETSTATE:
+ usb_dfu_get_state(pdev);
+ break;
+
+ case DFU_ABORT:
+ usb_dfu_abort(pdev);
+ break;
+
+ case DFU_DETACH:
+ usb_dfu_detach(pdev, req);
+ break;
+
+ default:
+ ERROR("phase ID :%i\n", usbd_dfu_phase_id);
+ usb_core_ctl_error(pdev);
+ ret = USBD_FAIL;
+ break;
+ }
+ } else if (hdfu->alt_setting == DFU_GET_PHASE) {
+ switch (req->b_request) {
+ case DFU_UPLOAD:
+ usb_dfu_upload(pdev, req);
+ break;
+
+ case DFU_GETSTATUS:
+ INFO("GETSTATUS :\n");
+ usb_dfu_get_status(pdev);
+
+ switch (hdfu->dev_state) {
+ case APP_STATE_IDLE:
+ INFO("\t\tAPP_STATE_IDLE\n");
+ break;
+ case APP_STATE_DETACH:
+ INFO("\t\tAPP_STATE_DETACH\n");
+ break;
+ case DFU_STATE_IDLE:
+ INFO("\t\tDFU_STATE_IDLE\n");
+ break;
+ case DFU_STATE_DNLOAD_SYNC:
+ INFO("\t\tDFU_STATE_DNLOAD_SYNC\n");
+ break;
+ case DFU_STATE_DNLOAD_BUSY:
+ INFO("\t\tDFU_STATE_DNLOAD_BUSY\n");
+ break;
+ case DFU_STATE_DNLOAD_IDLE:
+ INFO("\t\tDFU_STATE_DNLOAD_IDLE\n");
+ break;
+ case DFU_STATE_MANIFEST_SYNC:
+ INFO("\t\tDFU_STATE_MANIFEST_SYNC\n");
+ break;
+ case DFU_STATE_MANIFEST:
+ INFO("\t\tDFU_STATE_MANIFEST\n");
+ break;
+ case DFU_STATE_MANIFEST_WAIT_RESET:
+ INFO(
+ "\t\tDFU_STATE_MANIFEST_WAIT_RESET\n");
+ break;
+ case DFU_STATE_UPLOAD_IDLE:
+ INFO("\t\tDFU_STATE_UPLOAD_IDLE\n");
+ break;
+ case DFU_STATE_ERROR:
+ ERROR("\t\tDFU_STATE_ERROR\n");
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case DFU_CLRSTATUS:
+ INFO("Receive DFU clear status\n");
+ usb_dfu_clear_status(pdev);
+ break;
+
+ case DFU_GETSTATE:
+ INFO("GETSTATE :\n");
+ usb_dfu_get_state(pdev);
+
+ switch (hdfu->dev_state) {
+ case APP_STATE_IDLE:
+ INFO("\t\tAPP_STATE_IDLE\n");
+ break;
+ case APP_STATE_DETACH:
+ INFO("\t\tAPP_STATE_DETACH\n");
+ break;
+ case DFU_STATE_IDLE:
+ INFO("\t\tDFU_STATE_IDLE\n");
+ break;
+ case DFU_STATE_DNLOAD_SYNC:
+ INFO("\t\tDFU_STATE_DNLOAD_SYNC\n");
+ break;
+ case DFU_STATE_DNLOAD_BUSY:
+ INFO("\t\tDFU_STATE_DNLOAD_BUSY\n");
+ break;
+ case DFU_STATE_DNLOAD_IDLE:
+ INFO("\t\tDFU_STATE_DNLOAD_IDLE\n");
+ break;
+ case DFU_STATE_MANIFEST_SYNC:
+ INFO("\t\tDFU_STATE_MANIFEST_SYNC\n");
+ break;
+ case DFU_STATE_MANIFEST:
+ INFO("\t\tDFU_STATE_MANIFEST\n");
+ break;
+ case DFU_STATE_MANIFEST_WAIT_RESET:
+ INFO(
+ "\t\tDFU_STATE_MANIFEST_WAIT_RESET\n");
+ break;
+ case DFU_STATE_UPLOAD_IDLE:
+ INFO("\t\tDFU_STATE_UPLOAD_IDLE\n");
+ break;
+ case DFU_STATE_ERROR:
+ ERROR("\t\tDFU_STATE_ERROR\n");
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case DFU_ABORT:
+ INFO("Receive DFU abort\n");
+ usb_dfu_abort(pdev);
+ break;
+
+ case DFU_DETACH:
+ INFO("Receive DFU detach\n");
+ break;
+
+ default:
+ ERROR("phase ID :%i\n", DFU_GET_PHASE);
+ usb_core_ctl_error(pdev);
+ ret = USBD_FAIL;
+ break;
+ }
+ } else {
+ ERROR("Unknown alternate : %i\n", hdfu->alt_setting);
+ ret = USBD_FAIL;
+ }
+ break;
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->b_request) {
+ case USB_REQ_GET_DESCRIPTOR:
+ if ((req->value >> 8) == DFU_DESCRIPTOR_TYPE) {
+ pbuf = pdev->desc->get_dfu_desc(&len);
+ len = MIN(len, req->length);
+ }
+
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = len;
+ pdev->ep_in[0].rem_length = len;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00, pbuf, len);
+
+ break;
+
+ case USB_REQ_GET_INTERFACE:
+ pdev->ep0_state = USBD_EP0_DATA_IN;
+ pdev->ep_in[0].total_length = 1;
+ pdev->ep_in[0].rem_length = 1;
+ /* Start the transfer */
+ usb_core_transmit(pdev, 0x00,
+ (uint8_t *)&hdfu->alt_setting, 1);
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ hdfu->alt_setting = (uint8_t)(req->value);
+ break;
+
+ default:
+ usb_core_ctl_error(pdev);
+ ret = USBD_FAIL;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static const usb_class_t USBD_DFU_initvalue = {
+ usb_dfu_init,
+ usb_dfu_de_init,
+ usb_dfu_setup,
+ usb_dfu_ep0_tx_ready,
+ usb_dfu_ep0_rx_ready,
+ usb_dfu_data_in,
+ usb_dfu_data_out,
+ usb_dfu_sof,
+ usb_dfu_iso_in_incomplete,
+ usb_dfu_iso_out_incomplete,
+ 0
+};
+
+void usb_dfu_register_callback(usb_handle_t *pdev)
+{
+ pdev->class = (usb_class_t *)&USBD_DFU_initvalue;
+}
+
+void usb_dfu_set_phase_id(uint32_t phase_id)
+{
+ usbd_dfu_phase_id = phase_id;
+ usbd_dfu_operation_complete = 0;
+}
+
+void usb_dfu_set_download_addr(uintptr_t addr)
+{
+ usbd_dfu_download_address = addr;
+}
+
+uint32_t usb_dfu_download_is_completed(void)
+{
+ return usbd_dfu_operation_complete;
+}
+
+uint32_t usb_dfu_get_current_req(void)
+{
+ return usbd_dfu_current_req;
+}
+
+uint32_t usb_dfu_detach_req(void)
+{
+ return usbd_detach_req;
+}
+
+void usb_dfu_request_detach(void)
+{
+ usbd_detach_req = 1;
+}
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index 5595703..27e7207 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -23,8 +23,17 @@
#define NUM_BASE_LEVEL_ENTRIES \
GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)
+#ifdef PLAT_BASE_XLAT_BASE
+CASSERT(!(PLAT_BASE_XLAT_BASE &
+ (NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t) - 1)),
+ invalid_plat_base_xlat_base);
+CASSERT(PLAT_BASE_XLAT_SIZE == sizeof(uint64_t) * NUM_BASE_LEVEL_ENTRIES,
+ invalid_plat_base_xlat_size);
+static uint64_t *base_xlation_table = (uint64_t *)PLAT_BASE_XLAT_BASE;
+#else
static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES]
__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
+#endif
#if ENABLE_ASSERTIONS
static unsigned long long get_max_supported_pa(void)
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 4afdeed..309fda1 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -22,6 +22,10 @@
#define NUM_BASE_LEVEL_ENTRIES \
GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)
+#ifdef PLAT_BASE_XLAT_BASE
+#error "PLAT_BASE_XLAT_BASE is not allowed on AArch64 capable architectures"
+#endif
+
static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES]
__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index ca67f2a..9c903f9 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -35,8 +35,17 @@
#define UNSET_DESC ~0ULL
#define MT_UNKNOWN ~0U
+#ifdef PLAT_XLAT_BASE
+#define XLAT_TABLE_REQUIRED_ENTRIES (XLAT_TABLE_ENTRIES * MAX_XLAT_TABLES)
+CASSERT(PLAT_XLAT_SIZE == sizeof(uint64_t) * XLAT_TABLE_REQUIRED_ENTRIES,
+ invalid_plat_xlat_size);
+CASSERT(!(PLAT_XLAT_BASE & (XLAT_TABLE_SIZE - 1)), invalid_plat_xlat_base);
+#define xlat_tables ((uint64_t (*)[XLAT_TABLE_ENTRIES]) \
+ (unsigned long *)PLAT_XLAT_BASE)
+#else
static uint64_t xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES]
__aligned(XLAT_TABLE_SIZE) __section("xlat_table");
+#endif
static unsigned int next_xlat;
static unsigned long long xlat_max_pa;
@@ -408,6 +417,15 @@ void init_xlation_table(uintptr_t base_va, uint64_t *table,
ap1_mask = 0ULL;
}
+#ifdef PLAT_BASE_XLAT_BASE
+ inv_dcache_range(PLAT_BASE_XLAT_BASE, PLAT_BASE_XLAT_SIZE);
+ zeromem((void *)PLAT_BASE_XLAT_BASE, PLAT_BASE_XLAT_SIZE);
+#endif
+#ifdef PLAT_XLAT_BASE
+ inv_dcache_range(PLAT_XLAT_BASE, PLAT_XLAT_SIZE);
+ zeromem((void *)PLAT_XLAT_BASE, PLAT_XLAT_SIZE);
+#endif
+
init_xlation_table_inner(mmap, base_va, table, level);
*max_va = xlat_max_va;
*max_pa = xlat_max_pa;
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index 003718e..a410ad6 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1026,7 +1026,12 @@ void init_xlat_tables_ctx(xlat_ctx_t *ctx)
xlat_mmap_print(mm);
/* All tables must be zeroed before mapping any region. */
-
+#ifdef PLAT_BASE_XLAT_BASE
+ inv_dcache_range(PLAT_BASE_XLAT_BASE, PLAT_BASE_XLAT_SIZE);
+#endif
+#ifdef PLAT_XLAT_BASE
+ inv_dcache_range(PLAT_XLAT_BASE, PLAT_XLAT_SIZE);
+#endif
for (unsigned int i = 0U; i < ctx->base_table_entries; i++)
ctx->base_table[i] = INVALID_DESC;
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 92a0f6e..44c537b 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -450,17 +450,24 @@ endef
# $(2) = input dts
define MAKE_DTB
+# List of DTB file(s) to generate, based on DTS file basename list
$(eval DOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
+# List of the pre-compiled DTS file(s)
$(eval DPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2)))))
-$(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ)))
+# Dependencies of the pre-compiled DTS file(s) on its source and included files
+$(eval DTSDEP := $(patsubst %.dtb,%.o.d,$(DOBJ)))
+# Dependencies of the DT compilation on its pre-compiled DTS
+$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ)))
$(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs
@echo " CPP $$<"
- $$(Q)$$(CPP) $$(CPPFLAGS) -x assembler-with-cpp -o $(DPRE) $$<
+ $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
+ $$(Q)$$(CPP) $$(CPPFLAGS) -x assembler-with-cpp -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$<
@echo " DTC $$<"
- $$(Q)$$(DTC) $$(DTC_FLAGS) -i fdts -d $(DEP) -o $$@ $(DPRE)
+ $$(Q)$$(DTC) $$(DTC_FLAGS) -i fdts -d $(DTBDEP) -o $$@ $(DPRE)
--include $(DEP)
+-include $(DTBDEP)
+-include $(DTSDEP)
endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 7df4cd2..0ade4e7 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -79,6 +79,9 @@ ENABLE_STACK_PROTECTOR := 0
# Flag to enable exception handling in EL3
EL3_EXCEPTION_HANDLING := 0
+# Flag to enable exception debug for AARCH32
+AARCH32_EXCEPTION_DEBUG := 0
+
# Build flag to treat usage of deprecated platform and framework APIs as error.
ERROR_DEPRECATED := 0
diff --git a/plat/arm/common/aarch32/arm_helpers.S b/plat/arm/common/aarch32/arm_helpers.S
index c4cfa8a..badddd3 100644
--- a/plat/arm/common/aarch32/arm_helpers.S
+++ b/plat/arm/common/aarch32/arm_helpers.S
@@ -48,7 +48,7 @@ func plat_crash_console_init
ldr r0, =PLAT_ARM_CRASH_UART_BASE
ldr r1, =PLAT_ARM_CRASH_UART_CLK_IN_HZ
ldr r2, =ARM_CONSOLE_BAUDRATE
- b console_core_init
+ b console_pl011_core_init
endfunc plat_crash_console_init
/* ---------------------------------------------
@@ -60,7 +60,7 @@ endfunc plat_crash_console_init
*/
func plat_crash_console_putc
ldr r1, =PLAT_ARM_CRASH_UART_BASE
- b console_core_putc
+ b console_pl011_core_putc
endfunc plat_crash_console_putc
/* ---------------------------------------------
@@ -73,5 +73,5 @@ endfunc plat_crash_console_putc
*/
func plat_crash_console_flush
ldr r0, =PLAT_ARM_CRASH_UART_BASE
- b console_core_flush
+ b console_pl011_core_flush
endfunc plat_crash_console_flush
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index a8df5ba..9d31f08 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -123,9 +123,7 @@ ENABLE_PMF := 1
SEPARATE_CODE_AND_RODATA := 1
# Use the multi console API, which is only available for AArch64 for now
-ifeq (${ARCH}, aarch64)
- MULTI_CONSOLE_API := 1
-endif
+MULTI_CONSOLE_API := 1
# Disable ARM Cryptocell by default
ARM_CRYPTOCELL_INTEG := 0
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 10c1914..b8234c1 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -9,6 +9,7 @@
#include <console.h>
#include <debug.h>
#include <mmio.h>
+#include <pl011.h>
#include <plat_arm.h>
#include <platform.h>
#include <platform_def.h>
@@ -61,8 +62,7 @@ void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config,
uintptr_t hw_config, void *plat_params_from_bl2)
{
/* Initialize the console to provide early debug support */
- console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
- ARM_CONSOLE_BAUDRATE);
+ arm_console_boot_init();
#if RESET_TO_SP_MIN
/* There are no parameters from BL2 if SP_MIN is a reset vector */
@@ -152,8 +152,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
void arm_sp_min_plat_runtime_setup(void)
{
/* Initialize the runtime console */
- console_init(PLAT_ARM_SP_MIN_RUN_UART_BASE,
- PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE);
+ arm_console_runtime_init();
}
/*******************************************************************************
diff --git a/plat/common/aarch32/crash_console_helpers.S b/plat/common/aarch32/crash_console_helpers.S
new file mode 100644
index 0000000..fc37c08
--- /dev/null
+++ b/plat/common/aarch32/crash_console_helpers.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <console.h>
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+#if MULTI_CONSOLE_API
+
+ /* -----------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Use normal console by default. Switch it to crash
+ * mode so serial consoles become active again.
+ * NOTE: This default implementation will only work for
+ * crashes that occur after a normal console (marked
+ * valid for the crash state) has been registered with
+ * the console framework. To debug crashes that occur
+ * earlier, the platform has to override these functions
+ * with an implementation that initializes a console
+ * driver with hardcoded parameters. See
+ * docs/porting-guide.rst for more information.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+ /*
+ * BL1 code can possibly crash so early that the data segment is not yet
+ * accessible. Don't risk undefined behavior by trying to run the normal
+ * console framework. Platforms that want to debug BL1 will need to
+ * override this with custom functions that can run from registers only.
+ */
+ mov r0, #0
+ bx lr
+#else /* IMAGE_BL1 */
+ mov r3, lr
+ mov r0, #CONSOLE_FLAG_CRASH
+ bl console_switch_state
+ mov r0, #1
+ bx r3
+#endif
+endfunc plat_crash_console_init
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_putc(int character)
+ * Output through the normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_putc
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Flush normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_flush
+ b console_flush
+endfunc plat_crash_console_flush
+
+#else /* MULTI_CONSOLE_API */
+
+ /* -----------------------------------------------------
+ * In the old API these are all no-op stubs that need to
+ * be overridden by the platform to be useful.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+ mov r0, #0
+ bx lr
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ bx lr
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ bx lr
+endfunc plat_crash_console_flush
+
+#endif
diff --git a/plat/common/aarch32/plat_sp_min_common.c b/plat/common/aarch32/plat_sp_min_common.c
index a9a92c7..f1b1e9c 100644
--- a/plat/common/aarch32/plat_sp_min_common.c
+++ b/plat/common/aarch32/plat_sp_min_common.c
@@ -21,5 +21,9 @@ void sp_min_plat_runtime_setup(void)
* Finish the use of console driver in SP_MIN so that any runtime logs
* from SP_MIN will be suppressed.
*/
+#if MULTI_CONSOLE_API
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+#else
console_uninit();
+#endif
}
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
index d618539..91ddc47 100644
--- a/plat/common/aarch32/platform_helpers.S
+++ b/plat/common/aarch32/platform_helpers.S
@@ -8,9 +8,16 @@
#include <asm_macros.S>
.weak plat_report_exception
+#if AARCH32_EXCEPTION_DEBUG
+ .weak plat_report_undef_inst
+ .weak plat_report_prefetch_abort
+ .weak plat_report_data_abort
+#endif
+#if !ERROR_DEPRECATED
.weak plat_crash_console_init
.weak plat_crash_console_putc
.weak plat_crash_console_flush
+#endif
.weak plat_reset_handler
.weak plat_disable_acp
.weak bl1_plat_prepare_exit
@@ -26,6 +33,36 @@ func plat_report_exception
bx lr
endfunc plat_report_exception
+#if AARCH32_EXCEPTION_DEBUG
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_undef_inst
+ bx lr
+endfunc plat_report_undef_inst
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_prefetch_abort
+ bx lr
+endfunc plat_report_prefetch_abort
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_data_abort
+ bx lr
+endfunc plat_report_data_abort
+#endif
+
+#if !ERROR_DEPRECATED
/* -----------------------------------------------------
* Placeholder function which should be redefined by
* each platform.
@@ -54,6 +91,7 @@ func plat_crash_console_flush
mov r0, #0
bx lr
endfunc plat_crash_console_flush
+#endif
/* -----------------------------------------------------
* Placeholder function which should be redefined by
diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S
new file mode 100644
index 0000000..5af8db2
--- /dev/null
+++ b/plat/common/aarch64/crash_console_helpers.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <console.h>
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+#if MULTI_CONSOLE_API
+
+ /* -----------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Use normal console by default. Switch it to crash
+ * mode so serial consoles become active again.
+ * NOTE: This default implementation will only work for
+ * crashes that occur after a normal console (marked
+ * valid for the crash state) has been registered with
+ * the console framework. To debug crashes that occur
+ * earlier, the platform has to override these functions
+ * with an implementation that initializes a console
+ * driver with hardcoded parameters. See
+ * docs/porting-guide.rst for more information.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+ /*
+ * BL1 code can possibly crash so early that the data segment is not yet
+ * accessible. Don't risk undefined behavior by trying to run the normal
+ * console framework. Platforms that want to debug BL1 will need to
+ * override this with custom functions that can run from registers only.
+ */
+ mov x0, #0
+ ret
+#else /* IMAGE_BL1 */
+ mov x3, x30
+ mov x0, #CONSOLE_FLAG_CRASH
+ bl console_switch_state
+ mov x0, #1
+ ret x3
+#endif
+endfunc plat_crash_console_init
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_putc(int character)
+ * Output through the normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_putc
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Flush normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_flush
+ b console_flush
+endfunc plat_crash_console_flush
+
+#else /* MULTI_CONSOLE_API */
+
+ /* -----------------------------------------------------
+ * In the old API these are all no-op stubs that need to
+ * be overridden by the platform to be useful.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+ mov x0, #0
+ ret
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ ret
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ ret
+endfunc plat_crash_console_flush
+
+#endif
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index 7214588..d3ffcaf 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -10,9 +10,11 @@
#include <platform_def.h>
.weak plat_report_exception
+#if !ERROR_DEPRECATED
.weak plat_crash_console_init
.weak plat_crash_console_putc
.weak plat_crash_console_flush
+#endif
.weak plat_reset_handler
.weak plat_disable_acp
.weak bl1_plat_prepare_exit
@@ -37,6 +39,7 @@ func plat_report_exception
ret
endfunc plat_report_exception
+#if !ERROR_DEPRECATED
#if MULTI_CONSOLE_API
/* -----------------------------------------------------
* int plat_crash_console_init(void)
@@ -109,6 +112,7 @@ func plat_crash_console_flush
ret
endfunc plat_crash_console_flush
#endif
+#endif /* ERROR_DEPRECATED */
/* -----------------------------------------------------
* Placeholder function which should be redefined by
diff --git a/plat/common/plat_log_common.c b/plat/common/plat_log_common.c
index 49e1c15..c757c6b 100644
--- a/plat/common/plat_log_common.c
+++ b/plat/common/plat_log_common.c
@@ -5,6 +5,7 @@
*/
#include <debug.h>
+#include <platform.h>
/* Allow platforms to override the log prefix string */
#pragma weak plat_log_get_prefix
diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S
index ad71b89..668fd62 100644
--- a/plat/imx/common/lpuart_console.S
+++ b/plat/imx/common/lpuart_console.S
@@ -6,6 +6,7 @@
#include <arch.h>
#include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
#include <assert_macros.S>
#include "imx8_lpuart.h"
@@ -26,7 +27,7 @@ func console_lpuart_register
mov x0, x6
mov x30, x7
- finish_console_register lpuart
+ finish_console_register lpuart putc=1, getc=1
register_fail:
ret x7
diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S
index 5c87465..ec4390a 100644
--- a/plat/layerscape/common/aarch64/ls_console.S
+++ b/plat/layerscape/common/aarch64/ls_console.S
@@ -6,6 +6,7 @@
#include <arch.h>
#include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
#include <console_macros.S>
#include <assert_macros.S>
#include "ls_16550.h"
@@ -106,7 +107,7 @@ func console_ls_16550_register
mov x0, x6
mov x30, x7
- finish_console_register ls_16550
+ finish_console_register ls_16550 putc=1, getc=1, flush=1
register_fail:
ret x7
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
new file mode 100644
index 0000000..263c3ba
--- /dev/null
+++ b/plat/st/common/bl2_io_storage.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_dummy.h>
+#include <io_mmc.h>
+#if STM32MP_FMC_NAND
+#include <io_nand.h>
+#endif
+#include <io_programmer_st_usb.h>
+#if STM32MP1_QSPI_NOR
+#include <io_qspi.h>
+#endif
+#include <io_stm32image.h>
+#include <io_storage.h>
+#if STM32MP_UART_PROGRAMMER
+#include <io_uart.h>
+#endif
+#include <mmc.h>
+#include <mmio.h>
+#if STM32MP_FMC_NAND
+#include <nand.h>
+#endif
+#include <partition.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32_sdmmc2.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <string.h>
+#ifdef STM32MP_USB
+#include <usb_core.h>
+#include <usb_ctx.h>
+#include <usb_dwc2.h>
+#include <usb_st_dfu.h>
+#endif
+#include <utils.h>
+
+/* IO devices */
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+
+static uintptr_t image_dev_handle;
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static io_block_spec_t gpt_block_spec = {
+ .offset = 0,
+ .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+
+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static const io_block_dev_spec_t mmc_block_dev_spec = {
+ /* It's used as temp buffer in block driver */
+ .buffer = {
+ .offset = (size_t)&block_buffer,
+ .length = MMC_BLOCK_SIZE,
+ },
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = NULL,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static uintptr_t storage_dev_handle;
+#if STM32MP_SDMMC || STM32MP_EMMC
+static const io_dev_connector_t *mmc_dev_con;
+#endif
+
+#if STM32MP1_QSPI_NOR
+static const io_dev_connector_t *qspi_dev_con;
+
+static QSPI_HandleTypeDef qspi_dev_spec = {
+ .instance = (QUADSPI_TypeDef *)STM32MP1_QSPI1_BASE,
+ .is_dual = 0,
+};
+#endif
+
+#if STM32MP_UART_PROGRAMMER
+/* uart*/
+static const io_dev_connector_t *uart_dev_con;
+
+static UART_HandleTypeDef uart_programmer = {
+ .Init.BaudRate = STM32MP_UART_BAUDRATE,
+ .Init.StopBits = UART_STOPBITS_1,
+ .Init.HwFlowCtl = UART_HWCONTROL_NONE,
+ .Init.Mode = UART_MODE_TX_RX,
+ .Init.OverSampling = UART_OVERSAMPLING_16,
+ .Init.FIFOMode = UART_FIFOMODE_ENABLE,
+ .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_AUTOBAUDRATE_INIT,
+ .AdvancedInit.AutoBaudRateEnable = UART_ADVFEATURE_AUTOBAUDRATE_DISABLE,
+};
+#endif /* STM32MP_UART_PROGRAMMER */
+
+#ifdef STM32MP_USB
+static usb_handle_t usb_core_handle;
+static usb_dfu_handle_t usb_dfu_handle;
+static pcd_handle_t pcd_handle;
+static const io_dev_connector_t *usb_dev_con;
+#endif /*STM32MP_USB*/
+
+#if STM32MP_FMC_NAND
+/* nand */
+static const io_dev_connector_t *nand_dev_con;
+static NAND_HandleTypeDef nand_dev_spec;
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+static const struct stm32image_part_info optee_header_partition_spec = {
+ .name = OPTEE_HEADER_IMAGE_NAME,
+ .binary_type = OPTEE_HEADER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_pager_partition_spec = {
+ .name = OPTEE_PAGER_IMAGE_NAME,
+ .binary_type = OPTEE_PAGER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_paged_partition_spec = {
+ .name = OPTEE_PAGED_IMAGE_NAME,
+ .binary_type = OPTEE_PAGED_BINARY_TYPE,
+};
+#else
+static const io_block_spec_t bl32_block_spec = {
+ .offset = BL32_BASE,
+ .length = STM32MP_BL32_SIZE
+};
+#endif
+
+static const io_block_spec_t bl2_block_spec = {
+ .offset = BL2_BASE,
+ .length = STM32MP_BL2_SIZE,
+};
+
+static const struct stm32image_part_info bl33_partition_spec = {
+ .name = BL33_IMAGE_NAME,
+ .binary_type = BL33_BINARY_TYPE,
+};
+
+enum {
+ IMG_IDX_BL33,
+#ifdef AARCH32_SP_OPTEE
+ IMG_IDX_OPTEE_HEADER,
+ IMG_IDX_OPTEE_PAGER,
+ IMG_IDX_OPTEE_PAGED,
+#endif
+ IMG_IDX_NUM
+};
+
+static struct stm32image_device_info stm32image_dev_info_spec = {
+ .lba_size = MMC_BLOCK_SIZE,
+ .part_info[IMG_IDX_BL33] = {
+ .name = BL33_IMAGE_NAME,
+ .binary_type = BL33_BINARY_TYPE,
+ },
+#ifdef AARCH32_SP_OPTEE
+ .part_info[IMG_IDX_OPTEE_HEADER] = {
+ .name = OPTEE_HEADER_IMAGE_NAME,
+ .binary_type = OPTEE_HEADER_BINARY_TYPE,
+ },
+ .part_info[IMG_IDX_OPTEE_PAGER] = {
+ .name = OPTEE_PAGER_IMAGE_NAME,
+ .binary_type = OPTEE_PAGER_BINARY_TYPE,
+ },
+ .part_info[IMG_IDX_OPTEE_PAGED] = {
+ .name = OPTEE_PAGED_IMAGE_NAME,
+ .binary_type = OPTEE_PAGED_BINARY_TYPE,
+ },
+#endif
+};
+
+static io_block_spec_t stm32image_block_spec = {
+ .offset = 0,
+ .length = 0,
+};
+
+static const io_dev_connector_t *stm32image_dev_con;
+
+static int open_dummy(const uintptr_t spec);
+static int open_image(const uintptr_t spec);
+static int open_storage(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+ [BL2_IMAGE_ID] = {
+ .dev_handle = &dummy_dev_handle,
+ .image_spec = (uintptr_t)&bl2_block_spec,
+ .check = open_dummy
+ },
+#ifdef AARCH32_SP_OPTEE
+ [BL32_IMAGE_ID] = {
+ .dev_handle = &image_dev_handle,
+ .image_spec = (uintptr_t)&optee_header_partition_spec,
+ .check = open_image
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ .dev_handle = &image_dev_handle,
+ .image_spec = (uintptr_t)&optee_pager_partition_spec,
+ .check = open_image
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ .dev_handle = &image_dev_handle,
+ .image_spec = (uintptr_t)&optee_paged_partition_spec,
+ .check = open_image
+ },
+#else
+ [BL32_IMAGE_ID] = {
+ .dev_handle = &dummy_dev_handle,
+ .image_spec = (uintptr_t)&bl32_block_spec,
+ .check = open_dummy
+ },
+#endif
+ [BL33_IMAGE_ID] = {
+ .dev_handle = &image_dev_handle,
+ .image_spec = (uintptr_t)&bl33_partition_spec,
+ .check = open_image
+ },
+#if STM32MP_SDMMC || STM32MP_EMMC
+ [GPT_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&gpt_block_spec,
+ .check = open_storage
+ },
+#endif
+ [STM32_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&stm32image_block_spec,
+ .check = open_storage
+ }
+};
+
+static int open_dummy(const uintptr_t spec)
+{
+ return io_dev_init(dummy_dev_handle, 0);
+}
+
+static int open_image(const uintptr_t spec)
+{
+ return io_dev_init(image_dev_handle, 0);
+}
+
+static int open_storage(const uintptr_t spec)
+{
+ return io_dev_init(storage_dev_handle, 0);
+}
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+ switch (boot_context->boot_interface_selected) {
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+ INFO("Using SDMMC\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+ INFO("Using EMMC\n");
+ break;
+#if STM32MP_UART_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+ INFO("Using UART\n");
+ break;
+#endif
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+ INFO("Using NOR\n");
+ if (boot_context->nor_isdual != 0U) {
+ INFO("NOR is configured in Dual Flash Mode\n");
+ }
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+ INFO("Using NAND\n");
+ break;
+#ifdef STM32MP_USB
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ INFO("Using USB\n");
+ break;
+#endif
+#ifdef STM32MP1_QSPI_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+ INFO("Using QSPI NAND\n");
+ break;
+#endif
+ default:
+ ERROR("Boot interface not found\n");
+ panic();
+ break;
+ }
+
+ if (boot_context->boot_interface_instance != 0U) {
+ INFO(" Instance %d\n", boot_context->boot_interface_instance);
+ }
+}
+
+#if STM32MP_EMMC || STM32MP_SDMMC
+static void print_bootrom_sd_status(boot_api_context_t *boot_context)
+{
+ if (boot_context->sd_err_internal_timeout_cnt != 0U) {
+ WARN("BootROM: %d timeout issues\n",
+ boot_context->sd_err_internal_timeout_cnt);
+ }
+
+ if (boot_context->sd_err_dcrc_fail_cnt != 0U) {
+ WARN("BootROM: %d DCRCFAIL error\n",
+ boot_context->sd_err_dcrc_fail_cnt);
+ }
+
+ if (boot_context->sd_err_dtimeout_cnt != 0U) {
+ WARN("BootROM: %d DTIMEOUT error\n",
+ boot_context->sd_err_dtimeout_cnt);
+ }
+
+ if (boot_context->sd_err_ctimeout_cnt != 0U) {
+ WARN("BootROM: %d CTIMEOUT error\n",
+ boot_context->sd_err_ctimeout_cnt);
+ }
+
+ if (boot_context->sd_err_ccrc_fail_cnt != 0U) {
+ WARN("BootROM: %d CCRCFAIL error count\n",
+ boot_context->sd_err_ccrc_fail_cnt);
+ }
+
+ if (boot_context->sd_overall_retry_cnt != 0U) {
+ WARN("BootROM: %d command retries\n",
+ boot_context->sd_overall_retry_cnt);
+ }
+}
+
+static void print_bootrom_emmc_status(boot_api_context_t *boot_context)
+{
+ INFO("BootROM: %d (0x%x) bytes copied from eMMC\n",
+ boot_context->emmc_nbbytes_rxcopied_tosysram_download_area,
+ boot_context->emmc_nbbytes_rxcopied_tosysram_download_area);
+
+ if (boot_context->emmc_error_status !=
+ BOOT_API_CTX_EMMC_ERROR_STATUS_NONE) {
+ WARN("BootROM eMMC error:\n");
+ switch (boot_context->emmc_error_status) {
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT:
+ WARN(" CMD timeout\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT:
+ WARN(" ACK timeout\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL:
+ WARN(" DATA CRC failed\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX:
+ WARN(" Not enough data copied\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND:
+ WARN(" Header not found\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO:
+ WARN(" Header size is zero\n");
+ break;
+ case BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE:
+ WARN(" Image not complete\n");
+ break;
+ default:
+ WARN(" Error not listed\n");
+ break;
+ }
+ }
+
+ switch (boot_context->emmc_xfer_status) {
+ case BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED:
+ WARN("BootROM: eMMC transfer status:\n");
+ WARN(" not started\n");
+ break;
+ case BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED:
+ break;
+ case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED:
+ WARN("BootROM: eMMC transfer status:\n");
+ WARN(" timeout detected\n");
+ break;
+ case BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT:
+ WARN("BootROM: eMMC transfer status:\n");
+ WARN(" data timeout detected\n");
+ break;
+ default:
+ WARN("BootROM: eMMC transfer status:\n");
+ WARN(" status not listed\n");
+ break;
+ }
+}
+#endif
+
+
+void stm32mp_io_setup(void)
+{
+ 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);
+
+ 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) {
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+ dmbsy();
+
+#if STM32MP_EMMC || STM32MP_SDMMC
+ memset(&params, 0, sizeof(struct stm32_sdmmc2_params));
+
+ 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
+ }
+
+ 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;
+ }
+
+ params.device_info = &device_info;
+ if (stm32_sdmmc2_mmc_init(&params) != 0) {
+ ERROR("SDMMC%u init failed\n",
+ boot_context->boot_interface_instance);
+ panic();
+ }
+
+ /* Open MMC as a block device to read GPT table */
+ io_result = register_io_dev_block(&mmc_dev_con);
+ if (io_result != 0) {
+ 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);
+
+ stm32image_dev_info_spec.device_size =
+ stm32_sdmmc2_mmc_get_device_size();
+
+ 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();
+ }
+
+ part->part_offset = entry->start;
+ part->bkp_offset = 0U;
+ }
+
+ /*
+ * 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;
+
+#if STM32MP1_QSPI_NOR
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+ dmbsy();
+
+ io_result = register_io_dev_qspi(&qspi_dev_con);
+
+ 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;
+
+ /* 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);
+
+ stm32image_dev_info_spec.device_size = QSPI_NOR_MAX_SIZE;
+ stm32image_dev_info_spec.lba_size = QSPI_NOR_LBA_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;
+
+#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 = io_dev_open(stm32image_dev_con,
+ (uintptr_t)&stm32image_dev_info_spec,
+ &image_dev_handle);
+ assert(io_result == 0);
+ break;
+#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;
+
+#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 = 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();
+#endif
+ break;
+
+#if STM32MP_UART_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+
+ /* 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);
+
+ 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;
+ }
+
+ /* 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;
+#endif
+
+#ifdef STM32MP_USB
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ usb_context = (struct usb_ctx *)boot_context->usb_context;
+
+ pcd_handle.in_ep[0].maxpacket = 0x40;
+ pcd_handle.out_ep[0].maxpacket = 0x40;
+
+ pcd_handle.state = HAL_PCD_STATE_READY;
+
+ usb_core_handle.data = &pcd_handle;
+
+ usb_dwc2_init_driver(&usb_core_handle,
+ (uint32_t *)USB_OTG_BASE);
+
+ usb_dfu_register_callback(&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.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;
+
+ /* 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);
+
+ assert(io_result == 0);
+ break;
+#endif
+#ifdef STM32MP1_QSPI_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+ ERROR("QSPI NAND not supported\n");
+ break;
+#endif
+
+ default:
+ ERROR("Boot interface %d not supported\n",
+ boot_context->boot_interface_selected);
+ break;
+ }
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int rc;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ rc = policy->check(policy->image_spec);
+ if (rc == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+
+ return rc;
+}
diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h
new file mode 100644
index 0000000..70f8202
--- /dev/null
+++ b/plat/st/common/include/stm32mp_auth.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_AUTH_H
+#define STM32MP_AUTH_H
+
+#include <boot_api.h>
+
+int check_header(boot_api_image_header_t *header, uintptr_t buffer);
+int check_authentication(boot_api_image_header_t *header, uintptr_t buffer);
+
+#endif /* STM32MP_AUTH_H */
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
new file mode 100644
index 0000000..dc2568b6
--- /dev/null
+++ b/plat/st/common/include/stm32mp_common.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_COMMON_H
+#define STM32MP_COMMON_H
+
+#include <cdefs.h>
+#include <stdbool.h>
+
+void __dead2 stm32mp_plat_reset(int cpu);
+
+void stm32mp_save_boot_ctx_address(uintptr_t address);
+uintptr_t stm32mp_get_boot_ctx_address(void);
+
+int stm32mp_is_single_core(void);
+
+uintptr_t stm32mp_ddrctrl_base(void);
+uintptr_t stm32mp_ddrphyc_base(void);
+uintptr_t stm32mp_pwr_base(void);
+uintptr_t stm32mp_rcc_base(void);
+
+int stm32_gic_enable_spi(int node, const char *name);
+
+uint32_t stm32_read_otp_status(uint32_t *otp_value, uint32_t word);
+uint8_t stm32_iwdg_get_instance(uintptr_t base);
+uint32_t stm32_iwdg_get_otp_config(uintptr_t base);
+
+#if defined(IMAGE_BL2)
+uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags);
+#endif
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank);
+int stm32_get_gpio_bank_clock(unsigned int bank);
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
+void stm32mp_print_cpuinfo(void);
+void stm32mp_print_boardinfo(void);
+
+uint64_t s2tick(uint32_t timeout_s);
+uint64_t ms2tick(uint32_t timeout_ms);
+uint64_t us2tick(uint32_t timeout_us);
+uint64_t timeout_start(void);
+bool timeout_elapsed(uint64_t tick_start, uint64_t tick_to);
+
+void stm32mp_io_setup(void);
+
+#endif /* STM32MP1_COMMON_H */
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
new file mode 100644
index 0000000..ee313d5
--- /dev/null
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_DT_H
+#define STM32MP_DT_H
+
+#include <libfdt.h>
+#include <stdbool.h>
+
+#define DT_DISABLED U(0)
+#define DT_NON_SECURE U(1)
+#define DT_SECURE U(2)
+#define DT_SHARED (DT_NON_SECURE | DT_SECURE)
+
+struct dt_node_info {
+ uint32_t base;
+ int32_t clock;
+ int32_t reset;
+ uint8_t status;
+};
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+int dt_open_and_check(void);
+int fdt_get_address(void **fdt_addr);
+bool fdt_check_node(int node);
+uint8_t fdt_get_status(int node);
+int fdt_get_interrupt(int node, const fdt32_t **array, int *len,
+ bool *extended);
+uint32_t fdt_read_uint32_default(int node, const char *prop_name,
+ uint32_t dflt_value);
+int fdt_read_uint32_array(int node, const char *prop_name,
+ uint32_t *array, uint32_t count);
+int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base,
+ size_t *size);
+int dt_set_stdout_pinctrl(void);
+void dt_fill_device_info(struct dt_node_info *info, int node);
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
+int dt_get_stdout_uart_info(struct dt_node_info *info);
+uint32_t dt_get_ddr_size(void);
+uintptr_t dt_get_ddrctrl_base(void);
+uintptr_t dt_get_ddrphyc_base(void);
+uintptr_t dt_get_pwr_base(void);
+uint32_t dt_get_pwr_vdd_voltage(void);
+uintptr_t dt_get_syscfg_base(void);
+const char *dt_get_board_model(void);
+int fdt_get_gpio_bank_pinctrl_node(unsigned int bank);
+int fdt_get_gpioz_nbpins_from_dt(void);
+
+#endif /* STM32MP_DT_H */
diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h
new file mode 100644
index 0000000..565b3d4
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shres_helpers.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHRES_HELPERS_H
+#define STM32MP_SHRES_HELPERS_H
+
+#include <debug.h>
+#include <stdint.h>
+
+/*
+ * Lock/unlock access to shared registers
+ *
+ * @lock - NULL or pointer to spin lock
+ */
+
+void stm32mp_lock_shregs(void);
+void stm32mp_unlock_shregs(void);
+void stm32mp_mmio_clrsetbits_32_shregs(uintptr_t addr, uint32_t clear,
+ uint32_t set);
+void stm32mp_mmio_clrbits_32_shregs(uintptr_t addr, uint32_t clear);
+void stm32mp_mmio_setbits_32_shregs(uintptr_t addr, uint32_t set);
+
+/*
+ * Shared reference counter: increments by 2 on secure increment
+ * request, decrements by 2 on secure decrement request. Bit #0
+ * is set to 1 on non-secure increment request and reset to 0 on
+ * non-secure decrement request. The counter initializes to
+ * either 0, 1 or 2 upon their expect default state.
+ * Counters saturates once above UINT_MAX / 2.
+ */
+#define SHREFCNT_NONSECURE_FLAG 0x1UL
+#define SHREFCNT_SECURE_STEP 0x2UL
+#define SHREFCNT_MAX (UINT32_MAX / 2)
+
+/* Return 1 if refcnt increments from 0, else return 0 */
+static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure)
+{
+ int rc = !*refcnt;
+
+ if (secure) {
+ *refcnt += SHREFCNT_SECURE_STEP;
+ if (*refcnt >= SHREFCNT_MAX) {
+ panic();
+ }
+ } else {
+ *refcnt |= SHREFCNT_NONSECURE_FLAG;
+ }
+
+ return rc;
+}
+
+/* Return 1 if refcnt decrements to 0, else return 0 */
+static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure)
+{
+ int rc = 0;
+
+ if (secure) {
+ if (*refcnt < SHREFCNT_MAX) {
+ if (*refcnt < SHREFCNT_SECURE_STEP) {
+ panic();
+ }
+ *refcnt -= SHREFCNT_SECURE_STEP;
+ rc = !*refcnt;
+ }
+ } else {
+ rc = (*refcnt == SHREFCNT_NONSECURE_FLAG);
+ *refcnt &= ~SHREFCNT_NONSECURE_FLAG;
+ }
+
+ return rc;
+}
+
+static inline int stm32mp_incr_refcnt(unsigned int *refcnt)
+{
+ return stm32mp_incr_shrefcnt(refcnt, true);
+}
+
+static inline int stm32mp_decr_refcnt(unsigned int *refcnt)
+{
+ return stm32mp_decr_shrefcnt(refcnt, true);
+}
+
+#endif /* STM32MP_SHRES_HELPERS_H */
diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c
new file mode 100644
index 0000000..773c95e
--- /dev/null
+++ b/plat/st/common/stm32mp_auth.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <errno.h>
+#include <hash_sec.h>
+#include <io_storage.h>
+#include <platform_def.h>
+#include <stm32mp_auth.h>
+#include <stm32mp_common.h>
+
+int check_header(boot_api_image_header_t *header, uintptr_t buffer)
+{
+ uint32_t i;
+ uint32_t img_checksum = 0;
+
+ /*
+ * Check header/payload validity:
+ * - Header magic
+ * - Header version
+ * - Payload checksum
+ */
+ if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+ ERROR("Header magic is not correct\n");
+ return -EINVAL;
+ }
+
+ if (header->header_version != BOOT_API_HEADER_VERSION) {
+ ERROR("Header version is not correct\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < header->image_length; i++) {
+ img_checksum += *(uint8_t *)(buffer + i);
+ }
+
+ if (header->payload_checksum != img_checksum) {
+ ERROR("Payload checksum is not correct:\n");
+ ERROR(" Computed: 0x%x (awaited: 0x%x)\n", img_checksum,
+ header->payload_checksum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int check_authentication(boot_api_image_header_t *header, uintptr_t buffer)
+{
+ uint32_t sec_closed, uret;
+ HASH_HandleTypeDef hhash;
+ uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ 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) {
+ ERROR("Error reading OTP configuration\n");
+ return -EINVAL;
+ }
+
+ /* Check Security Status */
+ if ((sec_closed & BIT(BOOT_API_OTP_MODE_CLOSED_BIT_POS)) == 0U) {
+ if (header->option_flags != 0U) {
+ WARN("Skip signature check (header option)\n");
+ return 0;
+ }
+ INFO("Check signature on Non-Full-Secured platform\n");
+ }
+
+ /* Check Public Key */
+ if (boot_context->p_bootrom_ext_service_ecdsa_check_key
+ (header->ecc_pubk, NULL) != STD_OK) {
+ return -EINVAL;
+ }
+
+ /* Compute end of header hash and payload hash */
+ uret = HASH_SHA256_Init(&hhash);
+ if (uret != STD_OK) {
+ ERROR("Hash init failed\n");
+ return -EBUSY;
+ }
+
+ uret = HASH_SHA256_Accumulate(&hhash,
+ (uint8_t *)&header->header_version,
+ sizeof(boot_api_image_header_t) -
+ header_skip_cksum);
+ if (uret != STD_OK) {
+ ERROR("Hash of header failed\n");
+ return -EINVAL;
+ }
+
+ uret = HASH_SHA256_Start(&hhash, (uint8_t *)buffer,
+ header->image_length, image_hash,
+ HASH_TIMEOUT_VALUE);
+ if (uret != STD_OK) {
+ ERROR("Hash of payload failed\n");
+ return -EINVAL;
+ }
+
+ uret = HASH_SHA256_Finish(&hhash, image_hash, HASH_TIMEOUT_VALUE);
+ if (uret != STD_OK) {
+ ERROR("Hash of payload failed\n");
+ return -EINVAL;
+ }
+
+ /* Verify signature */
+ if (boot_context->p_bootrom_ext_service_ecdsa_verify_signature
+ (image_hash, header->ecc_pubk, header->image_signature,
+ header->ecc_algo_type) != STD_OK) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
new file mode 100644
index 0000000..8efac68
--- /dev/null
+++ b/plat/st/common/stm32mp_common.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+ return BL33_BASE;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return read_cntfrq_el0();
+}
+
+#pragma weak stm32mp_plat_reset
+void __dead2 stm32mp_plat_reset(int cpu)
+{
+ panic();
+}
+
+/* Functions to save and get boot context address given by ROM code */
+static uintptr_t boot_ctx_address;
+
+void stm32mp_save_boot_ctx_address(uintptr_t address)
+{
+ boot_ctx_address = address;
+}
+
+uintptr_t stm32mp_get_boot_ctx_address(void)
+{
+ return boot_ctx_address;
+}
+
+/*
+ * This function determines if one single core is presently running. This is
+ * done by OTP read.
+ * Returns 1 if yes, 0 if more that one core is running, -1 if error.
+ */
+#pragma weak stm32mp_is_single_core
+
+int stm32mp_is_single_core(void)
+{
+ return 0;
+}
+
+uintptr_t stm32mp_ddrctrl_base(void)
+{
+ static uintptr_t ddrctrl_base;
+
+ if (ddrctrl_base == 0) {
+ ddrctrl_base = dt_get_ddrctrl_base();
+
+ assert(ddrctrl_base == DDRCTRL_BASE);
+ }
+
+ return ddrctrl_base;
+}
+
+uintptr_t stm32mp_ddrphyc_base(void)
+{
+ static uintptr_t ddrphyc_base;
+
+ if (ddrphyc_base == 0) {
+ ddrphyc_base = dt_get_ddrphyc_base();
+
+ assert(ddrphyc_base == DDRPHYC_BASE);
+ }
+
+ return ddrphyc_base;
+}
+
+uintptr_t stm32mp_pwr_base(void)
+{
+ static uintptr_t pwr_base;
+
+ if (pwr_base == 0) {
+ pwr_base = dt_get_pwr_base();
+
+ assert(pwr_base == PWR_BASE);
+ }
+
+ return pwr_base;
+}
+
+uintptr_t stm32mp_rcc_base(void)
+{
+ static uintptr_t rcc_base;
+
+ if (rcc_base == 0) {
+ rcc_base = fdt_rcc_read_addr();
+
+ assert(rcc_base == RCC_BASE);
+ }
+
+ return rcc_base;
+}
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+ switch (bank) {
+ case GPIO_BANK_A ... GPIO_BANK_K:
+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+ case GPIO_BANK_Z:
+ return GPIOZ_BASE;
+ default:
+ panic();
+ }
+}
+
+/* Return clock ID on success, negative value on error */
+int stm32_get_gpio_bank_clock(unsigned int bank)
+{
+ switch (bank) {
+ case GPIO_BANK_A ... GPIO_BANK_K:
+ return (int)GPIOA + (bank - GPIO_BANK_A);
+ case GPIO_BANK_Z:
+ return (int)GPIOZ;
+ default:
+ panic();
+ }
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return 0;
+ } else {
+ return bank * GPIO_BANK_OFFSET;
+ }
+}
+
+uint64_t s2tick(uint32_t timeout_s)
+{
+ return (uint64_t)timeout_s * read_cntfrq_el0();
+}
+
+uint64_t ms2tick(uint32_t timeout_ms)
+{
+ return s2tick(timeout_ms) / 1000U;
+}
+
+uint64_t us2tick(uint32_t timeout_us)
+{
+ return s2tick(timeout_us) / (1000U * 1000U);
+}
+
+uint64_t timeout_start(void)
+{
+ return read_cntpct_el0();
+}
+
+bool timeout_elapsed(uint64_t tick_start, uint64_t tick_to)
+{
+ return (tick_to != 0U) && ((read_cntpct_el0() - tick_start) > tick_to);
+}
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
new file mode 100644
index 0000000..48529cb
--- /dev/null
+++ b/plat/st/common/stm32mp_dt.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <libfdt.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32mp_clkfunc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+
+static int fdt_checked;
+
+static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE;
+
+/*******************************************************************************
+ * This function checks device tree file with its header.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_open_and_check(void)
+{
+ int ret = fdt_check_header(fdt);
+
+ if (ret == 0) {
+ fdt_checked = 1;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * This function gets the address of the DT.
+ * If DT is OK, fdt_addr is filled with DT address.
+ * Returns 1 if success, 0 otherwise.
+ ******************************************************************************/
+int fdt_get_address(void **fdt_addr)
+{
+ if (fdt_checked == 1) {
+ *fdt_addr = fdt;
+ }
+
+ return fdt_checked;
+}
+
+/*******************************************************************************
+ * This function check the presence of a node (generic use of fdt library).
+ * Returns true if present, else return false.
+ ******************************************************************************/
+bool fdt_check_node(int node)
+{
+ int len;
+ const char *cchar;
+
+ cchar = fdt_get_name(fdt, node, &len);
+
+ return (cchar != NULL) && (len >= 0);
+}
+
+/*******************************************************************************
+ * This function return global node status (generic use of fdt library).
+ ******************************************************************************/
+uint8_t fdt_get_status(int node)
+{
+ uint8_t status = DT_DISABLED;
+ int len;
+ const char *cchar;
+
+ cchar = fdt_getprop(fdt, node, "status", &len);
+ if ((cchar == NULL) ||
+ (strncmp(cchar, "okay", (size_t)len) == 0)) {
+ status |= DT_NON_SECURE;
+ }
+
+ cchar = fdt_getprop(fdt, node, "secure-status", &len);
+ if (cchar == NULL) {
+ if (status == DT_NON_SECURE) {
+ status |= DT_SECURE;
+ }
+ } else if (strncmp(cchar, "okay", (size_t)len) == 0) {
+ status |= DT_SECURE;
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+ * This function return interrupts from node.
+ ******************************************************************************/
+int fdt_get_interrupt(int node, const fdt32_t **array, int *len, bool *extended)
+{
+ uint8_t status = fdt_get_status(node);
+
+ *extended = false;
+
+ switch (status) {
+ case DT_SECURE:
+ *array = fdt_getprop(fdt, node, "interrupts-extended", len);
+ if (*array == NULL) {
+ *array = fdt_getprop(fdt, node, "interrupts", len);
+ } else {
+ *extended = true;
+ }
+ break;
+
+ case DT_SHARED:
+ *array = fdt_getprop(fdt, node, "secure-interrupts", len);
+ break;
+
+ default:
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if (*array == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function reads a value of a node property (generic use of fdt
+ * library).
+ * Returns value if success, and a default value if property not found.
+ * Default value is passed as parameter.
+ ******************************************************************************/
+uint32_t fdt_read_uint32_default(int node, const char *prop_name,
+ uint32_t dflt_value)
+{
+ const fdt32_t *cuint;
+ int lenp;
+
+ cuint = fdt_getprop(fdt, node, prop_name, &lenp);
+ if (cuint == NULL) {
+ return dflt_value;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function reads a series of parameters in a node property
+ * (generic use of fdt library).
+ * It reads the values inside the device tree, from property name and node.
+ * The number of parameters is also indicated as entry parameter.
+ * Returns 0 on success and a negative FDT error code on failure.
+ * If success, values are stored at the third parameter address.
+ ******************************************************************************/
+int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
+ uint32_t count)
+{
+ const fdt32_t *cuint;
+ int len;
+ uint32_t i;
+
+ cuint = fdt_getprop(fdt, node, prop_name, &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((uint32_t)len != (count * sizeof(uint32_t))) {
+ return -FDT_ERR_BADLAYOUT;
+ }
+
+ for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
+ *array = fdt32_to_cpu(*cuint);
+ array++;
+ cuint++;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function fills reg node info (base & size) with an index found by
+ * checking the reg-names node.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base,
+ size_t *size)
+{
+ const fdt32_t *cuint;
+ int index, len;
+
+ index = fdt_stringlist_search(fdt, node, "reg-names", name);
+ if (index < 0) {
+ return index;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((index * (int)sizeof(uint32_t)) > len) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ cuint += index << 1;
+ *base = fdt32_to_cpu(*cuint);
+ cuint++;
+ *size = fdt32_to_cpu(*cuint);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function gets the stdout path node.
+ * It reads the value indicated inside the device tree.
+ * Returns node on success and a negative FDT error code on failure.
+ ******************************************************************************/
+static int dt_get_stdout_node_offset(void)
+{
+ int node;
+ const char *cchar;
+
+ node = fdt_path_offset(fdt, "/secure-chosen");
+ if (node < 0) {
+ node = fdt_path_offset(fdt, "/chosen");
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+ }
+
+ cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
+ if (cchar == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ node = -FDT_ERR_NOTFOUND;
+ if (strchr(cchar, (int)':') != NULL) {
+ const char *name;
+ char *str = (char *)cchar;
+ int len = 0;
+
+ while (strncmp(":", str, 1)) {
+ len++;
+ str++;
+ }
+
+ name = fdt_get_alias_namelen(fdt, cchar, len);
+
+ if (name != NULL) {
+ node = fdt_path_offset(fdt, name);
+ }
+ } else {
+ node = fdt_path_offset(fdt, cchar);
+ }
+
+ return node;
+}
+
+/*******************************************************************************
+ * This function gets the stdout pin configuration information from the DT.
+ * And then calls the sub-function to treat it and set GPIO registers.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_set_stdout_pinctrl(void)
+{
+ int node;
+
+ node = dt_get_stdout_node_offset();
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return dt_set_pinctrl_config(node);
+}
+
+/*******************************************************************************
+ * This function fills the generic information from a given node.
+ ******************************************************************************/
+void dt_fill_device_info(struct dt_node_info *info, int node)
+{
+ const fdt32_t *cuint;
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint != NULL) {
+ info->base = fdt32_to_cpu(*cuint);
+ } else {
+ info->base = 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "clocks", NULL);
+ if (cuint != NULL) {
+ cuint++;
+ info->clock = (int)fdt32_to_cpu(*cuint);
+ } else {
+ info->clock = -1;
+ }
+
+ cuint = fdt_getprop(fdt, node, "resets", NULL);
+ if (cuint != NULL) {
+ cuint++;
+ info->reset = (int)fdt32_to_cpu(*cuint);
+ } else {
+ info->reset = -1;
+ }
+
+ info->status = fdt_get_status(node);
+}
+
+/*******************************************************************************
+ * This function retrieve the generic information from DT.
+ * Returns node on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
+{
+ int node;
+
+ node = fdt_node_offset_by_compatible(fdt, offset, compat);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ dt_fill_device_info(info, node);
+
+ return node;
+}
+
+/*******************************************************************************
+ * This function gets the UART instance info of stdout from the DT.
+ * Returns node on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_get_stdout_uart_info(struct dt_node_info *info)
+{
+ int node;
+
+ node = dt_get_stdout_node_offset();
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ dt_fill_device_info(info, node);
+
+ return node;
+}
+
+/*******************************************************************************
+ * This function gets DDR size information from the DT.
+ * Returns value in bytes on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t dt_get_ddr_size(void)
+{
+ int node;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read DDR node in DT\n", __func__);
+ return 0;
+ }
+
+ return fdt_read_uint32_default(node, "st,mem-size", 0);
+}
+
+/*******************************************************************************
+ * This function gets DDRCTRL base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_ddrctrl_base(void)
+{
+ int node;
+ uint32_t array[4];
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read DDR node in DT\n", __func__);
+ return 0;
+ }
+
+ if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+ return 0;
+ }
+
+ return array[0];
+}
+
+/*******************************************************************************
+ * This function gets DDRPHYC base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_ddrphyc_base(void)
+{
+ int node;
+ uint32_t array[4];
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read DDR node in DT\n", __func__);
+ return 0;
+ }
+
+ if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+ return 0;
+ }
+
+ return array[2];
+}
+
+/*******************************************************************************
+ * This function gets PWR base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_pwr_base(void)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read PWR node in DT\n", __func__);
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets PWR VDD regulator voltage information from the DT.
+ * Returns value in microvolts on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t dt_get_pwr_vdd_voltage(void)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read PWR node in DT\n", __func__);
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "pwr-supply", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (node < 0) {
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets SYSCFG base address information from the DT.
+ * Returns value on success, and 0 on failure.
+ ******************************************************************************/
+uintptr_t dt_get_syscfg_base(void)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read SYSCFG node in DT\n", __func__);
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ return 0;
+ }
+
+ return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function retrieves board model from DT
+ * Returns string taken from model node, NULL otherwise
+ ******************************************************************************/
+const char *dt_get_board_model(void)
+{
+ int node = fdt_path_offset(fdt, "/");
+
+ if (node < 0) {
+ return NULL;
+ }
+
+ return (const char *)fdt_getprop(fdt, node, "model", NULL);
+}
+
+/*******************************************************************************
+ * This function gets GPIO bank PINCTRL node information from the DT.
+ * Returns node value.
+ ******************************************************************************/
+int fdt_get_gpio_bank_pinctrl_node(unsigned int bank)
+{
+ switch (bank) {
+ case GPIO_BANK_A ... GPIO_BANK_K:
+ return fdt_path_offset(fdt, "/soc/pin-controller");
+ case GPIO_BANK_Z:
+ return fdt_path_offset(fdt, "/soc/pin-controller-z");
+ default:
+ panic();
+ }
+}
+
+/*******************************************************************************
+ * This function gets GPIOZ pin number information from the DT.
+ * It also checks node consistency.
+ ******************************************************************************/
+int fdt_get_gpioz_nbpins_from_dt(void)
+{
+ int pinctrl_node;
+ int pinctrl_subnode;
+
+ pinctrl_node = fdt_get_gpio_bank_pinctrl_node(GPIO_BANK_Z);
+ if (pinctrl_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
+ uint32_t bank_offset;
+ const fdt32_t *cuint;
+
+ if (fdt_getprop(fdt, pinctrl_subnode,
+ "gpio-controller", NULL) == NULL) {
+ continue;
+ }
+
+ cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ bank_offset = stm32_get_gpio_bank_offset(GPIO_BANK_Z);
+ if (fdt32_to_cpu(*cuint) != bank_offset) {
+ continue;
+ }
+
+ if (fdt_get_status(pinctrl_subnode) == DT_DISABLED) {
+ return 0;
+ }
+
+ cuint = fdt_getprop(fdt, pinctrl_subnode, "ngpios", NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return (int)fdt32_to_cpu(*cuint);
+ }
+
+ return 0;
+}
diff --git a/plat/st/common/stm32mp_shres_helpers.c b/plat/st/common/stm32mp_shres_helpers.c
new file mode 100644
index 0000000..b8bc2ec
--- /dev/null
+++ b/plat/st/common/stm32mp_shres_helpers.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <mmio.h>
+#include <spinlock.h>
+#include <stm32mp_shres_helpers.h>
+
+static struct spinlock shregs_lock;
+
+static int stm32mp_lock_available(void)
+{
+ /* The spinlocks are used only when MMU is enabled */
+#ifdef AARCH32
+ return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT);
+#else
+ return (read_sctlr_el3() & SCTLR_M_BIT) &&
+ (read_sctlr_el3() & SCTLR_C_BIT);
+#endif
+}
+
+void stm32mp_lock_shregs(void)
+{
+ if (stm32mp_lock_available() == 0U) {
+ return;
+ }
+
+ /* Assume interrupts are masked */
+ spin_lock(&shregs_lock);
+}
+
+void stm32mp_unlock_shregs(void)
+{
+ if (stm32mp_lock_available() == 0U) {
+ return;
+ }
+
+ spin_unlock(&shregs_lock);
+}
+
+/* Shared register access: upon shared resource lock */
+void stm32mp_mmio_clrsetbits_32_shregs(uintptr_t addr, uint32_t clear,
+ uint32_t set)
+{
+ stm32mp_lock_shregs();
+
+ mmio_clrsetbits_32(addr, clear, set);
+
+ stm32mp_unlock_shregs();
+}
+
+void stm32mp_mmio_clrbits_32_shregs(uintptr_t addr, uint32_t clear)
+{
+ stm32mp_lock_shregs();
+
+ mmio_clrbits_32(addr, clear);
+
+ stm32mp_unlock_shregs();
+}
+
+void stm32mp_mmio_setbits_32_shregs(uintptr_t addr, uint32_t set)
+{
+ stm32mp_lock_shregs();
+
+ mmio_setbits_32(addr, set);
+
+ stm32mp_unlock_shregs();
+}
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
deleted file mode 100644
index 7346c0c..0000000
--- a/plat/st/stm32mp1/bl2_io_storage.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_helpers.h>
-#include <assert.h>
-#include <boot_api.h>
-#include <debug.h>
-#include <io_driver.h>
-#include <io_dummy.h>
-#include <io_storage.h>
-#include <mmio.h>
-#include <platform.h>
-#include <platform_def.h>
-#include <stm32mp1_private.h>
-#include <stm32mp1_rcc.h>
-#include <string.h>
-#include <utils.h>
-
-/* IO devices */
-static const io_dev_connector_t *dummy_dev_con;
-static uintptr_t dummy_dev_handle;
-static uintptr_t dummy_dev_spec;
-
-static const io_block_spec_t bl32_block_spec = {
- .offset = BL32_BASE,
- .length = STM32MP1_BL32_SIZE
-};
-
-static const io_block_spec_t bl2_block_spec = {
- .offset = BL2_BASE,
- .length = STM32MP1_BL2_SIZE,
-};
-
-static int open_dummy(const uintptr_t spec);
-
-struct plat_io_policy {
- uintptr_t *dev_handle;
- uintptr_t image_spec;
- int (*check)(const uintptr_t spec);
-};
-
-static const struct plat_io_policy policies[] = {
- [BL2_IMAGE_ID] = {
- .dev_handle = &dummy_dev_handle,
- .image_spec = (uintptr_t)&bl2_block_spec,
- .check = open_dummy
- },
- [BL32_IMAGE_ID] = {
- .dev_handle = &dummy_dev_handle,
- .image_spec = (uintptr_t)&bl32_block_spec,
- .check = open_dummy
- },
-};
-
-static int open_dummy(const uintptr_t spec)
-{
- return io_dev_init(dummy_dev_handle, 0);
-}
-
-static void print_boot_device(boot_api_context_t *boot_context)
-{
- switch (boot_context->boot_interface_selected) {
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- INFO("Using SDMMC\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- INFO("Using EMMC\n");
- break;
- default:
- ERROR("Boot interface not found\n");
- panic();
- break;
- }
-
- if (boot_context->boot_interface_instance != 0U) {
- INFO(" Instance %d\n", boot_context->boot_interface_instance);
- }
-}
-
-static void print_reset_reason(void)
-{
- uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
-
- if (rstsr == 0U) {
- WARN("Reset reason unknown\n");
- return;
- }
-
- INFO("Reset reason (0x%x):\n", rstsr);
-
- if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
- if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
- INFO("System exits from STANDBY\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
- INFO("MPU exits from CSTANDBY\n");
- return;
- }
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
- INFO(" Power-on Reset (rst_por)\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
- INFO(" Brownout Reset (rst_bor)\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
- INFO(" System reset generated by MPU (MPSYSRST)\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
- INFO(" Reset due to a clock failure on HSE\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
- INFO(" IWDG1 Reset (rst_iwdg1)\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
- INFO(" IWDG2 Reset (rst_iwdg2)\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
- INFO(" Pad Reset from NRST\n");
- return;
- }
-
- if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
- INFO(" Reset due to a failure of VDD_CORE\n");
- return;
- }
-
- ERROR(" Unidentified reset reason\n");
-}
-
-void stm32mp1_io_setup(void)
-{
- int io_result __unused;
- boot_api_context_t *boot_context =
- (boot_api_context_t *)stm32mp1_get_boot_ctx_address();
-
- print_reset_reason();
-
- 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);
-}
-
-/*
- * Return an IO device handle and specification which can be used to access
- * an image. Use this to enforce platform load policy.
- */
-int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
- uintptr_t *image_spec)
-{
- int rc;
- const struct plat_io_policy *policy;
-
- assert(image_id < ARRAY_SIZE(policies));
-
- policy = &policies[image_id];
- rc = policy->check(policy->image_spec);
- if (rc == 0) {
- *image_spec = policy->image_spec;
- *dev_handle = *(policy->dev_handle);
- }
-
- return rc;
-}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 9f2d8bd..cd5d5b3 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_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
*/
@@ -8,38 +8,154 @@
#include <assert.h>
#include <bl_common.h>
#include <boot_api.h>
-#include <console.h>
+#include <bsec.h>
#include <debug.h>
#include <delay_timer.h>
#include <desc_image_load.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
#include <generic_delay_timer.h>
#include <mmio.h>
+#include <optee_utils.h>
#include <platform.h>
#include <platform_def.h>
+#include <stm32_console.h>
+#include <stm32_gpio.h>
+#include <stm32_iwdg.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_pmic.h>
+#include <stm32mp_reset.h>
+#include <stm32mp1xx_hal_uart.h>
#include <stm32mp1_clk.h>
-#include <stm32mp1_dt.h>
-#include <stm32mp1_pmic.h>
-#include <stm32mp1_private.h>
#include <stm32mp1_context.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_private.h>
#include <stm32mp1_pwr.h>
#include <stm32mp1_ram.h>
#include <stm32mp1_rcc.h>
-#include <stm32mp1_reset.h>
+#include <stm32mp1_shared_resources.h>
#include <string.h>
#include <xlat_tables_v2.h>
-void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
- u_register_t arg2, u_register_t arg3)
+#define PWRLP_TEMPO_5_HSI 5
+
+static struct console_stm32 console;
+static enum boot_device_e boot_device = BOOT_DEVICE_BOARD;
+
+static void print_reset_reason(void)
{
- stm32mp1_save_boot_ctx_address(arg0);
+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
+
+ if (rstsr == 0U) {
+ WARN("Reset reason unknown\n");
+ return;
+ }
+
+ INFO("Reset reason (0x%x):\n", rstsr);
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
+ if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
+ INFO("System exits from STANDBY\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
+ INFO("MPU exits from CSTANDBY\n");
+ return;
+ }
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
+ INFO(" Power-on Reset (rst_por)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
+ INFO(" Brownout Reset (rst_bor)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) {
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U)
+ INFO(" System reset generated by MCU (MCSYSRST)\n");
+ else
+ INFO(" Local reset generated by MCU (MCSYSRST)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
+ INFO(" System reset generated by MPU (MPSYSRST)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
+ INFO(" Reset due to a clock failure on HSE\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
+ INFO(" IWDG1 Reset (rst_iwdg1)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
+ INFO(" IWDG2 Reset (rst_iwdg2)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) {
+ INFO(" MPU Processor 0 Reset\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
+ INFO(" MPU Processor 1 Reset\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+ INFO(" Pad Reset from NRST\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
+ INFO(" Reset due to a failure of VDD_CORE\n");
+ return;
+ }
+
+ ERROR(" Unidentified reset reason\n");
+}
+
+enum boot_device_e get_boot_device(void)
+{
+ return boot_device;
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg0,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ stm32mp_save_boot_ctx_address(arg0);
}
void bl2_platform_setup(void)
{
int ret;
- if (dt_check_pmic()) {
+ if (dt_pmic_status() > 0) {
initialize_pmic();
+#if STM32MP1_DEBUG_ENABLE
+ /* Program PMIC to keep debug ON */
+ if ((stm32mp1_dbgmcu_boot_debug_info() == 1) &&
+ (stm32mp1_dbgmcu_is_debug_on() != 0)) {
+ VERBOSE("Program PMIC to keep debug ON\n");
+ if (pmic_keep_debug_unit() != 0) {
+ ERROR("PMIC not properly set for debug\n");
+ }
+ }
+#endif
}
ret = stm32mp1_ddr_probe();
@@ -48,62 +164,156 @@ void bl2_platform_setup(void)
panic();
}
+#ifdef AARCH32_SP_OPTEE
+ INFO("BL2 runs OP-TEE setup\n");
+ /* Initialize tzc400 after DDR initialization */
+ stm32mp1_security_setup();
+#else
INFO("BL2 runs SP_MIN setup\n");
+#endif
}
void bl2_el3_plat_arch_setup(void)
{
int32_t result;
- struct dt_node_info dt_dev_info;
+ struct dt_node_info dt_uart_info;
const char *board_model;
boot_api_context_t *boot_context =
- (boot_api_context_t *)stm32mp1_get_boot_ctx_address();
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
uint32_t clk_rate;
+ uintptr_t pwr_base;
+ uintptr_t rcc_base;
+ uint32_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+ uint32_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+
+ 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
+
+#ifdef AARCH32_SP_OPTEE
+ /* OP-TEE image needs post load processing: keep RAM read/write */
+ mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() -
+ STM32MP_DDR_S_SIZE,
+ STM32MP_DDR_BASE + dt_get_ddr_size() -
+ STM32MP_DDR_S_SIZE,
+ STM32MP_DDR_S_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
+ STM32MP_OPTEE_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE);
+#else
+ /* Prevent corruption of preloaded BL32 */
+ mmap_add_region(BL32_BASE, BL32_BASE,
+ BL32_LIMIT - BL32_BASE,
+ MT_MEMORY | MT_RO | MT_SECURE);
+
+#endif
+ /* Map non secure DDR for BL33 load and DDR training area restore */
+ mmap_add_region(STM32MP_DDR_BASE,
+ STM32MP_DDR_BASE,
+ STM32MP_DDR_MAX_SIZE,
+ MT_MEMORY | MT_RW | MT_NS);
+
+ /* Prevent corruption of preloaded Device Tree */
+ mmap_add_region(DTB_BASE, DTB_BASE,
+ DTB_LIMIT - DTB_BASE,
+ MT_MEMORY | MT_RO | MT_SECURE);
+
+ configure_mmu();
+
+ if (dt_open_and_check() < 0) {
+ panic();
+ }
+
+ pwr_base = stm32mp_pwr_base();
+ rcc_base = stm32mp_rcc_base();
+
+ /* Clear Stop Request bits to correctly manage low-power exit */
+ mmio_write_32(rcc_base + RCC_MP_SREQCLRR,
+ (uint32_t)(RCC_MP_SREQCLRR_STPREQ_P0 |
+ RCC_MP_SREQCLRR_STPREQ_P1));
/*
* Disable the backup domain write protection.
* The protection is enable at each reset by hardware
* and must be disabled by software.
*/
- mmio_setbits_32(PWR_BASE + PWR_CR1, PWR_CR1_DBP);
+ mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
- while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
;
}
+ /*
+ * Configure Standby mode available for MCU by default
+ * and allow to switch in standby SoC in all case
+ */
+ mmio_setbits_32(pwr_base + PWR_MCUCR, PWR_MCUCR_PDDS);
+
+ if (bsec_probe() != 0) {
+ panic();
+ }
+
/* Reset backup domain on cold boot cases */
- if ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
- mmio_setbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
- while ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
0U) {
;
}
- mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
}
- mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
- BL_CODE_END - BL_CODE_BASE,
- MT_CODE | MT_SECURE);
+ /* Wait 5 HSI periods before re-enabling PLLs after STOP modes */
+ mmio_clrsetbits_32(rcc_base + RCC_PWRLPDLYCR,
+ RCC_PWRLPDLYCR_PWRLP_DLY_MASK,
+ PWRLP_TEMPO_5_HSI);
- /* Prevent corruption of preloaded BL32 */
- mmap_add_region(BL32_BASE, BL32_BASE,
- BL32_LIMIT - BL32_BASE,
- MT_MEMORY | MT_RO | MT_SECURE);
+ /* 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);
- /* Prevent corruption of preloaded Device Tree */
- mmap_add_region(DTB_BASE, DTB_BASE,
- DTB_LIMIT - DTB_BASE,
- MT_MEMORY | MT_RO | MT_SECURE);
+ /* Disable MCKPROT */
+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
- configure_mmu();
+ if ((boot_context->boot_action !=
+ BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY) &&
+ (boot_context->boot_action !=
+ BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY)) {
+ mmio_write_32(bkpr_core1_addr, 0);
+ mmio_write_32(bkpr_core1_magic, 0);
+ }
generic_delay_timer_init();
- if (dt_open_and_check() < 0) {
- panic();
+#ifdef STM32MP_USB
+ if (boot_context->boot_interface_selected ==
+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) {
+ boot_device = BOOT_DEVICE_USB;
}
+#endif
+
+#if STM32MP_UART_PROGRAMMER
+ /* Disable programmer UART before changing clock tree */
+ if (boot_context->boot_interface_selected ==
+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
+ uintptr_t uart_prog_addr =
+ get_uart_address(boot_context->boot_interface_instance);
+
+ ((USART_TypeDef *)uart_prog_addr)->CR1 &= ~USART_CR1_UE;
+ }
+#endif
if (stm32mp1_clk_probe() < 0) {
panic();
@@ -113,12 +323,18 @@ void bl2_el3_plat_arch_setup(void)
panic();
}
- result = dt_get_stdout_uart_info(&dt_dev_info);
+ result = dt_get_stdout_uart_info(&dt_uart_info);
if ((result <= 0) ||
- (dt_dev_info.status == 0U) ||
- (dt_dev_info.clock < 0) ||
- (dt_dev_info.reset < 0)) {
+ (dt_uart_info.status == 0U) ||
+#if STM32MP_UART_PROGRAMMER
+ ((boot_context->boot_interface_selected ==
+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) &&
+ (get_uart_address(boot_context->boot_interface_instance) ==
+ dt_uart_info.base)) ||
+#endif
+ (dt_uart_info.clock < 0) ||
+ (dt_uart_info.reset < 0)) {
goto skip_console_init;
}
@@ -126,29 +342,57 @@ void bl2_el3_plat_arch_setup(void)
goto skip_console_init;
}
- if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) {
- goto skip_console_init;
+ if (dt_uart_info.status == DT_DISABLED) {
+ panic();
+ } else if (dt_uart_info.status == DT_SECURE) {
+ stm32mp_register_secure_periph_iomem(dt_uart_info.base);
+ } else {
+ stm32mp_register_non_secure_periph_iomem(dt_uart_info.base);
}
- stm32mp1_reset_assert((uint32_t)dt_dev_info.reset);
+ stm32mp_clk_enable((unsigned long)dt_uart_info.clock);
+
+ stm32mp_reset_assert((uint32_t)dt_uart_info.reset);
udelay(2);
- stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset);
+ stm32mp_reset_deassert((uint32_t)dt_uart_info.reset);
mdelay(1);
- clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock);
+ clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock);
- if (console_init(dt_dev_info.base, clk_rate,
- STM32MP1_UART_BAUDRATE) == 0) {
+ if (console_stm32_register(dt_uart_info.base, clk_rate,
+ STM32MP_UART_BAUDRATE, &console) == 0) {
panic();
}
+ stm32mp_print_cpuinfo();
board_model = dt_get_board_model();
if (board_model != NULL) {
- NOTICE("%s\n", board_model);
+ NOTICE("Model: %s\n", board_model);
+ }
+ stm32mp_print_boardinfo();
+
+ if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
+ NOTICE("%s\n", (boot_context->auth_status ==
+ BOOT_API_CTX_AUTH_FAILED) ?
+ "Boot authentication Failed" :
+ "Boot authentication Success");
}
skip_console_init:
+ /* Initialize IWDG Status, no startup */
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ /* Reload watchdog */
+ stm32_iwdg_refresh(IWDG2_INST);
+
+ result = stm32mp1_dbgmcu_freeze_iwdg2();
+ if (result != 0) {
+ INFO("IWDG2 freeze error : %i\n", result);
+ }
+
if (stm32_save_boot_interface(boot_context->boot_interface_selected,
boot_context->boot_interface_instance) !=
0) {
@@ -157,5 +401,118 @@ skip_console_init:
stm32mp1_arch_security_setup();
- stm32mp1_io_setup();
+ print_reset_reason();
+
+ stm32mp_io_setup();
+
+ stm32mp1_syscfg_init();
+}
+
+#if defined(AARCH32_SP_OPTEE)
+static void set_mem_params_info(entry_point_info_t *ep_info,
+ image_info_t *unpaged, image_info_t *paged)
+{
+ uintptr_t bl32_ep = 0;
+
+ /* Use the default dram setup if no valid ep found */
+ if (get_optee_header_ep(ep_info, &bl32_ep) &&
+ (bl32_ep >= STM32MP_OPTEE_BASE) &&
+ (bl32_ep < (STM32MP_OPTEE_BASE + STM32MP_OPTEE_SIZE))) {
+ assert((STM32MP_OPTEE_BASE >= BL2_LIMIT) ||
+ ((STM32MP_OPTEE_BASE + STM32MP_OPTEE_SIZE) <= BL2_BASE));
+
+ unpaged->image_base = STM32MP_OPTEE_BASE;
+ unpaged->image_max_size = STM32MP_OPTEE_SIZE;
+ } else {
+ unpaged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() -
+ STM32MP_DDR_S_SIZE;
+ unpaged->image_max_size = STM32MP_DDR_S_SIZE;
+ }
+ paged->image_base = STM32MP_DDR_BASE + dt_get_ddr_size() -
+ STM32MP_DDR_S_SIZE;
+ paged->image_max_size = STM32MP_DDR_S_SIZE;
+}
+#endif
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#if defined(AARCH32_SP_OPTEE)
+ bl_mem_params_node_t *bl32_mem_params;
+ bl_mem_params_node_t *pager_mem_params;
+ bl_mem_params_node_t *paged_mem_params;
+#endif
+
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+#if defined(AARCH32_SP_OPTEE)
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ bl_mem_params->ep_info.pc =
+ bl_mem_params->image_info.image_base;
+
+ set_mem_params_info(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err) {
+ ERROR("OPTEE header parse error.\n");
+ panic();
+ }
+
+ /* Set optee boot info from parsed header data */
+ bl_mem_params->ep_info.pc =
+ pager_mem_params->image_info.image_base;
+ bl_mem_params->ep_info.args.arg0 =
+ paged_mem_params->image_info.image_base;
+ bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
+ bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+#endif
+ break;
+
+ case BL33_IMAGE_ID:
+#ifdef AARCH32_SP_OPTEE
+ bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+ assert(bl32_mem_params);
+ bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+#else
+ /* BL33 expects to receive : TBD */
+ bl_mem_params->ep_info.args.arg0 = 0;
+ bl_mem_params->ep_info.spsr =
+ SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS);
+#endif
+ flush_dcache_range(bl_mem_params->image_info.image_base,
+ bl_mem_params->image_info.image_max_size);
+ break;
+
+#ifdef AARCH32_SP_OPTEE
+ case BL32_EXTRA1_IMAGE_ID:
+ case BL32_EXTRA2_IMAGE_ID:
+ clean_dcache_range(bl_mem_params->image_info.image_base,
+ bl_mem_params->image_info.image_max_size);
+ break;
+#endif
+
+ default:
+ err = -1;
+ break;
+ }
+
+ return err;
}
+
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 71c3593..5953e6e 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -1,13 +1,108 @@
/*
- * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __BOOT_API_H
-#define __BOOT_API_H
+#ifndef BOOT_API_H
+#define BOOT_API_H
#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * Exported constants
+ */
+
+/*
+ * Boot Context related definitions
+ */
+
+/*
+ * Possible value of boot context field 'boot_action'
+ */
+/* Boot action is Process Cold Boot */
+#define BOOT_API_CTX_BOOT_ACTION_COLD_BOOT_PROCESS 0x09U
+/* Boot action is Process Wakeup from CSTANDBY */
+#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY 0x0AU
+/* Boot action is Process Wakeup from STANDBY */
+#define BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY 0x0BU
+/* Boot action is Process Engineering Boot */
+#define BOOT_API_CTX_BOOT_ACTION_ENGI_BOOT 0x0CU
+
+#define BOOT_API_CTX_BOOT_ACTION_MPU_CORE0_RESET_PROCESS 0x0F
+
+/*
+ * Possible value of boot context field 'stby_exit_status'
+ */
+
+/* The boot reason is not a STANDBY Exit reason */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_NO_STANDBY 0x00
+
+/* STANDBY Exit with MPU_BEN=1, MCU_BEN=0 */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MPU_ONLY 0x01
+
+/*
+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot
+ * MCU restarted by bootROM
+ */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES 0x02
+
+/*
+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MPU will go for cold boot
+ * but MCU restart aborted (code integrity check) : have not been restarted
+ * by bootROM
+ */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT 0x03
+
+/*
+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MPU gone to CSTANDBY,
+ * MCU restarted correctly by bootROM
+ * This value should never be read by FSBL, because not executed in that case
+ */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY 0x04
+
+/*
+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted
+ * due code integrity check, then MPU will go for cold boot despite
+ * was not planned initially
+ */
+#define BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT 0x05
+
+/*
+ * STANDBY Exit with MPU_BEN=1, MCU_BEN=1, MCU restart aborted
+ * due to MCU security perimeter issue
+ */
+#define \
+BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_ALL_CORES_MCU_ABT_SEC_PERIMETER_ISSUE 0x06
+
+/*
+ * STANDBY Exit with MPU_BEN=0, MCU_BEN=1, MCU restart aborted
+ * due to MCU security perimeter issue, then MPU will go for cold boot
+ * despite was not planned initially
+ */
+#define \
+BOOT_API_CTX_STBY_EXIT_STATUS_WKUP_MCU_ONLY_MCU_ABT_SEC_PERIMETER_ISSUE 0x07
+
+/*
+ * Possible value of boot context field 'cstby_exit_status'
+ */
+/* The boot reason is not a CSTANDBY Exit reason */
+#define BOOT_API_CTX_CSTBY_EXIT_STATUS_NO_CSTBY 0x00
+/* CSTANDBY Exit with MCU detected as Not running */
+#define BOOT_API_CTX_CSTBY_EXIT_STATUS_MCU_NOT_RUNNING 0x01
+/* CSTANDBY Exit with MCU detected as Running */
+#define BOOT_API_CTX_CSTBY_EXIT_STATUS_MCU_RUNNING 0x02
+
+/*
+ * Possible value of boot context field 'auth_status'
+ */
+ /* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x00
+ /* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x01
+ /* Authentication done and success */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x02
/*
* Possible value of boot context field 'boot_interface_sel'
@@ -22,6 +117,21 @@
/* Boot occurred on EMMC */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U
+/* boot occurred on NAND FMC */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U
+
+/* boot occurred on QSPI NOR */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U
+
+/* boot occurred on UART */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U
+
+/* boot occurred on USB */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U
+
+/* boot occurred on NAND QSPI */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U
+
/**
* @brief Possible value of boot context field 'EmmcXferStatus'
*/
@@ -45,6 +155,10 @@
#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U
+/* Definitions relative to 'p_rom_version_info->platform_type_ver' field */
+#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_IC_EMU_FPGA 0xAA
+#define BOOT_API_CTX_ROM_VERSION_PLAT_VER_FPGA_ONLY 0xBB
+
/* Image Header related definitions */
/* Definition of header version */
@@ -76,6 +190,64 @@
#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U
/*
+ * MCU Code Integrity Check related definitions
+ */
+
+/*
+ * Defines to identify RTC backup registers to be used for MCU code integrity
+ * check
+ */
+
+/*
+ * TAMP_BCK0R contains two bits
+ * bit 0 : wanted value of 'RCC_TZCR.TZEN'
+ * bit 1 : wanted value of 'RCC_TZCR.MCKPROT'
+ */
+
+/*
+ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.TZEN'
+ * trustZone aware domain enabling/disabling
+ */
+#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_BIT 0
+
+/*
+ * TAMP_BCK0R bit position coding wanted value of 'RCC_TZCR.MCKPROT'
+ * ability of MCU to modify some clock settings in RCC
+ */
+#define BOOT_API_MCIC_MCU_SECURITY_PERIMETER_MCKPROT_BIT 1
+
+/* TAMP_BCK0R register index */
+#define \
+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_TZEN_MCKPROT_TAMP_BCK_REG_IDX 0
+
+/*
+ * TAMP_BCK1R register index
+ * This register is coding the wanted value of register 'EXTI_TZENR1'
+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1
+ * that is MCU quick restart requested
+ */
+#define \
+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR1_TAMP_BCK_REG_IDX 1
+
+/*
+ * TAMP_BCK2R register index
+ * This register is coding the wanted value of register 'EXTI_TZENR2'
+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1
+ * that is MCU quick restart requested
+ */
+#define \
+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR2_TAMP_BCK_REG_IDX 2
+
+/*
+ * TAMP_BCK3R register index
+ * This register is coding the wanted value of register 'EXTI_TZENR3'
+ * to be programmed by bootROM on wakeup from STANDBY when MCUBEN=1
+ * that is MCU quick restart requested
+ */
+#define \
+BOOT_API_MCIC_MCU_SECURITY_PERIMETER_EXTI_TZENR3_TAMP_BCK_REG_IDX 3
+
+/*
* TAMP_BCK4R register index
* This register is used to write a Magic Number in order to restart
* Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R
@@ -90,6 +262,39 @@
#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U
/*
+ * TAMP_BCK22R register index
+ * This register contains offset in bytes of code to Hash in RETRAM region
+ * Note : offset is intended as relative value from start of RETRAM
+ */
+#define \
+BOOT_API_MCIC_OFFSET_IN_BYTES_CODE_TO_HASH_RETRAM_TAMP_BCK_REG_IDX 22
+
+/*
+ * TAMP_BCK23R register index
+ * This register contains the size in bytes of the single consecutive region
+ * of MCU Firmware in RETRAM (Retention RAM) to hash (by SHA-256)
+ * Note : This is required as a MCU firmware Code Integrity Check (aka : MCIC)
+ * to avoid bootROM restarting MCU on a corrupted firmware
+ */
+#define \
+BOOT_API_MCIC_RETRAM_REGION_TO_HASH_IN_BYTES_TAMP_BCK_REG_IDX 23
+
+/*
+ * TAMP_BCK24R to TAMP_BCK31R register indexes
+ * Those registers contains SHA-256 digest of RETRAM MCU Firmware code between
+ * [(RETRAM_start + offset) -- (RETRAM_start + offset + size_to_hash)]
+ * in this order
+ * This is the MCU Code Integrity Check MCU Firmware signature
+ * value on 256 bits
+ */
+
+/* First TAMP_BKP index of MCU Firmware signature : ie TAMP_BCK24R */
+#define BOOT_API_MCIC_SHA_DIGEST_FIRST_TAMP_BCK_REG_IDX 24
+
+/* Last TAMP_BKP index of MCU Firmware signature : ie TAMP_BCK31R */
+#define BOOT_API_MCIC_SHA_DIGEST_LAST_TAMP_BCK_REG_IDX 31
+
+/*
* Possible value of boot context field 'hse_clock_value_in_hz'
*/
#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U
@@ -113,6 +318,57 @@
/* Closed = OTP_CFG0[6] */
#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6
+/* Mapping of OTP Word and OTP bits managing SSP and useful to FSBL-SSP */
+/* OTP_CFG8 */
+#define BOOT_API_OTP_SSP_WORD_NB 8U
+/* SSP_REQ = OTP_CFG8[8] */
+#define BOOT_API_OTP_SSP_REQ_BIT_POS 8
+/* SSP_SUCCESS = OTP_CFG8[9] */
+#define BOOT_API_OTP_SSP_SUCCESS_BIT_POS 9
+
+/*
+ * Possible values of boot context field
+ * 'ssp_config_ptr_in->ssp_cmd'
+ */
+/* 'K' 'B' 'U' 'P' -.> 'PUBK' */
+#define BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK 0x4B425550
+
+/*
+ * Exported types
+ */
+
+/* SSP Configuration structure */
+typedef struct {
+ /* SSP Command*/
+ uint32_t ssp_cmd;
+ uint8_t reserved[20];
+} boot_api_ssp_config_t;
+
+/*
+ * bootROM version information structure definition
+ * Total size = 24 bytes = 6 uint32_t
+ */
+typedef struct {
+ /* Chip Version */
+ uint32_t chip_ver;
+
+ /* Cut version within a fixed chip version */
+ uint32_t cut_ver;
+
+ /* Version of ROM Mask within a fixed cut version */
+ uint32_t rom_mask_ver;
+
+ /* Internal Version of bootROM code */
+ uint32_t bootrom_ver;
+
+ /* Version of bootROM adapted */
+ uint32_t for_chip_design_rtl_ver;
+
+ /* Restriction on compiled platform when it applies */
+ uint32_t platform_type_ver;
+
+} boot_api_rom_version_info_t;
+
/*
* Boot Context related definitions
*/
@@ -129,9 +385,133 @@ typedef struct {
*/
uint16_t boot_interface_selected;
uint16_t boot_interface_instance;
- uint32_t reserved1[13];
+ uint32_t reserved1;
+ uint32_t nand_data_width;
+ uint32_t nand_block_size;
+ uint32_t nand_page_size;
+ uint32_t reserved2;
+ uint32_t nand_ecc_bits;
+ uint32_t nand_block_nb;
+ uint32_t reserved3[4];
+ uint32_t nor_isdual;
+ uint32_t usb_context;
uint32_t otp_afmux_values[3];
- uint32_t reserved[9];
+ uint32_t reserved[2];
+ /*
+ * Log to boot context, what was the kind of boot action
+ * takes values from defines BOOT_API_BOOT_ACTION_XXX above
+ */
+ uint32_t boot_action;
+ /*
+ * STANDBY Exit status to be checked by FSBL in case
+ * field 'boot_action' == BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY
+ * take values from defines above 'BOOT_API_CTX_STBY_EXIT_STATUS_XXX'
+ * depending on encountered situation
+ */
+ uint32_t stby_exit_status;
+ /*
+ * CSTANDBY Exit status to be checked by FSBL in case
+ * boot_action == BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY
+ * take values from defines above 'BOOT_API_CTX_CSTBY_EXIT_STATUS_XXX'
+ * depending on encountered situation
+ */
+ uint32_t cstby_exit_status;
+ /*
+ * Returned authentication status : take values from defines
+ * BOOT_API_CTX_AUTH_XXX above
+ */
+ uint32_t auth_status;
+
+ /*
+ *******************************************************
+ * Pointers to bootROM External Secure Services
+ * External Secure Services offered by bootROM
+ * - ECDSA check key
+ * - ECDSA verify signature
+ * - ECDSA verify signature and go
+ *******************************************************
+ */
+ /*
+ * Check if hash of p_pub_key_in is equal to hash by SHA-256
+ * of OEM public key from OTP
+ *
+ * If no: => infinite loop in bootROM : boot failed
+ *
+ * else: copy p_pub_key_in to p_pub_key_out if
+ * p_pub_key_out not NULL.
+ * and return to caller.
+ *
+ * @param[in] p_pub_key_in points to an ECDSA public key :
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in/out] p_pub_key_out points to area where to store copy
+ * of public key.
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @retval STD_OK (0x77) or STD_NOT_OK (0x66)
+ */
+ uint32_t (*p_bootrom_ext_service_ecdsa_check_key)
+ (uint8_t *p_pub_key_in,
+ uint8_t *p_pub_key_out);
+ /*
+ * verify ECDSA signature
+ *
+ * Decrypt EDCSA signature from 'p_signature'
+ * using public key passed in parameter 'p_pub_key_in'
+ * Then compare it to hash from 'p_hash_in' (SHA-256)
+ *
+ * If no match: => infinite loop in bootROM
+ *
+ * else: return to caller
+ *
+ * @param[in] p_hash_in : points on hash in (SHA-256)
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] p_pub_key_in : points to an ECDSA public key
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] p_signature : points to an EDCSA signature.
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] ecc_algo : Ecc algorithm to be used P256 NIST or
+ * Brain_pool 256.
+ *
+ * @retval STD_OK (0x77) or STD_NOT_OK (0x66)
+ */
+ uint32_t (*p_bootrom_ext_service_ecdsa_verify_signature)
+ (uint8_t *p_hash_in, uint8_t *p_pub_key_in,
+ uint8_t *p_signature, uint32_t ecc_algo);
+ /*
+ * verify ECDSA signature and branch to entry point if match
+ *
+ * Decrypt EDCSA signature from 'p_signature'
+ * using public key passed in parameter 'p_pub_key_in'
+ * Then compare it to hash from 'p_hash_in' (SHA-256)
+ *
+ * If no match: => infinite loop in bootROM
+ *
+ * else: branch CA7-0 to branch address 'p_entry_in'
+ *
+ * @param[in] p_hash_in : points on hash in (SHA-256)
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] p_pub_key_in : points to an ECDSA public key
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] p_signature : points to an EDCSA signature.
+ * Very Important : address alignment constraint :
+ * This address should be multiple of 4 bytes only.
+ * @param[in] ecc_algo : Ecc algorithm to be used P256 NIST or
+ * Brain_pool 256.
+ * @param[in] p_entry_in : points to branch entry point.
+ *
+ * @retval STD_NOT_OK (0x66)
+ */
+ uint32_t (*p_bootrom_ext_service_ecdsa_verify_and_go)
+ (uint8_t *p_hash_in, uint8_t *p_pub_key_in,
+ uint8_t *p_signature_in, uint32_t ecc_algo,
+ uint32_t *p_entry_in);
+
/*
* Information specific to an SD boot
* Updated each time an SD boot is at least attempted,
@@ -161,6 +541,21 @@ typedef struct {
* ie FSBL partition on which the boot was successful
*/
uint32_t boot_partition_used_toboot;
+ /*
+ * Address of SSP configuration structure :
+ * given and defined by bootROM
+ * and used by FSBL. The structure is of type
+ * 'boot_api_ssp_config_t'
+ */
+ boot_api_ssp_config_t *p_ssp_config;
+ /*
+ * boot context field containing bootROM updated SSP Status
+ * Values can be of type BOOT_API_CTX_SSP_STATUS_XXX
+ */
+ uint32_t ssp_status;
+
+ /* Pointer on ROM constant containing ROM information */
+ const boot_api_rom_version_info_t *p_rom_version_info;
} __packed boot_api_context_t;
@@ -229,7 +624,9 @@ typedef struct {
*/
uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
/* Pad up to 256 byte total size */
- uint8_t pad[84];
+ uint8_t pad[83];
+ /* Add binary type information */
+ uint8_t binary_type;
} __packed boot_api_image_header_t;
-#endif /* __BOOT_API_H */
+#endif /* BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 47e1ffc..fd1ccbf 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -24,12 +24,22 @@
#define PLATFORM_STACK_SIZE 0xC00
#endif
+#ifdef AARCH32_SP_OPTEE
+#define OPTEE_HEADER_IMAGE_NAME "teeh"
+#define OPTEE_PAGED_IMAGE_NAME "teed"
+#define OPTEE_PAGER_IMAGE_NAME "teex"
+#define OPTEE_HEADER_BINARY_TYPE U(0x20)
+#define OPTEE_PAGER_BINARY_TYPE U(0x21)
+#define OPTEE_PAGED_BINARY_TYPE U(0x22)
+#endif
+
/* SSBL = second stage boot loader */
#define BL33_IMAGE_NAME "ssbl"
+#define BL33_BINARY_TYPE U(0x0)
-#define STM32MP1_PRIMARY_CPU U(0x0)
+#define STM32MP_PRIMARY_CPU U(0x0)
+#define STM32MP_SECONDARY_CPU U(0x1)
-#define PLATFORM_CACHE_LINE_SIZE 64
#define PLATFORM_CLUSTER_COUNT ULL(1)
#define PLATFORM_CLUSTER0_CORE_COUNT U(2)
#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
@@ -37,8 +47,9 @@
PLATFORM_CLUSTER0_CORE_COUNT)
#define PLATFORM_MAX_CPUS_PER_CLUSTER 2
-#define MAX_IO_DEVICES 4
-#define MAX_IO_HANDLES 4
+#define MAX_IO_DEVICES U(4)
+#define MAX_IO_HANDLES U(4)
+#define MAX_IO_BLOCK_DEVICES U(1)
/*******************************************************************************
* BL2 specific defines.
@@ -47,39 +58,45 @@
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
* size plus a little space for growth.
*/
-#define BL2_BASE STM32MP1_BL2_BASE
-#define BL2_LIMIT (STM32MP1_BL2_BASE + \
- STM32MP1_BL2_SIZE)
+#define BL2_BASE STM32MP_BL2_BASE
+#define BL2_LIMIT (STM32MP_BL2_BASE + \
+ STM32MP_BL2_SIZE)
/*******************************************************************************
* BL32 specific defines.
******************************************************************************/
-#define BL32_BASE STM32MP1_BL32_BASE
-#define BL32_LIMIT (STM32MP1_BL32_BASE + \
- STM32MP1_BL32_SIZE)
+#ifndef AARCH32_SP_OPTEE
+#define BL32_BASE STM32MP_BL32_BASE
+#define BL32_LIMIT (STM32MP_BL32_BASE + \
+ STM32MP_BL32_SIZE)
+#endif
/*******************************************************************************
* BL33 specific defines.
******************************************************************************/
-#define BL33_BASE STM32MP1_BL33_BASE
+#define BL33_BASE STM32MP_BL33_BASE
/*
* Load address of BL33 for this platform port
*/
-#define PLAT_STM32MP1_NS_IMAGE_OFFSET BL33_BASE
+#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
+
+/* need by flash programmer */
+#define FLASHLAYOUT_BASE STM32MP_DDR_BASE
+#define FLASHLAYOUT_LIMIT STM32MP_BL33_BASE
/*******************************************************************************
* DTB specific defines.
******************************************************************************/
-#define DTB_BASE STM32MP1_DTB_BASE
-#define DTB_LIMIT (STM32MP1_DTB_BASE + \
- STM32MP1_DTB_SIZE)
+#define DTB_BASE STM32MP_DTB_BASE
+#define DTB_LIMIT (STM32MP_DTB_BASE + \
+ STM32MP_DTB_SIZE)
/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
-#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
/*******************************************************************************
* Declarations and constants to access the mailboxes safely. Each mailbox is
@@ -98,6 +115,8 @@
*/
#define ARM_IRQ_SEC_PHY_TIMER U(29)
+#define ARM_IRQ_NON_SEC_SGI_0 U(0)
+
#define ARM_IRQ_SEC_SGI_0 U(8)
#define ARM_IRQ_SEC_SGI_1 U(9)
#define ARM_IRQ_SEC_SGI_2 U(10)
@@ -107,7 +126,15 @@
#define ARM_IRQ_SEC_SGI_6 U(14)
#define ARM_IRQ_SEC_SGI_7 U(15)
+/* Platform IRQ Priority */
+#define STM32MP1_IRQ_RCC_SEC_PRIO U(0x6)
+#define STM32MP1_IRQ_SEC_SPI_PRIO U(0x10)
+
#define STM32MP1_IRQ_TZC400 U(36)
+#define STM32MP1_IRQ_MCU_SEV U(176)
+#define STM32MP1_IRQ_RCC_WAKEUP U(177)
+#define STM32MP1_IRQ_IWDG1 U(182)
+#define STM32MP1_IRQ_IWDG2 U(183)
#define STM32MP1_IRQ_TAMPSERRS U(229)
#define STM32MP1_IRQ_AXIERRIRQ U(244)
@@ -120,9 +147,6 @@
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
- INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS, \
- GIC_HIGHEST_SEC_PRIORITY, \
- grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h
index fd08afc..4cd6643 100644
--- a/plat/st/stm32mp1/include/stm32mp1_context.h
+++ b/plat/st/stm32mp1/include/stm32mp1_context.h
@@ -4,11 +4,23 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_CONTEXT_H__
-#define __STM32MP1_CONTEXT_H__
+#ifndef STM32MP1_CONTEXT_H
+#define STM32MP1_CONTEXT_H
+#include <stdbool.h>
#include <stdint.h>
+#define DDR_CRC_GRANULE 32
+
+void stm32_clean_context(void);
+int stm32_save_context(uint32_t zq0cr0_zdata);
+int stm32_restore_context(void);
+int stm32_restore_backup_reg(void);
+uint32_t stm32_get_zdata_from_context(void);
int stm32_save_boot_interface(uint32_t interface, uint32_t instance);
+int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance);
+void stm32_save_ddr_training_area(void);
+void stm32_restore_ddr_training_area(void);
+uint32_t stm32_pm_get_optee_ep(void);
-#endif /* __STM32MP1_CONTEXT_H__ */
+#endif /* STM32MP1_CONTEXT_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
new file mode 100644
index 0000000..fd97a16
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_DBGMCU_H__
+#define __PLAT_DBGMCU_H__
+
+#include <stdint.h>
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+#define VERBOSE_HEXDUMP8(buf, len) stm32mp1_dbgmcu_hexdump8(buf, len)
+#else
+#define VERBOSE_HEXDUMP8(buf, len)
+#endif
+
+uint32_t stm32mp1_dbgmcu_get_chip_version(void);
+uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void);
+int stm32mp1_dbgmcu_freeze_iwdg2(void);
+int stm32mp1_dbgmcu_boot_debug_info(void);
+int stm32mp1_dbgmcu_clear_boot_info(void);
+uint32_t stm32mp1_dbgmcu_is_debug_on(void);
+void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len);
+
+#endif /* __PLAT_DBGMCU_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h
deleted file mode 100644
index 58e10d1..0000000
--- a/plat/st/stm32mp1/include/stm32mp1_dt.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __STM32MP1_DT_H__
-#define __STM32MP1_DT_H__
-
-#include <stdbool.h>
-
-struct dt_node_info {
- uint32_t base;
- int32_t clock;
- int32_t reset;
- bool status;
- bool sec_status;
-};
-
-/*******************************************************************************
- * Function and variable prototypes
- ******************************************************************************/
-int dt_open_and_check(void);
-int fdt_get_address(void **fdt_addr);
-bool fdt_check_node(int node);
-bool fdt_check_status(int node);
-bool fdt_check_secure_status(int node);
-uint32_t fdt_read_uint32_default(int node, const char *prop_name,
- uint32_t dflt_value);
-int fdt_read_uint32_array(int node, const char *prop_name,
- uint32_t *array, uint32_t count);
-int dt_set_pinctrl_config(int node);
-int dt_set_stdout_pinctrl(void);
-void dt_fill_device_info(struct dt_node_info *info, int node);
-int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
-int dt_get_stdout_uart_info(struct dt_node_info *info);
-int dt_get_stdout_node_offset(void);
-uint32_t dt_get_ddr_size(void);
-const char *dt_get_board_model(void);
-
-#endif /* __STM32MP1_DT_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_low_power.h b/plat/st/stm32mp1/include/stm32mp1_low_power.h
new file mode 100644
index 0000000..a9b2778
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_low_power.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_LOW_POWER_H
+#define STM32MP1_LOW_POWER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void stm32_rcc_wakeup_update(bool state);
+void stm32_apply_pmic_suspend_config(uint32_t mode);
+void stm32_exit_cstop(void);
+void stm32_pwr_down_wfi(void);
+void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr);
+
+#endif /* STM32MP1_LOW_POWER_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_power_config.h b/plat/st/stm32mp1/include/stm32mp1_power_config.h
new file mode 100644
index 0000000..bcee6b6
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_power_config.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_POWER_CONFIG_H
+#define STM32MP1_POWER_CONFIG_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define PSCI_MODE_SYSTEM_SUSPEND 0
+#define PSCI_MODE_SYSTEM_OFF 1
+
+enum stm32mp1_pm_domain {
+ STM32MP1_PD_VSW,
+ STM32MP1_PD_CORE_RET,
+ STM32MP1_PD_CORE,
+ STM32MP1_PD_MAX_PM_DOMAIN
+};
+
+void stm32mp1_init_lp_states(void);
+int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status);
+uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode);
+int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode);
+
+#endif /* STM32MP1_POWER_CONFIG_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index a789d53..cc6c9e7 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -1,22 +1,38 @@
/*
- * 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
*/
-#ifndef __STM32MP1_PRIVATE_H__
-#define __STM32MP1_PRIVATE_H__
+#ifndef STM32MP1_PRIVATE_H
+#define STM32MP1_PRIVATE_H
+
+#include <bl_common.h>
+#include <boot_api.h>
+#include <stdbool.h>
+
+enum boot_device_e {
+ BOOT_DEVICE_USB,
+ BOOT_DEVICE_BOARD
+};
-void stm32mp1_io_setup(void);
void configure_mmu(void);
void stm32mp1_arch_security_setup(void);
void stm32mp1_security_setup(void);
+void stm32mp1_sp_min_security_setup(void);
+
+enum boot_device_e get_boot_device(void);
-void stm32mp1_save_boot_ctx_address(uintptr_t address);
-uintptr_t stm32mp1_get_boot_ctx_address(void);
+#if STM32MP_UART_PROGRAMMER
+uintptr_t get_uart_address(uint32_t instance_nb);
+#endif
void stm32mp1_gic_pcpu_init(void);
void stm32mp1_gic_init(void);
-#endif /* __STM32MP1_PRIVATE_H__ */
+enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode);
+
+void stm32mp1_syscfg_init(void);
+
+#endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..b161cab
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <debug.h>
+#include <etzpc.h>
+#include <stdbool.h>
+
+void stm32mp_clk_enable(unsigned long id);
+void stm32mp_clk_disable(unsigned long id);
+
+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + i)
+
+enum stm32mp_shres {
+ STM32MP1_SHRES_GPIOZ_0 = 0,
+ STM32MP1_SHRES_GPIOZ_1,
+ STM32MP1_SHRES_GPIOZ_2,
+ STM32MP1_SHRES_GPIOZ_3,
+ STM32MP1_SHRES_GPIOZ_4,
+ STM32MP1_SHRES_GPIOZ_5,
+ STM32MP1_SHRES_GPIOZ_6,
+ STM32MP1_SHRES_GPIOZ_7,
+ STM32MP1_SHRES_IWDG1,
+ STM32MP1_SHRES_USART1,
+ STM32MP1_SHRES_SPI6,
+ STM32MP1_SHRES_I2C4,
+ STM32MP1_SHRES_RNG1,
+ STM32MP1_SHRES_HASH1,
+ STM32MP1_SHRES_CRYP1,
+ STM32MP1_SHRES_I2C6,
+ STM32MP1_SHRES_RTC,
+ STM32MP1_SHRES_MCU,
+ STM32MP1_SHRES_HSI,
+ STM32MP1_SHRES_LSI,
+ STM32MP1_SHRES_HSE,
+ STM32MP1_SHRES_LSE,
+ STM32MP1_SHRES_CSI,
+ STM32MP1_SHRES_PLL1,
+ STM32MP1_SHRES_PLL1_P,
+ STM32MP1_SHRES_PLL1_Q,
+ STM32MP1_SHRES_PLL1_R,
+ STM32MP1_SHRES_PLL2,
+ STM32MP1_SHRES_PLL2_P,
+ STM32MP1_SHRES_PLL2_Q,
+ STM32MP1_SHRES_PLL2_R,
+ STM32MP1_SHRES_PLL3,
+ STM32MP1_SHRES_PLL3_P,
+ STM32MP1_SHRES_PLL3_Q,
+ STM32MP1_SHRES_PLL3_R,
+
+ STM32MP1_SHRES_COUNT
+};
+
+void stm32mp1_register_secure_periph(unsigned int id);
+void stm32mp1_register_shared_periph(unsigned int id);
+void stm32mp1_register_non_secure_periph(unsigned int id);
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp1_register_etzpc_decprot(unsigned int id,
+ enum etzpc_decprot_attributes attr);
+
+bool stm32mp1_periph_is_shared(unsigned long id);
+bool stm32mp1_periph_is_non_secure(unsigned long id);
+bool stm32mp1_periph_is_secure(unsigned long id);
+bool stm32mp1_periph_is_unregistered(unsigned long id);
+
+bool stm32mp_gpio_bank_is_shared(unsigned int bank);
+bool stm32mp_gpio_bank_is_non_secure(unsigned int bank);
+bool stm32mp_gpio_bank_is_secure(unsigned int bank);
+
+bool stm32mp1_clock_is_shareable(unsigned long clock_id);
+bool stm32mp1_clock_is_shared(unsigned long clock_id);
+bool stm32mp1_clock_is_non_secure(unsigned long clock_id);
+
+void stm32mp1_driver_init_late(void);
+
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
new file mode 100644
index 0000000..956493f
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_SMC_H__
+#define __STM32MP1_SMC_H__
+
+#include <platform_def.h>
+
+/*
+ * SMC function IDs for STM32 Service queries
+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
+ * like this is defined in SMC calling Convention by ARM
+ * for SiP (silicon Partner)
+ * https://developer.arm.com/docs/den0028/latest
+ */
+
+/* Secure Service access from Non-secure */
+#define STM32_SMC_RCC 0x82001000
+#define STM32_SMC_PWR 0x82001001
+#define STM32_SMC_RCC_CAL 0x82001002
+#define STM32_SMC_BSEC 0x82001003
+
+/* Low Power services */
+#define STM32_SMC_SR_MODE 0x82001004
+#define STM32_SMC_PD_DOMAIN 0x82001008
+
+/* SMC function IDs for SiP Service queries */
+#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
+#define STM32_SIP_SVC_UID 0x8200ff01
+/* 0x8200ff02 is reserved */
+#define STM32_SIP_SVC_VERSION 0x8200ff03
+
+/* STM32 SiP Service Calls version numbers */
+#define STM32_SIP_SVC_VERSION_MAJOR 0x0
+#define STM32_SIP_SVC_VERSION_MINOR 0x1
+
+/* Number of STM32 SiP Calls implemented */
+#define STM32_COMMON_SIP_NUM_CALLS 10
+
+/* Register access service use for RCC/RTC/PWR */
+#define STM32_SMC_REG_READ 0x0
+#define STM32_SMC_REG_WRITE 0x1
+#define STM32_SMC_REG_SET 0x2
+#define STM32_SMC_REG_CLEAR 0x3
+
+/* Service for BSEC */
+#define STM32_SMC_READ_SHADOW 0x01
+#define STM32_SMC_PROG_OTP 0x02
+#define STM32_SMC_WRITE_SHADOW 0x03
+#define STM32_SMC_READ_OTP 0x04
+#define STM32_SMC_READ_ALL 0x05
+#define STM32_SMC_WRITE_ALL 0x06
+
+/* SMC error codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
+/* DDR Self-Refresh modes */
+#define STM32_SMC_SR_MODE_SSR 0x0
+#define STM32_SMC_SR_MODE_ASR 0x1
+#define STM32_SMC_SR_MODE_HSR 0x2
+
+#endif /* __STM32MP1_SMC_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_usb_desc.h b/plat/st/stm32mp1/include/stm32mp1_usb_desc.h
new file mode 100644
index 0000000..71cacb3
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_usb_desc.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USBD_DESC_H
+#define __USBD_DESC_H
+
+#include <usb_core.h>
+
+/* Max DFU Packet Size = 1024 bytes */
+#define USBD_DFU_XFER_SIZE 1024
+
+#define TRANSFER_SIZE_BYTES(size) \
+ ((uint8_t)((size) & 0xFF)), /* XFERSIZEB0 */\
+ ((uint8_t)((size) >> 8)) /* XFERSIZEB1 */
+
+/* Descriptor of DFU interface 0 Alternate setting n */
+#define USBD_DFU_IF_DESC(n) 0x09, /* Interface Descriptor size */\
+ USB_DESC_TYPE_INTERFACE, /* descriptor type */\
+ 0x00, /* Number of Interface */\
+ (n), /* Alternate setting */\
+ 0x00, /* bNumEndpoints*/\
+ 0xFE, /* Application Specific Class Code */\
+ 0x01, /* Device Firmware Upgrade Code */\
+ 0x02, /* DFU mode protocol */ \
+ USBD_IDX_INTERFACE_STR + (n) + 1 /* iInterface:
+ * Index of
+ * string
+ * descriptor
+ */
+/* DFU1.1 Standard only supported */
+#define USB_DFU_VERSION 0x0110
+#define USBD_DESC_MAX_ITF_NUM 0x6
+#define USB_DFU_CONFIG_DESC_SIZ 72
+#define USB_DFU_DESC_SIZ 9
+/* String size (1 byte) + type (1 byte) + 24 UTF16 characters */
+/* (2 bytes per character) */
+#define USB_SIZ_STRING_SERIAL (1 + 1 + (24 * 2))
+#define USBD_MAX_STR_DESC_SIZ 0x100
+#define USBD_VID 0x0483
+#define USBD_PID 0xDF11
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "STMicroelectronics"
+#define USBD_PRODUCT_HS_STRING "DFU in HS Mode @Device ID /0x500, @Revision ID /0x0000"
+#define USBD_PRODUCT_FS_STRING "DFU in FS Mode @Device ID /0x500, @Revision ID /0x0000"
+#define USBD_CONFIGURATION_HS_STRING "DFU Config"
+#define USBD_INTERFACE_HS_STRING "DFU Interface"
+#define USBD_CONFIGURATION_FS_STRING "DFU Config"
+#define USBD_INTERFACE_FS_STRING "DFU Interface"
+
+void stm32mp_usb_init_desc(usb_handle_t *pdev);
+
+#endif /* __USBD_DESC_H */
diff --git a/plat/st/stm32mp1/include/usb_ctx.h b/plat/st/stm32mp1/include/usb_ctx.h
new file mode 100644
index 0000000..0046bd0
--- /dev/null
+++ b/plat/st/stm32mp1/include/usb_ctx.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __USB_CTX_H
+#define __USB_CTX_H
+
+#include <usb_core.h>
+
+struct usb_ctx {
+ usb_handle_t *pusbd_device_ctx;
+ pcd_handle_t *phpcd_ctx;
+};
+
+#endif /* __USB_CTX_H */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index 6f5bc4c..4ef135e 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -26,7 +26,9 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
VERSION_2, entry_point_info_t,
SECURE | EXECUTABLE | EP_FIRST_EXE),
+#if !defined(AARCH32_SP_OPTEE)
.ep_info.pc = BL32_BASE,
+#endif
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
SPSR_E_LITTLE,
DISABLE_ALL_EXCEPTIONS),
@@ -34,13 +36,48 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t,
IMAGE_ATTRIB_PLAT_SETUP),
-
+#if defined(AARCH32_SP_OPTEE)
+ /* optee header is loaded is SYSRAM above BL2 */
+ .image_info.image_base = STM32MP_OPTEE_BASE,
+ .image_info.image_max_size = STM32MP_OPTEE_SIZE,
+#else
.image_info.image_base = BL32_BASE,
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
-
+#endif
.next_handoff_image_id = BL33_IMAGE_ID,
},
+#if defined(AARCH32_SP_OPTEE)
+ /* Fill BL32 external 1 image related information */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ /* Fill BL32 external 2 image related information */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* AARCH32_SP_OPTEE */
+
/* Fill BL33 related information */
{
.image_id = BL33_IMAGE_ID,
@@ -49,7 +86,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
VERSION_2, entry_point_info_t,
NON_SECURE | EXECUTABLE),
- .ep_info.pc = PLAT_STM32MP1_NS_IMAGE_OFFSET,
+ .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET,
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
SPSR_E_LITTLE,
DISABLE_ALL_EXCEPTIONS),
@@ -57,9 +94,9 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
- .image_info.image_base = PLAT_STM32MP1_NS_IMAGE_OFFSET,
- .image_info.image_max_size = STM32MP1_DDR_MAX_SIZE -
- (PLAT_STM32MP1_NS_IMAGE_OFFSET - STM32MP1_DDR_BASE),
+ .image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = STM32MP_DDR_MAX_SIZE -
+ (PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE),
.next_handoff_image_id = INVALID_IMAGE_ID,
}
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
index 3c6d677..db53c37 100644
--- a/plat/st/stm32mp1/plat_image_load.c
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -4,7 +4,23 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <bl_common.h>
+#include <boot_api.h>
+#include <bsec.h>
+#include <cassert.h>
+#include <debug.h>
#include <desc_image_load.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_context.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#include <utils_def.h>
/*******************************************************************************
* This function flushes the data structures so that they are visible
@@ -12,14 +28,101 @@
******************************************************************************/
void plat_flush_next_bl_params(void)
{
+ uint32_t version;
+
flush_bl_params_desc();
+
+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
+ assert_stm32mp1_monotonic_counter_reach_max);
+
+ /* Check if monotonic counter need to be incremented */
+ ;
+ if (bsec_shadow_read_otp(&version, MONOTONIC_OTP) != BSEC_OK) {
+ ERROR("BSEC: MONOTONIC_OTP Error\n");
+ panic();
+ }
+
+ INFO("read version %i current version %i\n", version, STM32_TF_VERSION);
+
+ if ((version + 1U) < BIT(STM32_TF_VERSION)) {
+ uint32_t result;
+
+ /* need to increment the monotonic counter */
+ version = BIT(STM32_TF_VERSION) - 1U;
+
+ result = bsec_program_otp(version, MONOTONIC_OTP);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: MONOTONIC_OTP program Error %i\n",
+ result);
+ panic();
+ }
+ INFO("Monotonic counter has been incremented value 0x%x\n",
+ version);
+ }
}
+#ifdef AARCH32_SP_OPTEE
+static bool addr_inside_backupsram(uintptr_t addr)
+{
+ return (addr >= STM32MP_BACKUP_RAM_BASE) &&
+ (addr < (STM32MP_BACKUP_RAM_BASE + STM32MP_BACKUP_RAM_SIZE));
+}
+#endif
+
/*******************************************************************************
* This function returns the list of loadable images.
******************************************************************************/
bl_load_info_t *plat_get_bl_image_load_info(void)
{
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+#ifdef AARCH32_SP_OPTEE
+ bl_mem_params_node_t *bl32 = get_bl_mem_params_node(BL32_IMAGE_ID);
+#endif
+ bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID);
+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
+ uint32_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uintptr_t pwr_base = stm32mp_pwr_base();
+
+ /*
+ * If going back from CSTANDBY / STANDBY and DDR was in Self-Refresh,
+ * BL33 must not be loaded as it would overwrite the code already
+ * in DDR. For this, the BL33 part of the bl_mem_params_desc_ptr
+ * struct should be modified to skip its loading
+ */
+ if (((boot_context->boot_action ==
+ BOOT_API_CTX_BOOT_ACTION_WAKEUP_CSTANDBY) ||
+ (boot_context->boot_action ==
+ BOOT_API_CTX_BOOT_ACTION_WAKEUP_STANDBY)) &&
+ ((mmio_read_32(pwr_base + PWR_CR3) & PWR_CR3_DDRSREN) != 0U) &&
+ ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U)) {
+ stm32mp_clk_enable(RTCAPB);
+
+ if (mmio_read_32(bkpr_core1_addr) != 0U) {
+ bl33->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
+
+#ifdef AARCH32_SP_OPTEE
+ bl32->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
+ bl32->ep_info.pc = stm32_pm_get_optee_ep();
+
+ if (addr_inside_backupsram(bl32->ep_info.pc)) {
+ stm32mp_clk_enable(BKPSRAM);
+ }
+#else
+ /*
+ * Set ep_info PC to 0, to inform BL32 it is a reset
+ * after STANDBY
+ */
+ bl33->ep_info.pc = 0;
+#endif
+ }
+
+ stm32mp_clk_disable(RTCAPB);
+ }
+
+ bl33->image_info.image_max_size = dt_get_ddr_size();
+
return get_bl_load_info_from_mem_params_desc();
}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 30b2932..06594f0 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -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
#
@@ -8,24 +8,78 @@ ARM_CORTEX_A7 := yes
ARM_WITH_NEON := yes
BL2_AT_EL3 := 1
USE_COHERENT_MEM := 0
+MULTI_CONSOLE_API := 1
+# Please don't increment this value without good understanding of
+# the monotonic counter
STM32_TF_VERSION ?= 0
+$(eval $(call add_define_val,STM32_TF_VERSION,${STM32_TF_VERSION}))
+
+# Enable software PMIC programming in case of debug purpose
+STM32MP1_DEBUG_ENABLE ?= 1
+$(eval $(call add_define_val,STM32MP1_DEBUG_ENABLE,${STM32MP1_DEBUG_ENABLE}))
# Not needed for Cortex-A7
WORKAROUND_CVE_2017_5715:= 0
-PLAT_INCLUDES := -Iplat/st/stm32mp1/include/
-PLAT_INCLUDES += -Iinclude/common/tbbr
+# Specific modification for reset halt workaround
+STM32MP1_RESET_HALT_WORKAROUND ?= 1
+$(eval $(call add_define,STM32MP1_RESET_HALT_WORKAROUND))
+
+AARCH32_EXCEPTION_DEBUG := 1
+
+ifeq ($(AARCH32_SP),optee)
+$(eval $(call add_define,AARCH32_SP_OPTEE))
+endif
+
+# Number of TF-A copies in the device
+STM32_TF_A_COPIES := 2
+$(eval $(call add_define,STM32_TF_A_COPIES))
+ifeq ($(AARCH32_SP),optee)
+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4)))
+else
+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1)))
+endif
+$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
+
+# Boot devices
+STM32MP1_QSPI_NOR := 1
+$(eval $(call add_define,STM32MP1_QSPI_NOR))
+STM32MP_FMC_NAND := 1
+$(eval $(call add_define,STM32MP_FMC_NAND))
+STM32MP_EMMC := 1
+$(eval $(call add_define,STM32MP_EMMC))
+STM32MP_SDMMC := 1
+$(eval $(call add_define,STM32MP_SDMMC))
+STM32MP1_QSPI_NAND := 1
+$(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
+
+STM32MP_UART_PROGRAMMER := 1
+$(eval $(call add_define,STM32MP_UART_PROGRAMMER))
+
+PLAT_INCLUDES := -Iinclude/common/tbbr
+PLAT_INCLUDES += -Iinclude/drivers/partition
PLAT_INCLUDES += -Iinclude/drivers/st
+PLAT_INCLUDES += -Iplat/st/common/include/
+PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
+
+PLAT_INCLUDES += -Iinclude/lib/usb
+
+STM32MP_USB := 1
# Device tree
-STM32_DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
-FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME)))
+DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
+FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME)))
DTC_FLAGS += -Wno-unit_address_vs_reg
include lib/libfdt/libfdt.mk
-PLAT_BL_COMMON_SOURCES := plat/st/stm32mp1/stm32mp1_common.c
+PLAT_BL_COMMON_SOURCES := plat/st/common/stm32mp_common.c \
+ plat/st/stm32mp1/stm32mp1_private.c
PLAT_BL_COMMON_SOURCES += drivers/console/aarch32/console.S \
drivers/st/uart/aarch32/stm32_console.S
@@ -43,23 +97,56 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \
drivers/arm/tzc/tzc400.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
+ drivers/st/bsec/bsec.c \
+ drivers/st/clk/stm32mp_clkfunc.c \
drivers/st/clk/stm32mp1_clk.c \
drivers/st/clk/stm32mp1_clkfunc.c \
drivers/st/ddr/stm32mp1_ddr_helpers.c \
drivers/st/gpio/stm32_gpio.c \
- drivers/st/pmic/stm32_i2c.c \
- drivers/st/pmic/stm32mp1_pmic.c \
- drivers/st/pmic/stpmu1.c \
+ drivers/st/i2c/stm32_i2c.c \
+ drivers/st/iwdg/stm32_iwdg.c \
+ drivers/st/pmic/stm32mp_pmic.c \
+ drivers/st/pmic/stpmic1.c \
drivers/st/reset/stm32mp1_reset.c \
+ plat/st/common/stm32mp_dt.c \
+ plat/st/common/stm32mp_shres_helpers.c \
plat/st/stm32mp1/stm32mp1_context.c \
- plat/st/stm32mp1/stm32mp1_dt.c \
+ plat/st/stm32mp1/stm32mp1_dbgmcu.c \
plat/st/stm32mp1/stm32mp1_helper.S \
- plat/st/stm32mp1/stm32mp1_security.c
+ plat/st/stm32mp1/stm32mp1_security.c \
+ plat/st/stm32mp1/stm32mp1_shared_resources.c
-BL2_SOURCES += drivers/io/io_dummy.c \
+BL2_SOURCES += drivers/io/io_block.c \
+ drivers/io/io_dummy.c \
drivers/io/io_storage.c \
- plat/st/stm32mp1/bl2_io_storage.c \
- plat/st/stm32mp1/bl2_plat_setup.c
+ drivers/st/hash/hash_sec.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
+
+ifeq (${STM32MP1_QSPI_NOR},1)
+BL2_SOURCES += drivers/st/qspi/io_qspi.c
+endif
+
+ifeq (${STM32MP_FMC_NAND},1)
+BL2_SOURCES += drivers/st/nand/io_nand.c \
+ drivers/st/nand/nand.c
+endif
+
+ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
+BL2_SOURCES += drivers/mmc/mmc.c \
+ drivers/partition/gpt.c \
+ drivers/partition/partition.c \
+ drivers/st/io/io_mmc.c \
+ drivers/st/mmc/stm32_sdmmc2.c
+endif
+
+ifeq (${STM32MP_UART_PROGRAMMER},1)
+BL2_SOURCES += drivers/st/uart/io_programmer_uart.c \
+ drivers/st/uart/stm32mp1xx_hal_uart.c
+endif
BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \
drivers/st/ddr/stm32mp1_ram.c
@@ -68,19 +155,36 @@ BL2_SOURCES += common/desc_image_load.c \
plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
plat/st/stm32mp1/plat_image_load.c
-# For memory footprint optimization, build with thumb and interwork support
-ASFLAGS += -mthumb -mthumb-interwork
-TF_CFLAGS += -mthumb -mthumb-interwork
+ifneq (${STM32MP_USB},0)
+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)
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+ifeq (${STM32MP1_RESET_HALT_WORKAROUND},1)
+BL2_SOURCES += plat/st/stm32mp1/stm32mp1_helper_dbg.S
+endif
+
+# Do not use neon in TF-A code, it leads to issues in low-power functions
+TF_CFLAGS += -mfloat-abi=soft
# Macros and rules to build TF binary
STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
-STM32_DT_BASENAME := $(STM32_DTB_FILE_NAME:.dtb=)
+STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=)
STM32_TF_STM32 := ${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32
STM32_TF_BINARY := $(STM32_TF_STM32:.stm32=.bin)
STM32_TF_MAPFILE := $(STM32_TF_STM32:.stm32=.map)
STM32_TF_LINKERFILE := $(STM32_TF_STM32:.stm32=.ld)
STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf)
-STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME}
+STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o
# Variables for use with stm32image
@@ -123,7 +227,7 @@ ${STM32_TF_OBJS}: plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE
-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
-c plat/st/stm32mp1/stm32mp1.S -o $@
-${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S
+${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT}
@echo " LDS $<"
${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
new file mode 100644
index 0000000..e4f86a2
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <runtime_svc.h>
+#include <std_svc.h>
+#include <stm32mp_pmic.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_smc.h>
+#include <stpmic1.h>
+
+#include "bsec_svc.h"
+
+#define SSP_OTP_REQ BIT(BOOT_API_OTP_SSP_REQ_BIT_POS)
+#define SSP_OTP_SUCCESS BIT(BOOT_API_OTP_SSP_SUCCESS_BIT_POS)
+#define SSP_OTP_MASK (SSP_OTP_REQ | SSP_OTP_SUCCESS)
+
+enum bsec_ssp_status {
+ BSEC_NO_SSP = 0,
+ BSEC_SSP_SET,
+ BSEC_SSP_ERROR
+};
+
+struct otp_exchange {
+ uint32_t version;
+ uint32_t configuration;
+ uint32_t reserved;
+ uint32_t status;
+ uint32_t general_lock;
+ uint32_t debug_conf;
+ uint32_t reserved1[2];
+ uint32_t otp_disturb[3];
+ uint32_t reserved2[3];
+ uint32_t error_status[3];
+ uint32_t reserved3[3];
+ uint32_t permanent_lock[3];
+ uint32_t reserved4[3];
+ uint32_t programming_lock[3];
+ uint32_t reserved5[3];
+ uint32_t shadow_write_lock[3];
+ uint32_t reserved6[3];
+ uint32_t shadow_read_lock[3];
+ uint32_t reserved7[3];
+ uint32_t otp_value[STM32MP1_OTP_MAX_ID + 1];
+ uint32_t reserved8[112];
+ uint32_t bsec_hw_conf;
+ uint32_t ip_version;
+ uint32_t ip_id;
+ uint32_t ip_magic_id;
+};
+
+static enum bsec_ssp_status bsec_check_ssp(uint32_t otp, uint32_t update)
+{
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)BOOT_PARAM_ADDR;
+
+ /* No SSP update or SSP already done*/
+ if ((((otp & SSP_OTP_MASK) == 0U) && ((update & SSP_OTP_MASK) == 0U)) ||
+ (((otp & SSP_OTP_MASK) == SSP_OTP_MASK) &&
+ ((update & SSP_OTP_MASK) == SSP_OTP_MASK))) {
+ return BSEC_NO_SSP;
+ }
+
+ /* SSP update */
+ if ((update & SSP_OTP_MASK) != 0U) {
+ if ((update & SSP_OTP_SUCCESS) != 0U) {
+ return BSEC_SSP_ERROR;
+ }
+
+ /* SSP boot process */
+ boot_context->p_ssp_config->ssp_cmd =
+ BOOT_API_CTX_SSP_CMD_CALC_CHIP_PUBK;
+#ifndef DCACHE_OFF
+ flush_dcache_range((uintptr_t)boot_context->p_ssp_config,
+ sizeof(boot_api_ssp_config_t));
+#endif
+ if (dt_pmic_status() > 0) {
+ initialize_pmic();
+ stpmic1_regulator_mask_reset_set("buck1");
+ }
+
+ return BSEC_SSP_SET;
+ }
+ return BSEC_NO_SSP;
+}
+
+static uint32_t bsec_read_all_bsec(struct otp_exchange *exchange)
+{
+ uint32_t i;
+ uint32_t result;
+
+ if (exchange == NULL) {
+ return BSEC_ERROR;
+ }
+
+ exchange->version = BSEC_SERVICE_VERSION;
+
+ for (i = 0U; i <= STM32MP1_OTP_MAX_ID; i++) {
+ if (bsec_check_nsec_access_rights(i) == BSEC_OK) {
+ result = bsec_shadow_register(i);
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ result = bsec_read_otp(&exchange->otp_value[i], i);
+ if (result != BSEC_OK) {
+ return result;
+ }
+ }
+ }
+
+ exchange->configuration = mmio_read_32(bsec_get_base() +
+ BSEC_OTP_CONF_OFF);
+
+ exchange->status = mmio_read_32(bsec_get_base() + BSEC_OTP_STATUS_OFF);
+
+ exchange->general_lock = mmio_read_32(bsec_get_base() +
+ BSEC_OTP_LOCK_OFF);
+
+ exchange->debug_conf = mmio_read_32(bsec_get_base() + BSEC_DEN_OFF);
+
+ exchange->otp_disturb[0] = mmio_read_32(bsec_get_base() +
+ BSEC_DISTURBED_OFF);
+
+ exchange->otp_disturb[1] = mmio_read_32(bsec_get_base() +
+ BSEC_DISTURBED1_OFF);
+
+ exchange->otp_disturb[2] = mmio_read_32(bsec_get_base() +
+ BSEC_DISTURBED2_OFF);
+
+ exchange->error_status[0] = mmio_read_32(bsec_get_base() +
+ BSEC_ERROR_OFF);
+
+ exchange->error_status[1] = mmio_read_32(bsec_get_base() +
+ BSEC_ERROR1_OFF);
+
+ exchange->error_status[2] = mmio_read_32(bsec_get_base() +
+ BSEC_ERROR2_OFF);
+
+ exchange->permanent_lock[0] = mmio_read_32(bsec_get_base() +
+ BSEC_WRLOCK_OFF);
+
+ exchange->permanent_lock[1] = mmio_read_32(bsec_get_base() +
+ BSEC_WRLOCK1_OFF);
+
+ exchange->permanent_lock[2] = mmio_read_32(bsec_get_base() +
+ BSEC_WRLOCK2_OFF);
+
+ exchange->programming_lock[0] = mmio_read_32(bsec_get_base() +
+ BSEC_SPLOCK_OFF);
+
+ exchange->programming_lock[1] = mmio_read_32(bsec_get_base() +
+ BSEC_SPLOCK1_OFF);
+
+ exchange->programming_lock[2] = mmio_read_32(bsec_get_base() +
+ BSEC_SPLOCK2_OFF);
+
+ exchange->shadow_write_lock[0] = mmio_read_32(bsec_get_base() +
+ BSEC_SWLOCK_OFF);
+
+ exchange->shadow_write_lock[1] = mmio_read_32(bsec_get_base() +
+ BSEC_SWLOCK1_OFF);
+
+ exchange->shadow_write_lock[2] = mmio_read_32(bsec_get_base() +
+ BSEC_SWLOCK2_OFF);
+
+ exchange->shadow_read_lock[0] = mmio_read_32(bsec_get_base() +
+ BSEC_SRLOCK_OFF);
+
+ exchange->shadow_read_lock[1] = mmio_read_32(bsec_get_base() +
+ BSEC_SRLOCK1_OFF);
+
+ exchange->shadow_read_lock[2] = mmio_read_32(bsec_get_base() +
+ BSEC_SRLOCK2_OFF);
+
+ exchange->bsec_hw_conf = mmio_read_32(bsec_get_base() +
+ BSEC_IPHW_CFG_OFF);
+
+ exchange->ip_version = mmio_read_32(bsec_get_base() + BSEC_IPVR_OFF);
+
+ exchange->ip_id = mmio_read_32(bsec_get_base() + BSEC_IP_ID_OFF);
+
+ exchange->ip_magic_id = mmio_read_32(bsec_get_base() +
+ BSEC_IP_MAGIC_ID_OFF);
+
+ return BSEC_OK;
+}
+
+static uint32_t bsec_write_all_bsec(struct otp_exchange *exchange,
+ uint32_t *ret_otp_value)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t start_otp = 0U;
+ uint32_t value = 0U;
+ uint32_t ret;
+ struct bsec_config config_param;
+
+ *ret_otp_value = 0U;
+
+ if (exchange == NULL) {
+ return BSEC_ERROR;
+ }
+
+ if (exchange->version != BSEC_SERVICE_VERSION) {
+ return BSEC_ERROR;
+ }
+
+ for (i = start_otp; i <= STM32MP1_OTP_MAX_ID; i++) {
+ if (bsec_check_nsec_access_rights(i) != BSEC_OK) {
+ continue;
+ }
+
+ ret = bsec_shadow_register(i);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ ret = bsec_read_otp(&value, i);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ if ((value == exchange->otp_value[i]) &&
+ (i != BOOT_API_OTP_SSP_WORD_NB)) {
+ continue;
+ }
+
+ if (i == BOOT_API_OTP_SSP_WORD_NB) {
+ *ret_otp_value = (uint32_t)bsec_check_ssp(value,
+ exchange->otp_value[i]);
+ VERBOSE("Result OTP SSP %d\n", *ret_otp_value);
+ if (*ret_otp_value == (uint32_t)BSEC_SSP_ERROR) {
+ continue;
+ }
+ }
+
+ ret = bsec_program_otp(exchange->otp_value[i], i);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ ret = bsec_write_otp(exchange->otp_value[i], i);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+ }
+
+ ret = bsec_write_debug_conf(exchange->debug_conf);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ for (j = 0U; j < 3U; j++) {
+ if (exchange->permanent_lock[j] == 0U) {
+ continue;
+ }
+
+ for (i = 0U; i < 32U; i++) {
+ if (bsec_check_nsec_access_rights((32U * j) + i) !=
+ BSEC_OK) {
+ continue;
+ }
+
+ value = (exchange->permanent_lock[j] >> i) & 1U;
+ if (value != 0U) {
+ ret = bsec_permanent_lock_otp((32U * j) + i);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+ }
+ }
+ }
+
+ for (j = 0U; j < 3U; j++) {
+ if (exchange->programming_lock[j] == 0U) {
+ continue;
+ }
+
+ for (i = 0U; i < 32U; i++) {
+ if (bsec_check_nsec_access_rights((32U * j) + i) !=
+ BSEC_OK) {
+ continue;
+ }
+
+ value = (exchange->programming_lock[j] >> i) & 1U;
+ if (value != 0U) {
+ if (!bsec_write_sp_lock((32U * j) + i, 1U)) {
+ return BSEC_ERROR;
+ }
+ }
+ }
+ }
+
+ for (j = 0U; j < 3U; j++) {
+ if (exchange->shadow_write_lock[j] == 0U) {
+ continue;
+ }
+
+ for (i = 0U; i < 32U; i++) {
+ if (bsec_check_nsec_access_rights((32U * j) + i) !=
+ BSEC_OK) {
+ continue;
+ }
+
+ value = (exchange->shadow_write_lock[j] >> i) & 1U;
+ if (value != 0U) {
+ if (!bsec_write_sw_lock((32U * j) + i, 1U)) {
+ return BSEC_ERROR;
+ }
+ }
+ }
+ }
+
+ for (j = 0U; j < 3U; j++) {
+ if (exchange->shadow_read_lock[j] == 0U) {
+ continue;
+ }
+
+ for (i = 0U; i < 32U; i++) {
+ if (bsec_check_nsec_access_rights((32U * j) + i) !=
+ BSEC_OK) {
+ continue;
+ }
+
+ value = (exchange->shadow_read_lock[j] >> i) & 1U;
+ if (value != 0U) {
+ if (!bsec_write_sr_lock((32U * j) + i, 1U)) {
+ return BSEC_ERROR;
+ }
+ }
+ }
+ }
+
+ ret = bsec_get_config(&config_param);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ config_param.power =
+ (uint8_t)(exchange->configuration & BSEC_CONF_POWER_UP_MASK) >>
+ BSEC_CONF_POWER_UP_SHIFT;
+ config_param.freq =
+ (uint8_t)(exchange->configuration & BSEC_CONF_FRQ_MASK) >>
+ BSEC_CONF_FRQ_SHIFT;
+ config_param.pulse_width =
+ (uint8_t)(exchange->configuration & BSEC_CONF_PRG_WIDTH_MASK) >>
+ BSEC_CONF_PRG_WIDTH_SHIFT;
+ config_param.tread =
+ (uint8_t)((exchange->configuration & BSEC_CONF_TREAD_MASK) >>
+ BSEC_CONF_TREAD_SHIFT);
+ config_param.den_lock =
+ (uint8_t)(exchange->general_lock & DENREG_LOCK_MASK) >>
+ DENREG_LOCK_SHIFT;
+ config_param.prog_lock =
+ (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;
+ }
+
+ ret = bsec_set_config(&config_param);
+ if (ret != BSEC_OK) {
+ return ret;
+ }
+
+ INFO("write all otp succeed\n");
+
+ return BSEC_OK;
+}
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value)
+{
+ 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)) {
+ return BSEC_ERROR;
+ }
+
+ if (((x1 == STM32_SMC_READ_ALL) || (x1 == STM32_SMC_WRITE_ALL)) &&
+ (!ddr_is_nonsecured_area((uintptr_t)x2,
+ sizeof(struct otp_exchange)))) {
+ return BSEC_ERROR;
+ }
+
+ switch (x1) {
+ case STM32_SMC_READ_SHADOW:
+ result = bsec_read_otp(ret_otp_value, x2);
+ break;
+ case STM32_SMC_PROG_OTP:
+ *ret_otp_value = 0U;
+ if (x2 == BOOT_API_OTP_SSP_WORD_NB) {
+ result = bsec_read_otp(&tmp_data, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ *ret_otp_value = (uint32_t)bsec_check_ssp(tmp_data,
+ otp_exch->otp_value[x2]);
+ if (*ret_otp_value == (uint32_t)BSEC_SSP_ERROR) {
+ result = BSEC_OK;
+ break;
+ }
+ }
+ result = bsec_program_otp(x3, x2);
+ break;
+ case STM32_SMC_WRITE_SHADOW:
+ *ret_otp_value = 0;
+ result = bsec_write_otp(x3, x2);
+ break;
+ case STM32_SMC_READ_OTP:
+ *ret_otp_value = 0;
+ result = bsec_read_otp(&tmp_data, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_shadow_register(x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_read_otp(ret_otp_value, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_write_otp(tmp_data, x2);
+ break;
+ case STM32_SMC_READ_ALL:
+ result = bsec_read_all_bsec(otp_exch);
+ break;
+ case STM32_SMC_WRITE_ALL:
+ result = bsec_write_all_bsec(otp_exch, ret_otp_value);
+ break;
+ default:
+ result = BSEC_ERROR;
+ break;
+ }
+
+ return result;
+}
diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h
new file mode 100644
index 0000000..75c9aa3
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016-2017, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BSEC_SVC_H
+#define BSEC_SVC_H
+
+#include <arch.h>
+#include <bl_common.h>
+#include <bsec.h>
+
+/* version of this service */
+/* must be increase at each structure modification */
+#define BSEC_SERVICE_VERSION 0x01U
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value);
+
+#endif /* BSEC_SVC_H */
diff --git a/plat/st/stm32mp1/services/low_power_svc.c b/plat/st/stm32mp1/services/low_power_svc.c
new file mode 100644
index 0000000..a7fe026
--- /dev/null
+++ b/plat/st/stm32mp1/services/low_power_svc.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <smccc_helpers.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_power_config.h>
+#include <stm32mp1_smc.h>
+#include "low_power_svc.h"
+
+uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2)
+{
+ uint32_t ret = STM32_SMC_OK;
+
+ switch (x2) {
+ case STM32_SMC_SR_MODE_SSR:
+ ddr_sr_mode_ssr();
+ break;
+
+ case STM32_SMC_SR_MODE_ASR:
+ ddr_sr_mode_asr();
+ break;
+
+ case STM32_SMC_SR_MODE_HSR:
+ ddr_sr_mode_hsr();
+ break;
+
+ default:
+ ret = STM32_SMC_INVALID_PARAMS;
+ break;
+ }
+
+ return ret;
+}
+
+uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2)
+{
+ if (stm32mp1_set_pm_domain_state((enum stm32mp1_pm_domain)x1,
+ (bool)x2) < 0) {
+ return STM32_SMC_FAILED;
+ }
+
+ return STM32_SMC_OK;
+}
diff --git a/plat/st/stm32mp1/services/low_power_svc.h b/plat/st/stm32mp1/services/low_power_svc.h
new file mode 100644
index 0000000..1264fa1
--- /dev/null
+++ b/plat/st/stm32mp1/services/low_power_svc.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LOW_POWER_SVC_H
+#define LOW_POWER_SVC_H
+
+#include <stdint.h>
+
+uint32_t sr_mode_scv_handler(uint32_t x1, uint32_t x2);
+uint32_t pm_domain_scv_handler(uint32_t x1, uint32_t x2);
+
+#endif /* LOW_POWER_SVC_H */
diff --git a/plat/st/stm32mp1/services/pwr_svc.c b/plat/st/stm32mp1/services/pwr_svc.c
new file mode 100644
index 0000000..80dcc7c
--- /dev/null
+++ b/plat/st/stm32mp1/services/pwr_svc.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <spinlock.h>
+#include <stm32mp_common.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_smc.h>
+#include "pwr_svc.h"
+
+static struct spinlock lock;
+
+void pwr_regs_lock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Lock is currently required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_lock(&lock);
+ }
+}
+
+void pwr_regs_unlock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Unlock is required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_unlock(&lock);
+ }
+}
+
+static void access_allowed_mask(uint32_t request, uint32_t offset,
+ uint32_t value, uint32_t allowed_mask)
+{
+ uint32_t addr = stm32mp_pwr_base() + offset;
+ uint32_t masked_value = value & allowed_mask;
+
+ pwr_regs_lock();
+
+ switch (request) {
+ case STM32_SMC_REG_WRITE:
+ mmio_clrsetbits_32(addr, allowed_mask, masked_value);
+ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ case STM32_SMC_REG_SET:
+ mmio_setbits_32(addr, masked_value);
+ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ case STM32_SMC_REG_CLEAR:
+ mmio_clrbits_32(addr, masked_value);
+ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ default:
+ break;
+ }
+
+ pwr_regs_unlock();
+}
+
+static void raw_allowed_access_request(uint32_t request,
+ uint32_t offset, uint32_t value)
+{
+ uint32_t allowed_mask = 0;
+
+ switch (offset) {
+ case PWR_CR3:
+ allowed_mask |= PWR_CR3_VBE | PWR_CR3_VBRS | PWR_CR3_USB33DEN |
+ PWR_CR3_REG18EN | PWR_CR3_REG11EN;
+ break;
+
+ case PWR_WKUPCR:
+ allowed_mask |= PWR_WKUPCR_MASK;
+ break;
+
+ case PWR_MPUWKUPENR:
+ allowed_mask |= PWR_MPUWKUPENR_MASK;
+ break;
+
+ default:
+ return;
+ }
+
+ if (allowed_mask != 0U) {
+ access_allowed_mask(request, offset, value, allowed_mask);
+ }
+}
+
+uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3)
+{
+ uint32_t request = x1;
+ uint32_t offset = x2;
+ uint32_t value = x3;
+
+ /*
+ * x2 may be either the PWR register offset or the register
+ * full physical address.
+ */
+ if ((offset & ~PWR_OFFSET_MASK) != 0) {
+ if ((offset & ~PWR_OFFSET_MASK) != stm32mp_pwr_base()) {
+ return STM32_SMC_INVALID_PARAMS;
+ }
+
+ offset &= PWR_OFFSET_MASK;
+ }
+
+ /* PWR controls for non secure resource may be accessed straight */
+ raw_allowed_access_request(request, offset, value);
+
+ return STM32_SMC_OK;
+}
diff --git a/plat/st/stm32mp1/services/pwr_svc.h b/plat/st/stm32mp1/services/pwr_svc.h
new file mode 100644
index 0000000..90cf1a3
--- /dev/null
+++ b/plat/st/stm32mp1/services/pwr_svc.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PWR_SVC_H
+#define PWR_SVC_H
+
+uint32_t pwr_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3);
+
+#endif /* PWR_SVC_H */
diff --git a/plat/st/stm32mp1/services/rcc_svc.c b/plat/st/stm32mp1/services/rcc_svc.c
new file mode 100644
index 0000000..1df6903
--- /dev/null
+++ b/plat/st/stm32mp1/services/rcc_svc.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <limits.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32_gpio.h>
+#include <stm32mp_common.h>
+#include <stm32mp_shres_helpers.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#include <stm32mp1_smc.h>
+#include "rcc_svc.h"
+
+#define STD_REG 0
+#define SET_REG 1
+#define CLR_REG 2
+
+static void shared_clk_request(uint32_t request,
+ uint32_t offset, uint32_t value)
+{
+ unsigned long id;
+ unsigned int bit;
+ uint32_t enable_bits = 0;
+ int clr_std_set = STD_REG;
+
+ switch (request) {
+ case STM32_SMC_REG_WRITE:
+ case STM32_SMC_REG_SET:
+ case STM32_SMC_REG_CLEAR:
+ break;
+ default:
+ return;
+ }
+
+ switch (offset) {
+ case RCC_MP_APB5ENSETR:
+ clr_std_set = SET_REG;
+ /* Non secure backup registers requires RTCAPB clock */
+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN;
+ break;
+ case RCC_MP_APB5ENCLRR:
+ clr_std_set = CLR_REG;
+ /* Non secure backup registers requires RTCAPB clock */
+ enable_bits |= RCC_MP_APB5ENSETR_RTCAPBEN;
+ break;
+
+ case RCC_MP_AHB5ENSETR:
+ clr_std_set = SET_REG;
+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) {
+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN;
+ }
+ break;
+ case RCC_MP_AHB5ENCLRR:
+ clr_std_set = CLR_REG;
+ if (stm32mp_gpio_bank_is_shared(GPIO_BANK_Z)) {
+ enable_bits |= RCC_MP_AHB5ENSETR_GPIOZEN;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ((clr_std_set != STD_REG) && (request == STM32_SMC_REG_CLEAR)) {
+ return;
+ }
+
+ /*
+ * Parse bit that relate to a functional clock.
+ * Call stm32mp1_clk_enable/disable_non_secure() for that clock
+ * according to request (write/set/clear) and target register
+ * (write or set/clear).
+ */
+ for (bit = 0; bit < __WORD_BIT; bit++) {
+
+ if ((BIT(bit) & enable_bits) == 0U) {
+ continue;
+ }
+
+ id = stm32mp1_clk_rcc2id(offset, bit);
+ if (id == ~0U) {
+ panic();
+ }
+
+ switch (clr_std_set) {
+ case SET_REG:
+ if ((BIT(bit) & value) != 0U) {
+ stm32mp1_clk_enable_non_secure(id);
+ }
+ break;
+ case CLR_REG:
+ if ((BIT(bit) & value) != 0U) {
+ stm32mp1_clk_disable_non_secure(id);
+ }
+ break;
+ default:
+ /* Standard registers case */
+ switch (request) {
+ case STM32_SMC_REG_WRITE:
+ if ((BIT(bit) & value) != 0U) {
+ stm32mp1_clk_enable_non_secure(id);
+ } else {
+ stm32mp1_clk_disable_non_secure(id);
+ }
+ break;
+ case STM32_SMC_REG_SET:
+ if ((BIT(bit) & value) != 0U) {
+ stm32mp1_clk_enable_non_secure(id);
+ }
+ break;
+ case STM32_SMC_REG_CLEAR:
+ if ((BIT(bit) & value) != 0U) {
+ stm32mp1_clk_disable_non_secure(id);
+ }
+ break;
+ default:
+ return;
+ }
+ break;
+ }
+
+ enable_bits &= ~BIT(bit);
+ if (enable_bits == 0U) {
+ break;
+ }
+ }
+}
+
+static void access_allowed_mask(uint32_t request, uint32_t offset,
+ uint32_t value, uint32_t allowed_mask)
+{
+ uint32_t addr = stm32mp_rcc_base() + offset;
+ uint32_t masked_value = value & allowed_mask;
+
+ switch (request) {
+ case STM32_SMC_REG_WRITE:
+ switch (offset) {
+ /* CLR registers show the SET state, not the CLR state */
+ case RCC_OCENCLRR:
+ case RCC_MP_SREQCLRR:
+ case RCC_APB5RSTCLRR:
+ case RCC_AHB5RSTCLRR:
+ case RCC_MP_APB5ENCLRR:
+ case RCC_MP_AHB5ENCLRR:
+ case RCC_MP_APB5LPENCLRR:
+ case RCC_MP_AHB5LPENCLRR:
+ case RCC_MP_IWDGFZCLRR:
+ mmio_write_32(addr, masked_value);
+ break;
+ default:
+ stm32mp_mmio_clrsetbits_32_shregs(addr, allowed_mask,
+ masked_value);
+ break;
+ }
+ VERBOSE("wrt 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ case STM32_SMC_REG_SET:
+ switch (offset) {
+ /* CLR registers show the SET state, not the CLR state */
+ case RCC_OCENCLRR:
+ case RCC_MP_SREQCLRR:
+ case RCC_APB5RSTCLRR:
+ case RCC_AHB5RSTCLRR:
+ case RCC_MP_APB5ENCLRR:
+ case RCC_MP_AHB5ENCLRR:
+ case RCC_MP_APB5LPENCLRR:
+ case RCC_MP_AHB5LPENCLRR:
+ case RCC_MP_IWDGFZCLRR:
+ mmio_write_32(addr, masked_value);
+ break;
+ default:
+ stm32mp_mmio_setbits_32_shregs(addr, masked_value);
+ break;
+ }
+ VERBOSE("set 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ case STM32_SMC_REG_CLEAR:
+ switch (offset) {
+ case RCC_OCENCLRR:
+ case RCC_MP_SREQCLRR:
+ case RCC_APB5RSTCLRR:
+ case RCC_AHB5RSTCLRR:
+ case RCC_MP_APB5ENCLRR:
+ case RCC_MP_AHB5ENCLRR:
+ case RCC_MP_APB5LPENCLRR:
+ case RCC_MP_AHB5LPENCLRR:
+ case RCC_MP_IWDGFZCLRR:
+ /* Nothing to do on CLR registers */
+ break;
+ default:
+ stm32mp_mmio_clrbits_32_shregs(addr, masked_value);
+ break;
+ }
+ VERBOSE("clear 0x%x = 0x%x => 0x%x\n", offset, value,
+ mmio_read_32(addr));
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void raw_allowed_access_request(uint32_t request,
+ uint32_t offset, uint32_t value)
+{
+ uint32_t allowed_mask = 0;
+
+ /* Use UINT32_MAX if no secure restriction on register access */
+ switch (offset) {
+ case RCC_OCENSETR:
+ case RCC_OCENCLRR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) {
+ allowed_mask |= RCC_OCENR_HSION | RCC_OCENR_HSIKERON;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) {
+ allowed_mask |= RCC_OCENR_CSION | RCC_OCENR_CSIKERON;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSE)) {
+ allowed_mask |= RCC_OCENR_HSEON | RCC_OCENR_HSEKERON |
+ RCC_OCENR_HSEBYP | RCC_OCENR_HSECSSON |
+ RCC_OCENR_DIGBYP;
+ }
+ break;
+
+ case RCC_HSICFGR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+
+ case RCC_CSICFGR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+
+ case RCC_MP_CIER:
+ case RCC_MP_CIFR:
+ /* RCC_MP_CIFR_xxxRDYF matches CIER and CIFR bit mapping */
+ allowed_mask |= RCC_MP_CIFR_WKUPF | RCC_MP_CIFR_PLL4DYF;
+
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_LSI)) {
+ allowed_mask |= RCC_MP_CIFR_LSIRDYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_LSE)) {
+ allowed_mask |= RCC_MP_CIFR_LSERDYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSI)) {
+ allowed_mask |= RCC_MP_CIFR_HSIRDYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HSE)) {
+ allowed_mask |= RCC_MP_CIFR_HSERDYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CSI)) {
+ allowed_mask |= RCC_MP_CIFR_CSIRDYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1)) {
+ allowed_mask |= RCC_MP_CIFR_PLL1DYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2)) {
+ allowed_mask |= RCC_MP_CIFR_PLL2DYF;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3)) {
+ allowed_mask |= RCC_MP_CIFR_PLL3DYF;
+ }
+ break;
+
+ case RCC_PLL1CR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_P)) {
+ allowed_mask |= RCC_PLLNCR_DIVPEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_Q)) {
+ allowed_mask |= RCC_PLLNCR_DIVQEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1_R)) {
+ allowed_mask |= RCC_PLLNCR_DIVREN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL1)) {
+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY |
+ RCC_PLLNCR_SSCG_CTRL;
+ }
+ break;
+
+ case RCC_PLL2CR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_P)) {
+ allowed_mask |= RCC_PLLNCR_DIVPEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_Q)) {
+ allowed_mask |= RCC_PLLNCR_DIVQEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2_R)) {
+ allowed_mask |= RCC_PLLNCR_DIVREN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL2)) {
+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY |
+ RCC_PLLNCR_SSCG_CTRL;
+ }
+ break;
+
+ case RCC_PLL3CR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_P)) {
+ allowed_mask |= RCC_PLLNCR_DIVPEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_Q)) {
+ allowed_mask |= RCC_PLLNCR_DIVQEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3_R)) {
+ allowed_mask |= RCC_PLLNCR_DIVREN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_PLL3)) {
+ allowed_mask |= RCC_PLLNCR_PLLON | RCC_PLLNCR_PLLRDY |
+ RCC_PLLNCR_SSCG_CTRL;
+ }
+ break;
+
+ case RCC_MP_BOOTCR: /* Allowed MPU/MCU reboot cfg */
+ case RCC_MP_GCR: /* Allowed MPU/MCU reboot cfg */
+ case RCC_MP_GRSTCSETR: /* Allowed MCU and system reset */
+ case RCC_BR_RSTSCLRR: /* Allowed system reset status */
+ case RCC_MC_RSTSCLRR: /* Allowed system reset status */
+ case RCC_MP_RSTSCLRR: /* Allowed system reset status */
+ allowed_mask = UINT32_MAX;
+ break;
+ case RCC_APB5RSTSETR:
+ case RCC_APB5RSTCLRR:
+ case RCC_MP_APB5ENSETR:
+ case RCC_MP_APB5ENCLRR:
+ case RCC_MP_APB5LPENSETR:
+ case RCC_MP_APB5LPENCLRR:
+ /*
+ * SPI6/I2C4/I2C6/USART1/IWDG1 resources may be non secure.
+ * TZPC/TZC/BSEC/STGEN resources are secure only.
+ * Bit mask RCC_MP_APB5ENSETR_xxxEN fits EN, RST and LPEN.
+ */
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_SPI6)) {
+ allowed_mask |= RCC_MP_APB5ENSETR_SPI6EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C4)) {
+ allowed_mask |= RCC_MP_APB5ENSETR_I2C4EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C6)) {
+ allowed_mask |= RCC_MP_APB5ENSETR_I2C6EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_USART1)) {
+ allowed_mask |= RCC_MP_APB5ENSETR_USART1EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) {
+ allowed_mask |= RCC_MP_APB5ENSETR_IWDG1APBEN;
+ }
+ break;
+ case RCC_AHB5RSTSETR:
+ case RCC_AHB5RSTCLRR:
+ case RCC_MP_AHB5ENSETR:
+ case RCC_MP_AHB5ENCLRR:
+ case RCC_MP_AHB5LPENSETR:
+ case RCC_MP_AHB5LPENCLRR:
+ /*
+ * RNG1/HASH1/CRYP1/GPIOZ resources are accessible if
+ * related BKPSRAM resources are reserved to secure services.
+ * Bit mask RCC_MP_AHB5ENSETR_xxxEN fits EN, RST and LPEN.
+ */
+ if (stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z)) {
+ allowed_mask |= RCC_MP_AHB5ENSETR_GPIOZEN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_CRYP1)) {
+ allowed_mask |= RCC_MP_AHB5ENSETR_CRYP1EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_HASH1)) {
+ allowed_mask |= RCC_MP_AHB5ENSETR_HASH1EN;
+ }
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RNG1)) {
+ allowed_mask |= RCC_MP_AHB5ENSETR_RNG1EN;
+ }
+ break;
+ case RCC_RTCDIVR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RTC)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+ case RCC_I2C46CKSELR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C4) &&
+ stm32mp1_periph_is_non_secure(STM32MP1_SHRES_I2C6)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+ case RCC_SPI6CKSELR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_SPI6)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+ case RCC_UART1CKSELR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_USART1)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+ case RCC_RNG1CKSELR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_RNG1)) {
+ allowed_mask = UINT32_MAX;
+ }
+ break;
+ case RCC_MP_IWDGFZSETR:
+ case RCC_MP_IWDGFZCLRR:
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_IWDG1)) {
+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG1;
+ }
+ allowed_mask |= RCC_MP_IWDGFZSETR_IWDG2;
+ break;
+ default:
+ return;
+ }
+
+ if (allowed_mask != 0U) {
+ access_allowed_mask(request, offset, value, allowed_mask);
+ }
+}
+
+uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3)
+{
+ uint32_t request = x1;
+ uint32_t offset = x2;
+ uint32_t value = x3;
+
+ /*
+ * x2 may be either the RCC register offset or the register
+ * full physical address.
+ */
+ if ((offset & ~RCC_OFFSET_MASK) != 0) {
+ if ((offset & ~RCC_OFFSET_MASK) != stm32mp_rcc_base()) {
+ return STM32_SMC_INVALID_PARAMS;
+ }
+
+ offset &= RCC_OFFSET_MASK;
+ }
+
+ /* Some clocks may be managed by some secure services */
+ shared_clk_request(request, offset, value);
+
+ /* RCC controls for non secure resource may be accessed straight */
+ raw_allowed_access_request(request, offset, value);
+
+ return STM32_SMC_OK;
+}
+
+uint32_t rcc_cal_scv_handler(uint32_t x1)
+{
+ uint32_t ret = STM32_SMC_FAILED;
+
+ switch (x1) {
+ case CK_CSI:
+ if (stm32mp1_rcc_start_csi_cal() == 0) {
+ ret = STM32_SMC_OK;
+ }
+ break;
+
+ case CK_HSI:
+ if (stm32mp1_rcc_start_hsi_cal() == 0) {
+ ret = STM32_SMC_OK;
+ }
+ break;
+
+ default:
+ ret = STM32_SMC_INVALID_PARAMS;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/st/stm32mp1/services/rcc_svc.h b/plat/st/stm32mp1/services/rcc_svc.h
new file mode 100644
index 0000000..75d4a3c
--- /dev/null
+++ b/plat/st/stm32mp1/services/rcc_svc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RCC_SVC_H
+#define RCC_SVC_H
+
+uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3);
+uint32_t rcc_cal_scv_handler(uint32_t x1);
+
+#endif /* RCC_SVC_H */
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
new file mode 100644
index 0000000..fff91c0
--- /dev/null
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <psci.h>
+#include <runtime_svc.h>
+#include <stm32mp1_smc.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <uuid.h>
+#include "bsec_svc.h"
+#include "low_power_svc.h"
+#include "pwr_svc.h"
+#include "rcc_svc.h"
+
+/* STM32 SiP Service UUID */
+DEFINE_SVC_UUID2(stm32_sip_svc_uid,
+ 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
+ 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
+
+/* Setup STM32MP1 Standard Services */
+static int32_t stm32mp1_svc_setup(void)
+{
+ /*
+ * PSCI is the only specification implemented as a Standard Service.
+ * Invoke PSCI setup from here.
+ */
+ return 0;
+}
+
+/*
+ * Top-level Standard Service SMC handler. This handler will in turn dispatch
+ * calls to PSCI SMC handler.
+ */
+static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, void *cookie,
+ void *handle, u_register_t flags)
+{
+ uint32_t ret1 = 0U, ret2 = 0U;
+ bool ret_uid = false, ret2_enabled = false;
+
+ switch (smc_fid) {
+ case STM32_SIP_SVC_CALL_COUNT:
+ ret1 = STM32_COMMON_SIP_NUM_CALLS;
+ break;
+
+ case STM32_SIP_SVC_UID:
+ /* Return UUID to the caller */
+ ret_uid = true;
+ break;
+
+ case STM32_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ ret1 = STM32_SIP_SVC_VERSION_MAJOR;
+ ret2 = STM32_SIP_SVC_VERSION_MINOR;
+ ret2_enabled = true;
+ break;
+
+ case STM32_SMC_BSEC:
+ ret1 = bsec_main(x1, x2, x3, &ret2);
+ ret2_enabled = true;
+ break;
+
+ case STM32_SMC_RCC:
+ ret1 = rcc_scv_handler(x1, x2, x3);
+ break;
+
+ case STM32_SMC_RCC_CAL:
+ ret1 = rcc_cal_scv_handler(x1);
+ break;
+
+ case STM32_SMC_PWR:
+ ret1 = pwr_scv_handler(x1, x2, x3);
+ break;
+
+ case STM32_SMC_SR_MODE:
+ ret1 = sr_mode_scv_handler(x1, x2);
+ break;
+
+ case STM32_SMC_PD_DOMAIN:
+ ret1 = pm_domain_scv_handler(x1, x2);
+ break;
+
+ default:
+ WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
+ ret1 = SMC_UNK;
+ break;
+ }
+
+ if (ret_uid) {
+ SMC_UUID_RET(handle, stm32_sip_svc_uid);
+ }
+
+ if (ret2_enabled) {
+ SMC_RET2(handle, ret1, ret2);
+ }
+
+ SMC_RET1(handle, ret1);
+}
+
+/* Register Standard Service Calls as runtime service */
+DECLARE_RT_SVC(stm32mp1_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ stm32mp1_svc_setup,
+ stm32mp1_svc_smc_handler
+);
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 9fde153..322d389 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -7,8 +7,15 @@
SP_MIN_WITH_SECURE_FIQ := 1
BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
+ drivers/st/etzpc/etzpc.c \
+ drivers/st/rng/stm32_rng.c \
+ drivers/st/rtc/stm32_rtc.c \
+ drivers/st/tamper/stm32_tamp.c \
+ drivers/st/timer/stm32_timer.c \
plat/st/stm32mp1/sp_min/sp_min_setup.c \
+ plat/st/stm32mp1/stm32mp1_low_power.c \
plat/st/stm32mp1/stm32mp1_pm.c \
+ plat/st/stm32mp1/stm32mp1_power_config.c \
plat/st/stm32mp1/stm32mp1_topology.c
# Generic GIC v2
BL32_SOURCES += drivers/arm/gic/common/gic_common.c \
@@ -19,3 +26,10 @@ BL32_SOURCES += drivers/arm/gic/common/gic_common.c \
# Generic PSCI
BL32_SOURCES += plat/common/plat_psci_common.c
+
+# stm32mp1 specific services
+BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
+ plat/st/stm32mp1/services/low_power_svc.c \
+ plat/st/stm32mp1/services/pwr_svc.c \
+ plat/st/stm32mp1/services/rcc_svc.c \
+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 56598c8..e8dc409 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -7,19 +7,32 @@
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
-#include <console.h>
+#include <bsec.h>
#include <context.h>
#include <context_mgmt.h>
#include <debug.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <etzpc.h>
#include <generic_delay_timer.h>
+#include <gicv2.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <platform_sp_min.h>
+#include <stm32_console.h>
+#include <stm32_gpio.h>
+#include <stm32_iwdg.h>
+#include <stm32_rng.h>
+#include <stm32_rtc.h>
+#include <stm32_tamp.h>
+#include <stm32_timer.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_pmic.h>
#include <stm32mp1_clk.h>
-#include <stm32mp1_dt.h>
+#include <stm32mp1_context.h>
+#include <stm32mp1_power_config.h>
#include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
#include <string.h>
#include <tzc400.h>
#include <xlat_tables_v2.h>
@@ -30,22 +43,107 @@
******************************************************************************/
static entry_point_info_t bl33_image_ep_info;
+static struct console_stm32 console;
+
+static struct stm32_tamp_int int_tamp[PLAT_MAX_TAMP_INT] = {
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+};
+
+static struct stm32_tamp_ext ext_tamp[PLAT_MAX_TAMP_EXT] = {
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+ TAMP_UNUSED,
+};
+
+static void tzc_it_handler(void)
+{
+ ERROR("No IT handler in ARM tzc400 driver\n");
+}
+
+static void stm32_sgi1_it_handler(void)
+{
+ uint32_t id;
+
+ gicv2_end_of_interrupt(ARM_IRQ_SEC_SGI_1);
+
+ 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);
+
+
+ isb();
+ dsb();
+
+ /* Flush L1/L2 data caches */
+ write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
+ dcsw_op_all(DC_OP_CISW);
+
+ for ( ; ; ) {
+ wfi();
+ }
+}
+
/*******************************************************************************
* Interrupt handler for FIQ (secure IRQ)
******************************************************************************/
void sp_min_plat_fiq_handler(uint32_t id)
{
- switch (id) {
+ uint32_t value = 0;
+
+ switch (id & INT_ID_MASK) {
+ case ARM_IRQ_SEC_PHY_TIMER:
+ case STM32MP1_IRQ_MCU_SEV:
+ case STM32MP1_IRQ_RCC_WAKEUP:
+ stm32mp1_rcc_it_handler(id);
+ break;
case STM32MP1_IRQ_TZC400:
- ERROR("STM32MP1_IRQ_TZC400 generated\n");
+ tzc400_init(STM32MP1_TZC_BASE);
+ tzc400_it_handler();
panic();
break;
+ case STM32MP1_IRQ_TAMPSERRS:
+ stm32_tamp_it_handler();
+ break;
+ case ARM_IRQ_SEC_SGI_1:
+ stm32_sgi1_it_handler();
+ break;
+ case STM32MP1_IRQ_IWDG1:
+ case STM32MP1_IRQ_IWDG2:
+ stm32_iwdg_it_handler(id);
+ break;
case STM32MP1_IRQ_AXIERRIRQ:
ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
+ tzc400_init(STM32MP1_TZC_BASE);
+ __asm__("mrc p15, 1, %0, c9, c0, 3" : "=r" (value));
+ if (value) {
+ /* we have a pending IT clear it */
+ value = 0;
+ __asm__("mcr p15, 1, %0, c9, c0, 3" :: "r" (value));
+ } else {
+ ERROR("IRQ_AXIERRIRQ handle call w/o any flag set!!\n");
+ }
+
+ /* Check if FIQ has been generated due to TZC400 abort*/
+ if (tzc400_is_pending_interrupt()) {
+ tzc_it_handler();
+ } else {
+ ERROR("IRQ_AXIERRIRQ cause can't be detected");
+ }
+
panic();
break;
default:
- ERROR("SECURE IT handler not define for it : %i", id);
+ ERROR("SECURE IT handler not define for it : %u", id);
break;
}
}
@@ -59,11 +157,54 @@ void sp_min_plat_fiq_handler(uint32_t id)
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
{
entry_point_info_t *next_image_info;
+ uint32_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uint32_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
next_image_info = &bl33_image_ep_info;
+ /*
+ * PC is set to 0 when resetting after STANDBY
+ * The context should be restored, and the image information
+ * should be filled with what what was saved
+ */
if (next_image_info->pc == 0U) {
- return NULL;
+ void *cpu_context;
+ uint32_t magic_nb, saved_pc;
+
+ stm32mp_clk_enable(RTCAPB);
+
+ magic_nb = mmio_read_32(bkpr_core1_magic);
+ saved_pc = mmio_read_32(bkpr_core1_addr);
+
+ stm32mp_clk_disable(RTCAPB);
+
+ if (stm32_restore_context() != 0) {
+ panic();
+ }
+
+ cpu_context = cm_get_context(NON_SECURE);
+
+ next_image_info->spsr = read_ctx_reg(get_regs_ctx(cpu_context),
+ CTX_SPSR);
+
+ /* PC should be retrieved in backup register if OK, else it can
+ * be retrieved from non-secure context
+ */
+ if (magic_nb == BOOT_API_A7_CORE0_MAGIC_NUMBER) {
+ /* BL33 return address should be in DDR */
+ if ((saved_pc < STM32MP_DDR_BASE) ||
+ (saved_pc > (STM32MP_DDR_BASE +
+ (dt_get_ddr_size() - 1U)))) {
+ panic();
+ }
+
+ next_image_info->pc = saved_pc;
+ } else {
+ next_image_info->pc =
+ read_ctx_reg(get_regs_ctx(cpu_context), CTX_LR);
+ }
}
return next_image_info;
@@ -75,6 +216,9 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+#if STM32MP_UART_PROGRAMMER
+ uint32_t boot_itf, boot_instance;
+#endif
struct dt_node_info dt_dev_info;
int result;
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
@@ -105,18 +249,78 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
panic();
}
+ if (bsec_probe() != 0) {
+ panic();
+ }
+
if (stm32mp1_clk_probe() < 0) {
panic();
}
+ /* Initialize uart for console except if it is used by programmer */
result = dt_get_stdout_uart_info(&dt_dev_info);
+#if STM32MP_UART_PROGRAMMER
+ stm32_get_boot_interface(&boot_itf, &boot_instance);
+ if ((result > 0) && dt_dev_info.status &&
+ !((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) &&
+ (get_uart_address(boot_instance) == dt_dev_info.base))) {
+#else
if ((result > 0) && dt_dev_info.status) {
- if (console_init(dt_dev_info.base, 0, STM32MP1_UART_BAUDRATE)
- == 0) {
+#endif
+ if (console_stm32_register(dt_dev_info.base, 0,
+ STM32MP_UART_BAUDRATE, &console) ==
+ 0) {
panic();
}
}
+
+ if (dt_pmic_status() > 0) {
+ initialize_pmic();
+ }
+
+ stm32mp1_init_lp_states();
+}
+
+/*******************************************************************************
+ * Set security setup in sp_min
+ ******************************************************************************/
+void stm32mp1_sp_min_security_setup(void)
+{
+ uint32_t filter_conf = 0;
+ uint32_t active_conf = 0;
+ int ret;
+
+ if (etzpc_init() != 0) {
+ ERROR("ETZPC configuration issue\n");
+ panic();
+ }
+
+ /* Init rtc driver */
+ ret = stm32_rtc_init();
+ if (ret < 0) {
+ WARN("RTC driver init error %i\n", ret);
+ }
+
+ /* Init rng driver */
+ ret = stm32_rng_init();
+ if (ret < 0) {
+ WARN("RNG driver init error %i\n", ret);
+ }
+
+ /* Init tamper */
+ if (stm32_tamp_init() > 0) {
+ stm32_tamp_configure_internal(int_tamp, PLAT_MAX_TAMP_INT);
+ stm32_tamp_configure_external(ext_tamp, PLAT_MAX_TAMP_EXT,
+ filter_conf, active_conf);
+
+ /* Enable timestamp for tamper */
+ stm32_rtc_set_tamper_timestamp();
+ }
+
+ if (stm32_timer_init() == 0) {
+ stm32mp1_cal_init();
+ }
}
/*******************************************************************************
@@ -128,6 +332,16 @@ void sp_min_platform_setup(void)
BL_CODE_END - BL_CODE_BASE,
MT_CODE | MT_SECURE);
+#if SEPARATE_CODE_AND_RODATA
+ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+ BL_RO_DATA_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 */
@@ -136,8 +350,21 @@ void sp_min_platform_setup(void)
generic_delay_timer_init();
stm32mp1_gic_init();
+
+ /* Update security settings */
+ stm32mp1_sp_min_security_setup();
+
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ stm32mp1_driver_init_late();
}
void sp_min_plat_arch_setup(void)
{
}
+
+void sp_min_plat_runtime_setup(void)
+{
+}
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
index 0d7a8bb..a9cc26b 100644
--- a/plat/st/stm32mp1/stm32mp1.ld.S
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -4,8 +4,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef __STM32MP1_LD_S__
-#define __STM32MP1_LD_S__
+#ifndef STM32MP1_LD_S
+#define STM32MP1_LD_S
+
#include <platform_def.h>
#include <xlat_tables_defs.h>
@@ -16,7 +17,7 @@ ENTRY(__BL2_IMAGE_START__)
MEMORY {
HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000
- RAM (rwx) : ORIGIN = STM32MP1_BINARY_BASE, LENGTH = STM32MP1_BINARY_SIZE
+ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE
}
SECTIONS
@@ -31,7 +32,7 @@ SECTIONS
__HEADER_END__ = .;
} >HEADER
- . = STM32MP1_BINARY_BASE;
+ . = STM32MP_BINARY_BASE;
.data . : {
. = ALIGN(PAGE_SIZE);
__DATA_START__ = .;
@@ -42,7 +43,7 @@ SECTIONS
* The strongest and only alignment contraint is MMU 4K page.
* Indeed as images below will be removed, 4K pages will be re-used.
*/
- . = ( STM32MP1_DTB_BASE - STM32MP1_BINARY_BASE );
+ . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE );
__DTB_IMAGE_START__ = .;
*(.dtb_image*)
__DTB_IMAGE_END__ = .;
@@ -52,20 +53,22 @@ SECTIONS
* The strongest and only alignment contraint is MMU 4K page.
* Indeed as images below will be removed, 4K pages will be re-used.
*/
- . = ( STM32MP1_BL2_BASE - STM32MP1_BINARY_BASE );
+ . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE );
__BL2_IMAGE_START__ = .;
*(.bl2_image*)
__BL2_IMAGE_END__ = .;
+#ifndef AARCH32_SP_OPTEE
/*
* bl32 will be settled by bl2.
* The strongest and only alignment constraint is 8 words to simplify
* memraise8 assembly code.
*/
- . = ( STM32MP1_BL32_BASE - STM32MP1_BINARY_BASE );
+ . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE );
__BL32_IMAGE_START__ = .;
*(.bl32_image*)
__BL32_IMAGE_END__ = .;
+#endif
__DATA_END__ = .;
} >RAM
@@ -73,4 +76,4 @@ SECTIONS
__TF_END__ = .;
}
-#endif /*__STM32MP1_LD_S__*/
+#endif /* STM32MP1_LD_S */
diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c
deleted file mode 100644
index 7d84da1..0000000
--- a/plat/st/stm32mp1/stm32mp1_common.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_helpers.h>
-#include <assert.h>
-#include <bl_common.h>
-#include <debug.h>
-#include <gicv2.h>
-#include <mmio.h>
-#include <platform_def.h>
-#include <platform.h>
-#include <stm32mp1_private.h>
-#include <xlat_tables_v2.h>
-
-#define MAP_SRAM MAP_REGION_FLAT(STM32MP1_SRAM_BASE, \
- STM32MP1_SRAM_SIZE, \
- MT_MEMORY | \
- MT_RW | \
- MT_SECURE | \
- MT_EXECUTE_NEVER)
-
-#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
- STM32MP1_DEVICE1_SIZE, \
- MT_DEVICE | \
- MT_RW | \
- MT_SECURE | \
- MT_EXECUTE_NEVER)
-
-#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
- STM32MP1_DEVICE2_SIZE, \
- MT_DEVICE | \
- MT_RW | \
- MT_SECURE | \
- MT_EXECUTE_NEVER)
-
-#define MAP_DDR MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
- STM32MP1_DDR_MAX_SIZE, \
- MT_MEMORY | \
- MT_RW | \
- MT_SECURE | \
- MT_EXECUTE_NEVER)
-
-#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
- STM32MP1_DDR_MAX_SIZE, \
- MT_MEMORY | \
- MT_RW | \
- MT_NS | \
- MT_EXECUTE_NEVER)
-
-#if defined(IMAGE_BL2)
-static const mmap_region_t stm32mp1_mmap[] = {
- MAP_SRAM,
- MAP_DEVICE1,
- MAP_DEVICE2,
- MAP_DDR,
- {0}
-};
-#endif
-#if defined(IMAGE_BL32)
-static const mmap_region_t stm32mp1_mmap[] = {
- MAP_SRAM,
- MAP_DEVICE1,
- MAP_DEVICE2,
- MAP_DDR_NS,
- {0}
-};
-#endif
-
-void configure_mmu(void)
-{
- mmap_add(stm32mp1_mmap);
- init_xlat_tables();
-
- enable_mmu_svc_mon(0);
-}
-
-uintptr_t plat_get_ns_image_entrypoint(void)
-{
- return BL33_BASE;
-}
-
-unsigned int plat_get_syscnt_freq2(void)
-{
- return read_cntfrq_el0();
-}
-
-/* Functions to save and get boot context address given by ROM code */
-static uintptr_t boot_ctx_address;
-
-void stm32mp1_save_boot_ctx_address(uintptr_t address)
-{
- boot_ctx_address = address;
-}
-
-uintptr_t stm32mp1_get_boot_ctx_address(void)
-{
- return boot_ctx_address;
-}
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
index 245fd17..8dc1146 100644
--- a/plat/st/stm32mp1/stm32mp1_context.c
+++ b/plat/st/stm32mp1/stm32mp1_context.c
@@ -4,39 +4,235 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arch_helpers.h>
+#include <boot_api.h>
+#include <context.h>
+#include <context_mgmt.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <errno.h>
#include <mmio.h>
#include <platform_def.h>
+#include <smccc_helpers.h>
+#include <stm32_rtc.h>
#include <stm32mp1_clk.h>
#include <stm32mp1_context.h>
+#include <stm32mp1_ddr_regs.h>
+#include <stm32mp1_shared_resources.h>
+#include <string.h>
+#include <utils.h>
#define TAMP_BOOT_ITF_BACKUP_REG_ID U(20)
#define TAMP_BOOT_ITF_MASK U(0x0000FF00)
#define TAMP_BOOT_ITF_SHIFT 8
+#define TRAINING_AREA_SIZE 64
+
+#ifdef AARCH32_SP_OPTEE
+/* OPTEE_MAILBOX_MAGIC relates to struct backup_data_s as defined */
+#define OPTEE_MAILBOX_MAGIC_V1 0x01
+#define OPTEE_MAILBOX_MAGIC ((OPTEE_MAILBOX_MAGIC_V1 << 16) + \
+ TRAINING_AREA_SIZE)
+#endif
+
+struct backup_data_s {
+#ifdef AARCH32_SP_OPTEE
+ uint32_t magic;
+ uint32_t core0_resume_hint;
+ uint32_t zq0cr0_zdata;
+ uint8_t ddr_training_backup[TRAINING_AREA_SIZE];
+#else
+ smc_ctx_t saved_smc_context[PLATFORM_CORE_COUNT];
+ cpu_context_t saved_cpu_context[PLATFORM_CORE_COUNT];
+ uint32_t zq0cr0_zdata;
+ struct stm32_rtc_calendar rtc;
+ uint8_t ddr_training_backup[TRAINING_AREA_SIZE];
+#endif
+};
+
+#ifdef AARCH32_SP_OPTEE
+uint32_t stm32_pm_get_optee_ep(void)
+{
+ struct backup_data_s *backup_data;
+ uint32_t ep;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ /* Context & Data to be saved at the beginning of Backup SRAM */
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ if (backup_data->magic != OPTEE_MAILBOX_MAGIC) {
+ panic();
+ }
+
+ ep = backup_data->core0_resume_hint;
+
+ stm32mp_clk_disable(BKPSRAM);
+
+ return ep;
+}
+#else /*AARCH32_SP_OPTEE*/
+void stm32_clean_context(void)
+{
+ stm32mp_clk_enable(BKPSRAM);
+
+ zeromem((void *)STM32MP_BACKUP_RAM_BASE, sizeof(struct backup_data_s));
+
+ stm32mp_clk_disable(BKPSRAM);
+}
+
+int stm32_save_context(uint32_t zq0cr0_zdata)
+{
+ void *smc_context;
+ void *cpu_context;
+ struct backup_data_s *backup_data;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ /* Context & Data to be saved at the beginning of Backup SRAM */
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ /* Retrieve smc context struct address */
+ smc_context = smc_get_ctx(NON_SECURE);
+
+ /* Retrieve smc context struct address */
+ cpu_context = cm_get_context(NON_SECURE);
+
+ /* Save context in Backup SRAM */
+ memcpy(&backup_data->saved_smc_context[0], smc_context,
+ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT);
+ memcpy(&backup_data->saved_cpu_context[0], cpu_context,
+ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT);
+
+ backup_data->zq0cr0_zdata = zq0cr0_zdata;
+
+ stm32_rtc_get_calendar(&backup_data->rtc);
+
+ stm32mp_clk_disable(BKPSRAM);
+
+ return 0;
+}
+
+int stm32_restore_context(void)
+{
+ void *smc_context;
+ void *cpu_context;
+ struct backup_data_s *backup_data;
+ struct stm32_rtc_calendar current_calendar;
+ unsigned long long stdby_time_in_ms;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ /* Context & Data to be saved at the beginning of Backup SRAM */
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ /* Retrieve smc context struct address */
+ smc_context = smc_get_ctx(NON_SECURE);
+
+ /* Retrieve smc context struct address */
+ cpu_context = cm_get_context(NON_SECURE);
+
+ /* Restore data from Backup SRAM */
+ memcpy(smc_context, backup_data->saved_smc_context,
+ sizeof(smc_ctx_t) * PLATFORM_CORE_COUNT);
+ memcpy(cpu_context, backup_data->saved_cpu_context,
+ sizeof(cpu_context_t) * PLATFORM_CORE_COUNT);
+
+ /* update STGEN counter with standby mode length */
+ stm32_rtc_get_calendar(&current_calendar);
+ stdby_time_in_ms = stm32_rtc_diff_calendar(&current_calendar,
+ &backup_data->rtc);
+ stm32mp1_stgen_increment(stdby_time_in_ms);
+
+ stm32mp_clk_disable(BKPSRAM);
+
+ return 0;
+}
+#endif /*AARCH32_SP_OPTEE*/
+
+uint32_t stm32_get_zdata_from_context(void)
+{
+ struct backup_data_s *backup_data;
+ uint32_t zdata;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ zdata = (backup_data->zq0cr0_zdata >> DDRPHYC_ZQ0CRN_ZDATA_SHIFT) &
+ DDRPHYC_ZQ0CRN_ZDATA_MASK;
+
+ stm32mp_clk_disable(BKPSRAM);
+
+ return zdata;
+}
+
int stm32_save_boot_interface(uint32_t interface, uint32_t instance)
{
- uint32_t tamp_clk_off = 0;
uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID);
- if (!stm32mp1_clk_is_enabled(RTCAPB)) {
- tamp_clk_off = 1;
- if (stm32mp1_clk_enable(RTCAPB) != 0) {
- return -EINVAL;
- }
- }
+ stm32mp_clk_enable(RTCAPB);
mmio_clrsetbits_32(bkpr_itf_idx,
TAMP_BOOT_ITF_MASK,
((interface << 4) | (instance & 0xFU)) <<
TAMP_BOOT_ITF_SHIFT);
- if (tamp_clk_off != 0U) {
- if (stm32mp1_clk_disable(RTCAPB) != 0) {
- return -EINVAL;
- }
- }
+ stm32mp_clk_disable(RTCAPB);
return 0;
}
+
+int stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
+{
+ uint32_t backup_reg_itf;
+ uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID);
+
+ stm32mp_clk_enable(RTCAPB);
+
+ backup_reg_itf = (mmio_read_32(bkpr_itf_idx) &
+ TAMP_BOOT_ITF_MASK) >> TAMP_BOOT_ITF_SHIFT;
+
+ stm32mp_clk_disable(RTCAPB);
+
+ *interface = backup_reg_itf >> 4;
+ *instance = backup_reg_itf & 0xFU;
+
+ return 0;
+}
+
+/*
+ * When returning from STANDBY, the 64 first bytes of DDR will be overwritten
+ * during DDR DQS training. This area must then be saved before going to
+ * standby, and will be restored after
+ */
+void stm32_save_ddr_training_area(void)
+{
+ struct backup_data_s *backup_data;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ memcpy(&backup_data->ddr_training_backup,
+ (const uint32_t *)STM32MP_DDR_BASE,
+ TRAINING_AREA_SIZE);
+ dsb();
+
+ stm32mp_clk_disable(BKPSRAM);
+}
+
+void stm32_restore_ddr_training_area(void)
+{
+ struct backup_data_s *backup_data;
+
+ stm32mp_clk_enable(BKPSRAM);
+
+ backup_data = (struct backup_data_s *)STM32MP_BACKUP_RAM_BASE;
+
+ memcpy((uint32_t *)STM32MP_DDR_BASE,
+ &backup_data->ddr_training_backup,
+ TRAINING_AREA_SIZE);
+ dsb();
+
+ stm32mp_clk_disable(BKPSRAM);
+}
diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
new file mode 100644
index 0000000..716f7d8
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bsec.h>
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#include <utils_def.h>
+
+#define DBGMCU_IDC 0x0U
+#define IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_APB4FZ1 0x2CU
+#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
+
+#define TAMP_DBG_BACKUP_REG_ID 20
+#define TAMP_DBG_DEBUG BIT(16)
+
+static uintptr_t get_rcc_base(void)
+{
+ /* This is called before stm32mp_rcc_base() is available */
+ return RCC_BASE;
+}
+
+static int stm32mp1_dbgmcu_init(void)
+{
+ uint32_t dbg_conf;
+ uintptr_t rcc_base = get_rcc_base();
+
+ dbg_conf = bsec_read_debug_conf();
+
+ if ((dbg_conf & BSEC_DBGSWGEN) == 0U) {
+ uint32_t result = bsec_write_debug_conf(dbg_conf |
+ BSEC_DBGSWGEN);
+
+ if (result != BSEC_OK) {
+ ERROR("Error enabling DBGSWGEN\n");
+ return (int)result;
+ }
+ }
+
+ if ((mmio_read_32(rcc_base + RCC_DBGCFGR) & RCC_DBGCFGR_DBGCKEN) ==
+ 0U) {
+ mmio_setbits_32(rcc_base + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+ }
+
+ return 0;
+}
+
+#if STM32MP1_DEBUG_ENABLE
+int stm32mp1_dbgmcu_boot_debug_info(void)
+{
+ uint32_t backup_reg_dbg;
+
+ stm32mp_clk_enable(RTCAPB);
+
+ backup_reg_dbg = (mmio_read_32(tamp_bkpr(TAMP_DBG_BACKUP_REG_ID))
+ & TAMP_DBG_DEBUG);
+
+ stm32mp_clk_disable(RTCAPB);
+
+ if (backup_reg_dbg != 0U) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int stm32mp1_dbgmcu_clear_boot_info(void)
+{
+ stm32mp_clk_enable(RTCAPB);
+
+ mmio_clrbits_32(tamp_bkpr(TAMP_DBG_BACKUP_REG_ID),
+ TAMP_DBG_DEBUG);
+
+ stm32mp_clk_disable(RTCAPB);
+
+ return 0;
+}
+
+uint32_t stm32mp1_dbgmcu_is_debug_on(void)
+{
+ uint32_t dbg_conf;
+
+ dbg_conf = bsec_read_debug_conf();
+
+ return (dbg_conf & (BSEC_SPIDEN | BSEC_SPINDEN));
+}
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+void stm32mp1_dbgmcu_hexdump8(uint8_t *buf, uint32_t len)
+{
+ uint32_t i;
+
+ VERBOSE(" ");
+ for (i = 0; i < len; i++) {
+ printf("%02x ", buf[i]);
+ if (((i + 1) % 16) == 0) {
+ if ((i + 1) < len) {
+ printf("\n");
+ VERBOSE(" ");
+ }
+ } else if (((i + 1) % 8) == 0) {
+ printf(" ");
+ }
+ }
+ printf("\n");
+}
+#endif
+#endif
+
+uint32_t stm32mp1_dbgmcu_get_chip_version(void)
+{
+ if (stm32mp1_dbgmcu_init() == 0) {
+ return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) >> 16);
+ }
+
+ return 0;
+}
+
+uint32_t stm32mp1_dbgmcu_get_chip_dev_id(void)
+{
+ if (stm32mp1_dbgmcu_init() == 0) {
+ return (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+ IDC_DEV_ID_MASK);
+ }
+
+ return 0;
+}
+
+int stm32mp1_dbgmcu_freeze_iwdg2(void)
+{
+ if (stm32mp1_dbgmcu_init() == 0) {
+ uint32_t dbg_conf = bsec_read_debug_conf();
+
+ if (((dbg_conf & BSEC_SPIDEN) != 0U) ||
+ ((dbg_conf & BSEC_SPINDEN) != 0U)) {
+ mmio_setbits_32(DBGMCU_BASE + DBGMCU_APB4FZ1,
+ DBGMCU_APB4FZ1_IWDG2);
+ }
+
+ return 0;
+ }
+
+ return -EPERM;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index bb3fecf..a6b1a7b 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -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
*/
@@ -7,84 +7,206 @@
#ifndef STM32MP1_DEF_H
#define STM32MP1_DEF_H
+#ifndef __ASSEMBLY__
+#include <bsec.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <etzpc.h>
+#include <stm32mp1_clkfunc.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_context.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_ddr.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_ddr_regs.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_ram.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#include <stm32mp1_usb_desc.h>
+#include <stm32mp1xx_hal_uart.h>
+#endif
#include <tbbr_img_def.h>
#include <utils_def.h>
#include <xlat_tables_defs.h>
+#define AUTHENTICATE_BL33
+
+/*******************************************************************************
+ * CHIP ID
+ ******************************************************************************/
+#define STM32MP157C_PART_NB U(0x05000000)
+#define STM32MP157A_PART_NB U(0x05000001)
+#define STM32MP153C_PART_NB U(0x05000024)
+#define STM32MP153A_PART_NB U(0x05000025)
+#define STM32MP151C_PART_NB U(0x0500002E)
+#define STM32MP151A_PART_NB U(0x0500002F)
+
+#define STM32MP1_REV_A U(0x1000)
+#define STM32MP1_REV_B U(0x2000)
+
+/*******************************************************************************
+ * PACKAGE ID
+ ******************************************************************************/
+#define PKG_AA_LBGA448 U(4)
+#define PKG_AB_LBGA354 U(3)
+#define PKG_AC_TFBGA361 U(2)
+#define PKG_AD_TFBGA257 U(1)
+
+/*******************************************************************************
+ * BOOT PARAM
+ ******************************************************************************/
+#define BOOT_PARAM_ADDR U(0x2FFC0078)
+
/*******************************************************************************
* STM32MP1 memory map related constants
******************************************************************************/
+#define STM32MP_ROM_BASE U(0x00000000)
+#define STM32MP_ROM_SIZE U(0x00020000)
+
+#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
+#define STM32MP_SYSRAM_SIZE U(0x00040000)
+
+/* 384 Ko (128 x 3) Non secure from MCU available for TF*/
+#define STM32MP_SRAM_MCU_BASE U(0x30000000)
+#define STM32MP_SRAM_MCU_SIZE U(0x00060000)
-#define STM32MP1_SRAM_BASE U(0x2FFC0000)
-#define STM32MP1_SRAM_SIZE U(0x00040000)
+#define STM32MP_RETRAM_BASE U(0x38000000)
+#define STM32MP_RETRAM_SIZE U(0x00010000)
+
+#define STM32MP_BACKUP_RAM_BASE U(0x54000000)
+#define STM32MP_BACKUP_RAM_SIZE U(0x00001000)
/* DDR configuration */
-#define STM32MP1_DDR_BASE U(0xC0000000)
-#define STM32MP1_DDR_SIZE_DFLT U(0x20000000) /* 512 MB */
-#define STM32MP1_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
-#define STM32MP1_DDR_SPEED_DFLT 528
+#define STM32MP_DDR_BASE U(0xC0000000)
+#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */
+#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */
+#else
+#define STM32MP_DDR_S_SIZE U(0) /* DDR is non secure */
+#endif
/* DDR power initializations */
#ifndef __ASSEMBLY__
enum ddr_type {
STM32MP_DDR3,
STM32MP_LPDDR2,
+ STM32MP_LPDDR3,
};
#endif
/* Section used inside TF binaries */
-#define STM32MP1_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */
+#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */
/* 256 Octets reserved for header */
-#define STM32MP1_HEADER_SIZE U(0x00000100)
+#define STM32MP_HEADER_SIZE U(0x00000100)
-#define STM32MP1_BINARY_BASE (STM32MP1_SRAM_BASE + \
- STM32MP1_PARAM_LOAD_SIZE + \
- STM32MP1_HEADER_SIZE)
+#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE)
-#define STM32MP1_BINARY_SIZE (STM32MP1_SRAM_SIZE - \
- (STM32MP1_PARAM_LOAD_SIZE + \
- STM32MP1_HEADER_SIZE))
+#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \
+ (STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE))
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_BL32_SIZE U(0)
+
+#define STM32MP_OPTEE_BASE STM32MP_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \
+ STM32MP_OPTEE_BASE)
+#else
#if STACK_PROTECTOR_ENABLED
-#define STM32MP1_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */
+#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */
#else
-#define STM32MP1_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */
+#define STM32MP_BL32_SIZE U(0x00010000) /* 64 Ko for BL32 */
+#endif
#endif
-#define STM32MP1_BL32_BASE (STM32MP1_SRAM_BASE + \
- STM32MP1_SRAM_SIZE - \
- STM32MP1_BL32_SIZE)
+#define STM32MP_BL32_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_BL32_SIZE)
+#ifdef AARCH32_SP_OPTEE
#if STACK_PROTECTOR_ENABLED
-#define STM32MP1_BL2_SIZE U(0x00015000) /* 84 Ko for BL2 */
+#define STM32MP_BL2_SIZE U(0x00019000) /* 100 Ko for BL2 */
#else
-#define STM32MP1_BL2_SIZE U(0x00013000) /* 76 Ko for BL2 */
+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 Ko for BL2 */
+#endif
+#else
+#if STACK_PROTECTOR_ENABLED
+#define STM32MP_BL2_SIZE U(0x00018000) /* 96 Ko for BL2 */
+#else
+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 Ko for BL2 */
+#endif
#endif
-#define STM32MP1_BL2_BASE (STM32MP1_BL32_BASE - \
- STM32MP1_BL2_SIZE)
+#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \
+ STM32MP_BL2_SIZE)
-/* BL2 and BL32/sp_min require 5 tables */
-#define MAX_XLAT_TABLES 5
+/* BL2 and BL32/sp_min require 7 tables */
+#define MAX_XLAT_TABLES U(7) /* 28 Ko for mapping */
/*
* MAX_MMAP_REGIONS is usually:
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
*/
#if defined(IMAGE_BL2)
+ #if (defined STM32MP_USB)
+ #define MAX_MMAP_REGIONS 12
+ #else
#define MAX_MMAP_REGIONS 11
+ #endif
#endif
#if defined(IMAGE_BL32)
- #define MAX_MMAP_REGIONS 6
+ #define MAX_MMAP_REGIONS 6
#endif
+#define XLAT_TABLE_OCTETSIZE U(0x1000)
+#define PLAT_XLAT_SIZE (MAX_XLAT_TABLES * \
+ XLAT_TABLE_OCTETSIZE)
+
+#define PLAT_XLAT_BASE (STM32MP_BL2_BASE - \
+ PLAT_XLAT_SIZE)
+
+/*
+ * Uncomment this to get the xlat tables back in each binary image
+ * (xlat_table sections in .lds)
+ *
+ * #undef PLAT_XLAT_BASE
+ */
+
/* DTB initialization value */
-#define STM32MP1_DTB_SIZE U(0x00004000) /* 16Ko for DTB */
+#define STM32MP_DTB_SIZE U(0x00005000) /* 20Ko for DTB */
+
+#define STM32MP_DTB_BASE (PLAT_XLAT_BASE - \
+ STM32MP_DTB_SIZE)
-#define STM32MP1_DTB_BASE (STM32MP1_BL2_BASE - \
- STM32MP1_DTB_SIZE)
+#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
-#define STM32MP1_BL33_BASE (STM32MP1_DDR_BASE + U(0x100000))
+/* Define Temporary Stack size use during low power mode */
+#define STM32MP_INT_STACK_SIZE 0x400
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for MTD devices
+ ******************************************************************************/
+#define STM32MP_NOR_BL33_OFFSET U(0x00080000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NOR_TEEH_OFFSET U(0x00280000)
+#define STM32MP_NOR_TEED_OFFSET U(0x002C0000)
+#define STM32MP_NOR_TEEX_OFFSET U(0x00300000)
+#endif
+
+#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)
+#endif
/*******************************************************************************
* STM32MP1 device/io map related constants (used for MMU)
@@ -106,6 +228,60 @@ enum ddr_type {
#define PWR_BASE U(0x50001000)
/*******************************************************************************
+ * STM32MP1 EXTI
+ ******************************************************************************/
+#define EXTI_BASE U(0x5000D000)
+#define EXTI_TZENR1 U(0x14)
+#define EXTI_RPR3 U(0x4C)
+#define EXTI_FPR3 U(0x50)
+#define EXTI_C1IMR1 U(0x80)
+#define EXTI_C2IMR1 U(0xC0)
+#define EXTI_C2IMR2 U(0xD0)
+#define EXTI_C2IMR3 U(0xE0)
+#define EXTI_TZENR1_TZEN18 BIT(18)
+#define EXTI_IMR1_IM18 BIT(18)
+#define EXTI_RPR3_RPIF65 BIT(1)
+#define EXTI_FPR3_FPIF65 BIT(1)
+
+/*******************************************************************************
+ * STM32MP1 RTC
+ ******************************************************************************/
+#define RTC_BASE U(0x5C004000)
+
+/*******************************************************************************
+ * STM32MP1 GPIO
+ ******************************************************************************/
+#define GPIOA_BASE U(0x50002000)
+#define GPIOB_BASE U(0x50003000)
+#define GPIOC_BASE U(0x50004000)
+#define GPIOD_BASE U(0x50005000)
+#define GPIOE_BASE U(0x50006000)
+#define GPIOF_BASE U(0x50007000)
+#define GPIOG_BASE U(0x50008000)
+#define GPIOH_BASE U(0x50009000)
+#define GPIOI_BASE U(0x5000A000)
+#define GPIOJ_BASE U(0x5000B000)
+#define GPIOK_BASE U(0x5000C000)
+#define GPIOZ_BASE U(0x54004000)
+#define GPIO_BANK_OFFSET U(0x1000)
+
+/* Bank IDs used in GPIO driver API */
+#define GPIO_BANK_A U(0)
+#define GPIO_BANK_B U(1)
+#define GPIO_BANK_C U(2)
+#define GPIO_BANK_D U(3)
+#define GPIO_BANK_E U(4)
+#define GPIO_BANK_F U(5)
+#define GPIO_BANK_G U(6)
+#define GPIO_BANK_H U(7)
+#define GPIO_BANK_I U(8)
+#define GPIO_BANK_J U(9)
+#define GPIO_BANK_K U(10)
+#define GPIO_BANK_Z U(25)
+
+#define STM32MP_GPIOZ_PIN_MAX_COUNT 8
+
+/*******************************************************************************
* STM32MP1 UART
******************************************************************************/
#define USART1_BASE U(0x5C000000)
@@ -116,16 +292,31 @@ enum ddr_type {
#define USART6_BASE U(0x44003000)
#define UART7_BASE U(0x40018000)
#define UART8_BASE U(0x40019000)
-#define STM32MP1_DEBUG_USART_BASE UART4_BASE
-#define STM32MP1_UART_BAUDRATE 115200
+#define STM32MP_UART_BAUDRATE U(115200)
+
+/* For UART crash console */
+#define STM32MP_DEBUG_USART_BASE UART4_BASE
+/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */
+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN
+#define DEBUG_UART_TX_GPIO_PORT 11
+#define DEBUG_UART_TX_GPIO_ALTERNATE 6
+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR
+#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI
+#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR
+#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN
/*******************************************************************************
- * STM32MP1 GIC-400
+ * STM32MP1 TZPC
******************************************************************************/
-#define STM32MP1_GICD_BASE U(0xA0021000)
-#define STM32MP1_GICC_BASE U(0xA0022000)
-#define STM32MP1_GICH_BASE U(0xA0024000)
-#define STM32MP1_GICV_BASE U(0xA0026000)
+#define STM32MP1_ETZPC_BASE U(0x5C007000)
+#define STM32MP1_ETZPC_SIZE U(0x000003FF)
+
+#define STM32MP1_ETZPC_TZMA_ROM_ID U(0)
+/*SYSRAM internal RAM*/
+#define STM32MP1_ETZPC_TZMA_RAM_ID U(1)
/*******************************************************************************
* STM32MP1 TZC (TZ400)
@@ -133,6 +324,7 @@ enum ddr_type {
#define STM32MP1_TZC_BASE U(0x5C006000)
#define STM32MP1_TZC_A7_ID U(0)
+#define STM32MP1_TZC_M4_ID U(1)
#define STM32MP1_TZC_LCD_ID U(3)
#define STM32MP1_TZC_GPU_ID U(4)
#define STM32MP1_TZC_MDMA_ID U(5)
@@ -143,28 +335,117 @@ enum ddr_type {
#define STM32MP1_TZC_ETH_ID U(10)
#define STM32MP1_TZC_DAP_ID U(15)
-#define STM32MP1_MEMORY_NS 0
-#define STM32MP1_MEMORY_SECURE 1
-
-#define STM32MP1_FILTER_BIT_ALL 3
+#define STM32MP1_FILTER_BIT_ALL U(3)
/*******************************************************************************
* STM32MP1 SDMMC
******************************************************************************/
-#define STM32MP1_SDMMC1_BASE U(0x58005000)
-#define STM32MP1_SDMMC2_BASE U(0x58007000)
-#define STM32MP1_SDMMC3_BASE U(0x48004000)
+#define STM32MP_SDMMC1_BASE U(0x58005000)
+#define STM32MP_SDMMC2_BASE U(0x58007000)
+#define STM32MP_SDMMC3_BASE U(0x48004000)
-#define STM32MP1_SD_INIT_FREQ 400000 /*400 KHz*/
-#define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/
-#define STM32MP1_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/
-#define STM32MP1_EMMC_INIT_FREQ STM32MP1_SD_INIT_FREQ
-#define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/
-#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/
+#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/
+#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/
+#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/
+#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/
+#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/
+
+/*******************************************************************************
+ * STM32MP1 QSPI
+ ******************************************************************************/
+#define STM32MP1_QSPI1_BASE U(0x58003000)
+
+/*******************************************************************************
+ * STM32MP1 BSEC / OTP
+ ******************************************************************************/
+#define STM32MP1_BSEC_BASE U(0x5C005000)
+#define STM32MP1_OTP_MAX_ID 0x5FU
+#define STM32MP1_UPPER_OTP_START 0x20U
+
+#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U)
+
+/* OTP offsets */
+#define DATA0_OTP U(0)
+#define PART_NUMBER_OTP U(1)
+#define MONOTONIC_OTP U(4)
+#define NAND_OTP U(9)
+#define UID0_OTP U(13)
+#define UID1_OTP U(14)
+#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 */
+#define DATA0_OTP_SECURED BIT(6)
+
+/* PART NUMBER */
+#define PART_SHIFT 0
+#define PART_MASK GENMASK_32(7, 0)
+
+/* PACKAGE */
+#define PKG_SHIFT 27
+#define PKG_MASK GENMASK_32(29, 27)
+
+/* IWDG OTP */
+#define IWDG_HW_POS 3
+#define IWDG_FZ_STOP_POS 5
+#define IWDG_FZ_STANDBY_POS 7
+
+/* NAND OTP */
+/* NAND parameter storage flag */
+#define NAND_PARAM_STORED_IN_OTP U(0x80000000)
+
+/* NAND page size in bytes */
+#define NAND_PAGE_SIZE_OFFSET 29
+#define NAND_PAGE_SIZE_MASK U(0x60000000)
+#define NAND_PAGE_SIZE_2K 0
+#define NAND_PAGE_SIZE_4K 1
+#define NAND_PAGE_SIZE_8K 2
+
+/* NAND block size in pages */
+#define NAND_BLOCK_SIZE_OFFSET 27
+#define NAND_BLOCK_SIZE_MASK U(0x18000000)
+#define NAND_BLOCK_SIZE_64_PAGES 0
+#define NAND_BLOCK_SIZE_128_PAGES 1
+#define NAND_BLOCK_SIZE_256_PAGES 2
+
+/* NAND number of block (in unit of 256 blocs) */
+#define NAND_BLOCK_NB_OFFSET 19
+#define NAND_BLOCK_NB_MASK U(0x07F80000)
+#define NAND_BLOCK_NB_UNIT U(256)
+
+/* NAND bus width in bits */
+#define NAND_WIDTH_OFFSET 18
+#define NAND_WIDTH_MASK 0x00040000
+
+/* NAND number of ECC bits per 512 bytes */
+#define NAND_ECC_BIT_NB_OFFSET 16
+#define NAND_ECC_BIT_NB_MASK U(0x00030000)
+#define NAND_ECC_BIT_NB_UNSET 0
+#define NAND_ECC_BIT_NB_1_BITS 1
+#define NAND_ECC_BIT_NB_4_BITS 2
+#define NAND_ECC_BIT_NB_8_BITS 3
+
+#define MAX_MONOTONIC_VALUE 32
+
+/*******************************************************************************
+ * STM32MP1 FMC
+ ******************************************************************************/
+#define STM32MP_FMC_BASE U(0x58002000)
+
+/*******************************************************************************
+ * STM32MP1 HASH
+ ******************************************************************************/
+#define HASH1_BASE U(0x54002000)
+#define HASH_BASE HASH1_BASE
/*******************************************************************************
* STM32MP1 TAMP
******************************************************************************/
+#define PLAT_MAX_TAMP_INT U(5)
+#define PLAT_MAX_TAMP_EXT U(3)
#define TAMP_BASE U(0x5C00A000)
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
@@ -174,6 +455,10 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
return TAMP_BKP_REGISTER_BASE + (idx << 2);
}
#endif
+/*******************************************************************************
+ * STM32MP1 USB
+ ******************************************************************************/
+#define USB_OTG_BASE U(0x49000000)
/*******************************************************************************
* STM32MP1 DDRCTRL
@@ -186,8 +471,60 @@ static inline uint32_t tamp_bkpr(uint32_t idx)
#define DDRPHYC_BASE U(0x5A004000)
/*******************************************************************************
- * STM32MP1 I2C4
+ * STM32MP1 IWDG
+ ******************************************************************************/
+#define IWDG_MAX_INSTANCE U(2)
+#define IWDG1_INST U(0)
+#define IWDG2_INST U(1)
+
+#define IWDG1_BASE U(0x5C003000)
+#define IWDG2_BASE U(0x5A002000)
+
+/*******************************************************************************
+ * STM32MP1 I2C
******************************************************************************/
#define I2C4_BASE U(0x5C002000)
+#define I2C6_BASE U(0x5C009000)
+
+/*******************************************************************************
+ * STM32MP1 DBGMCU
+ ******************************************************************************/
+#define DBGMCU_BASE U(0x50081000)
+
+/*******************************************************************************
+ * STM32MP1 SPI
+ ******************************************************************************/
+#define SPI6_BASE U(0x5C001000)
+
+/*******************************************************************************
+ * STM32MP1 RNG
+ ******************************************************************************/
+#define RNG1_BASE U(0x54003000)
+
+/*******************************************************************************
+ * STM32MP1 CRYP
+ ******************************************************************************/
+#define CRYP1_BASE U(0x54001000)
+
+/*******************************************************************************
+ * STM32MP1 TIMERS
+ ******************************************************************************/
+#define TIM12_BASE U(0x40006000)
+#define TIM15_BASE U(0x44006000)
+#define TIM_MAX_INSTANCE U(2)
+
+/*******************************************************************************
+ * DEBUG
+ ******************************************************************************/
+/*#define ICACHE_OFF*/
+/*#define DCACHE_OFF*/
+/*#define MMU_OFF*/
+
+/*******************************************************************************
+ * Device Tree defines
+ ******************************************************************************/
+#define DT_PWR_COMPAT "st,stm32mp1-pwr"
+#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
+#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg"
#endif /* STM32MP1_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c
deleted file mode 100644
index bde968a..0000000
--- a/plat/st/stm32mp1/stm32mp1_dt.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <libfdt.h>
-#include <platform_def.h>
-#include <stm32_gpio.h>
-#include <stm32mp1_clk.h>
-#include <stm32mp1_clkfunc.h>
-#include <stm32mp1_ddr.h>
-#include <stm32mp1_dt.h>
-#include <stm32mp1_ram.h>
-
-#define DT_GPIO_BANK_SHIFT 12
-#define DT_GPIO_BANK_MASK 0x1F000U
-#define DT_GPIO_PIN_SHIFT 8
-#define DT_GPIO_PIN_MASK 0xF00U
-#define DT_GPIO_MODE_MASK 0xFFU
-
-static int fdt_checked;
-
-static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE;
-
-/*******************************************************************************
- * This function gets the pin settings from DT information.
- * When analyze and parsing is done, set the GPIO registers.
- * Return 0 on success, else return a negative FDT_ERR_xxx error code.
- ******************************************************************************/
-static int dt_set_gpio_config(int node)
-{
- const fdt32_t *cuint, *slewrate;
- int len, pinctrl_node, pinctrl_subnode;
- uint32_t i;
- uint32_t speed = GPIO_SPEED_LOW;
- uint32_t pull = GPIO_NO_PULL;
-
- cuint = fdt_getprop(fdt, node, "pinmux", &len);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node));
- if (pinctrl_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- slewrate = fdt_getprop(fdt, node, "slew-rate", NULL);
- if (slewrate != NULL) {
- speed = fdt32_to_cpu(*slewrate);
- }
-
- if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) {
- pull = GPIO_PULL_UP;
- } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) {
- pull = GPIO_PULL_DOWN;
- } else {
- VERBOSE("No bias configured in node %d\n", node);
- }
-
- for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
- uint32_t pincfg;
- uint32_t bank;
- uint32_t pin;
- uint32_t mode;
- uint32_t alternate = GPIO_ALTERNATE_0;
-
- pincfg = fdt32_to_cpu(*cuint);
- cuint++;
-
- bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT;
-
- pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT;
-
- mode = pincfg & DT_GPIO_MODE_MASK;
-
- switch (mode) {
- case 0:
- mode = GPIO_MODE_INPUT;
- break;
- case 1 ... 16:
- alternate = mode - 1U;
- mode = GPIO_MODE_ALTERNATE;
- break;
- case 17:
- mode = GPIO_MODE_ANALOG;
- break;
- default:
- mode = GPIO_MODE_OUTPUT;
- break;
- }
-
- if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) {
- mode |= GPIO_OPEN_DRAIN;
- }
-
- fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
- uint32_t bank_offset;
- const fdt32_t *cuint2;
-
- if (fdt_getprop(fdt, pinctrl_subnode,
- "gpio-controller", NULL) == NULL) {
- continue;
- }
-
- cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
- if (cuint2 == NULL) {
- continue;
- }
-
- if (bank == GPIO_BANK_Z) {
- bank_offset = 0;
- } else {
- bank_offset = bank * STM32_GPIO_BANK_OFFSET;
- }
-
- if (fdt32_to_cpu(*cuint2) == bank_offset) {
- int clk_id = fdt_get_clock_id(pinctrl_subnode);
-
- if (clk_id < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- if (stm32mp1_clk_enable((unsigned long)clk_id) <
- 0) {
- return -FDT_ERR_BADVALUE;
- }
-
- break;
- }
- }
-
- set_gpio(bank, pin, mode, speed, pull, alternate);
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function checks device tree file with its header.
- * Returns 0 if success, and a negative value else.
- ******************************************************************************/
-int dt_open_and_check(void)
-{
- int ret = fdt_check_header(fdt);
-
- if (ret == 0) {
- fdt_checked = 1;
- }
-
- return ret;
-}
-
-/*******************************************************************************
- * This function gets the address of the DT.
- * If DT is OK, fdt_addr is filled with DT address.
- * Returns 1 if success, 0 otherwise.
- ******************************************************************************/
-int fdt_get_address(void **fdt_addr)
-{
- if (fdt_checked == 1) {
- *fdt_addr = fdt;
- }
-
- return fdt_checked;
-}
-
-/*******************************************************************************
- * This function check the presence of a node (generic use of fdt library).
- * Returns true if present, false else.
- ******************************************************************************/
-bool fdt_check_node(int node)
-{
- int len;
- const char *cchar;
-
- cchar = fdt_get_name(fdt, node, &len);
-
- return (cchar != NULL) && (len >= 0);
-}
-
-/*******************************************************************************
- * This function check the status of a node (generic use of fdt library).
- * Returns true if "okay" or missing, false else.
- ******************************************************************************/
-bool fdt_check_status(int node)
-{
- int len;
- const char *cchar;
-
- cchar = fdt_getprop(fdt, node, "status", &len);
- if (cchar == NULL) {
- return true;
- }
-
- return strncmp(cchar, "okay", (size_t)len) == 0;
-}
-
-/*******************************************************************************
- * This function check the secure-status of a node (generic use of fdt library).
- * Returns true if "okay" or missing, false else.
- ******************************************************************************/
-bool fdt_check_secure_status(int node)
-{
- int len;
- const char *cchar;
-
- cchar = fdt_getprop(fdt, node, "secure-status", &len);
- if (cchar == NULL) {
- return true;
- }
-
- return strncmp(cchar, "okay", (size_t)len) == 0;
-}
-
-/*******************************************************************************
- * This function reads a value of a node property (generic use of fdt
- * library).
- * Returns value if success, and a default value if property not found.
- * Default value is passed as parameter.
- ******************************************************************************/
-uint32_t fdt_read_uint32_default(int node, const char *prop_name,
- uint32_t dflt_value)
-{
- const fdt32_t *cuint;
- int lenp;
-
- cuint = fdt_getprop(fdt, node, prop_name, &lenp);
- if (cuint == NULL) {
- return dflt_value;
- }
-
- return fdt32_to_cpu(*cuint);
-}
-
-/*******************************************************************************
- * This function reads a series of parameters in a node property
- * (generic use of fdt library).
- * It reads the values inside the device tree, from property name and node.
- * The number of parameters is also indicated as entry parameter.
- * Returns 0 if success, and a negative value else.
- * If success, values are stored at the third parameter address.
- ******************************************************************************/
-int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
- uint32_t count)
-{
- const fdt32_t *cuint;
- int len;
- uint32_t i;
-
- cuint = fdt_getprop(fdt, node, prop_name, &len);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- if ((uint32_t)len != (count * sizeof(uint32_t))) {
- return -FDT_ERR_BADLAYOUT;
- }
-
- for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
- *array = fdt32_to_cpu(*cuint);
- array++;
- cuint++;
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function gets the pin settings from DT information.
- * When analyze and parsing is done, set the GPIO registers.
- * Returns 0 if success, and a negative value else.
- ******************************************************************************/
-int dt_set_pinctrl_config(int node)
-{
- const fdt32_t *cuint;
- int lenp = 0;
- uint32_t i;
-
- if (!fdt_check_status(node)) {
- return -FDT_ERR_NOTFOUND;
- }
-
- cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp);
- if (cuint == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- for (i = 0; i < ((uint32_t)lenp / 4U); i++) {
- int phandle_node, phandle_subnode;
-
- phandle_node =
- fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
- if (phandle_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) {
- int ret = dt_set_gpio_config(phandle_subnode);
-
- if (ret < 0) {
- return ret;
- }
- }
-
- cuint++;
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * This function gets the stdout pin configuration information from the DT.
- * And then calls the sub-function to treat it and set GPIO registers.
- * Returns 0 if success, and a negative value else.
- ******************************************************************************/
-int dt_set_stdout_pinctrl(void)
-{
- int node;
-
- node = dt_get_stdout_node_offset();
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- return dt_set_pinctrl_config(node);
-}
-
-/*******************************************************************************
- * This function fills the generic information from a given node.
- ******************************************************************************/
-void dt_fill_device_info(struct dt_node_info *info, int node)
-{
- const fdt32_t *cuint;
-
- cuint = fdt_getprop(fdt, node, "reg", NULL);
- if (cuint != NULL) {
- info->base = fdt32_to_cpu(*cuint);
- } else {
- info->base = 0;
- }
-
- cuint = fdt_getprop(fdt, node, "clocks", NULL);
- if (cuint != NULL) {
- cuint++;
- info->clock = (int)fdt32_to_cpu(*cuint);
- } else {
- info->clock = -1;
- }
-
- cuint = fdt_getprop(fdt, node, "resets", NULL);
- if (cuint != NULL) {
- cuint++;
- info->reset = (int)fdt32_to_cpu(*cuint);
- } else {
- info->reset = -1;
- }
-
- info->status = fdt_check_status(node);
- info->sec_status = fdt_check_secure_status(node);
-}
-
-/*******************************************************************************
- * This function retrieve the generic information from DT.
- * Returns node if success, and a negative value else.
- ******************************************************************************/
-int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
-{
- int node;
-
- node = fdt_node_offset_by_compatible(fdt, offset, compat);
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- dt_fill_device_info(info, node);
-
- return node;
-}
-
-/*******************************************************************************
- * This function gets the UART instance info of stdout from the DT.
- * Returns node if success, and a negative value else.
- ******************************************************************************/
-int dt_get_stdout_uart_info(struct dt_node_info *info)
-{
- int node;
-
- node = dt_get_stdout_node_offset();
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- dt_fill_device_info(info, node);
-
- return node;
-}
-
-/*******************************************************************************
- * This function gets the stdout path node.
- * It reads the value indicated inside the device tree.
- * Returns node if success, and a negative value else.
- ******************************************************************************/
-int dt_get_stdout_node_offset(void)
-{
- int node;
- const char *cchar;
-
- node = fdt_path_offset(fdt, "/chosen");
- if (node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
- if (cchar == NULL) {
- return -FDT_ERR_NOTFOUND;
- }
-
- node = -FDT_ERR_NOTFOUND;
- if (strchr(cchar, (int)':') != NULL) {
- const char *name;
- char *str = (char *)cchar;
- int len = 0;
-
- while (strncmp(":", str, 1)) {
- len++;
- str++;
- }
-
- name = fdt_get_alias_namelen(fdt, cchar, len);
-
- if (name != NULL) {
- node = fdt_path_offset(fdt, name);
- }
- } else {
- node = fdt_path_offset(fdt, cchar);
- }
-
- return node;
-}
-
-/*******************************************************************************
- * This function gets DDR size information from the DT.
- * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else.
- ******************************************************************************/
-uint32_t dt_get_ddr_size(void)
-{
- int node;
-
- node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
- if (node < 0) {
- INFO("%s: Cannot read DDR node in DT\n", __func__);
- return STM32MP1_DDR_SIZE_DFLT;
- }
-
- return fdt_read_uint32_default(node, "st,mem-size",
- STM32MP1_DDR_SIZE_DFLT);
-}
-
-/*******************************************************************************
- * This function retrieves board model from DT
- * Returns string taken from model node, NULL otherwise
- ******************************************************************************/
-const char *dt_get_board_model(void)
-{
- int node = fdt_path_offset(fdt, "/");
-
- if (node < 0) {
- return NULL;
- }
-
- return (const char *)fdt_getprop(fdt, node, "model", NULL);
-}
diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c
index 11eb0a3..498093d 100644
--- a/plat/st/stm32mp1/stm32mp1_gic.c
+++ b/plat/st/stm32mp1/stm32mp1_gic.c
@@ -4,13 +4,21 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <bl_common.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <gicv2.h>
+#include <libfdt.h>
#include <platform.h>
#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
#include <utils.h>
-#include <stm32mp1_private.h>
+struct stm32_gic_instance {
+ uint32_t cells;
+ uint32_t phandle_node;
+};
/******************************************************************************
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
@@ -21,19 +29,114 @@ static const interrupt_prop_t stm32mp1_interrupt_props[] = {
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
};
-static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+/* Fix target_mask_array as secondary core is not able to initialize it */
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2};
-static const gicv2_driver_data_t platform_gic_data = {
- .gicd_base = STM32MP1_GICD_BASE,
- .gicc_base = STM32MP1_GICC_BASE,
+static gicv2_driver_data_t platform_gic_data = {
.interrupt_props = stm32mp1_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props),
.target_masks = target_mask_array,
.target_masks_num = ARRAY_SIZE(target_mask_array),
};
+static struct stm32_gic_instance stm32_gic;
+
+static uint32_t enable_gic_interrupt(const fdt32_t *array)
+{
+ unsigned int id, cfg;
+
+ switch (fdt32_to_cpu(*array)) {
+ case GIC_SPI:
+ id = MIN_SPI_ID;
+ break;
+
+ case GIC_PPI:
+ id = MIN_PPI_ID;
+ break;
+
+ default:
+ id = MIN_SGI_ID;
+ break;
+ }
+
+ id += fdt32_to_cpu(*(array + 1));
+ cfg = (fdt32_to_cpu(*(array + 2)) < IRQ_TYPE_LEVEL_HIGH) ?
+ GIC_INTR_CFG_EDGE : GIC_INTR_CFG_LEVEL;
+
+ if ((id >= MIN_SPI_ID) && (id <= MAX_SPI_ID)) {
+ VERBOSE("Enable IT %i\n", id);
+ gicv2_set_interrupt_type(id, GICV2_INTR_GROUP0);
+ gicv2_set_interrupt_priority(id, STM32MP1_IRQ_SEC_SPI_PRIO);
+ gicv2_set_spi_routing(id, STM32MP_PRIMARY_CPU);
+ gicv2_interrupt_set_cfg(id, cfg);
+ gicv2_enable_interrupt(id);
+ }
+
+ return id;
+}
+
+static void find_next_interrupt(const fdt32_t **array)
+{
+ int node;
+ const fdt32_t *cuint;
+ void *fdt;
+
+ assert(fdt32_to_cpu(**array) != stm32_gic.phandle_node);
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(**array));
+ if (node < 0) {
+ panic();
+ }
+
+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ *array += fdt32_to_cpu(*cuint) + 1;
+}
+
void stm32mp1_gic_init(void)
{
+ int node;
+ void *fdt;
+ const fdt32_t *cuint;
+ struct dt_node_info dt_gic;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic");
+ if (node < 0) {
+ panic();
+ }
+
+ platform_gic_data.gicd_base = dt_gic.base;
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2));
+
+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ stm32_gic.cells = fdt32_to_cpu(*cuint);
+
+ stm32_gic.phandle_node = fdt_get_phandle(fdt, node);
+ if (stm32_gic.phandle_node == 0U) {
+ panic();
+ }
+
gicv2_driver_init(&platform_gic_data);
gicv2_distif_init();
@@ -46,3 +149,63 @@ void stm32mp1_gic_pcpu_init(void)
gicv2_set_pe_target_mask(plat_my_core_pos());
gicv2_cpuif_enable();
}
+
+int stm32_gic_enable_spi(int node, const char *name)
+{
+ const fdt32_t *cuint;
+ void *fdt;
+ int res, len;
+ int index = -1;
+ int i = 0;
+ int id = -1;
+ bool extended;
+ const fdt32_t *t_array, *max;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ cuint = fdt_getprop(fdt, node, "interrupt-parent", NULL);
+ if (cuint != NULL) {
+ if (stm32_gic.phandle_node != fdt32_to_cpu(*cuint)) {
+ return -FDT_ERR_NOTFOUND;
+ }
+ }
+
+ if (name != NULL) {
+ index = fdt_stringlist_search(fdt, node, "interrupt-names",
+ name);
+ if (index < 0) {
+ return index;
+ }
+ }
+
+ res = fdt_get_interrupt(node, &t_array, &len, &extended);
+ if (res < 0) {
+ return res;
+ }
+
+ max = t_array + (len / sizeof(uint32_t));
+
+ while ((t_array < max) && ((i <= index) || (index == -1))) {
+ if (!extended) {
+ if ((index == -1) || (i == index)) {
+ id = enable_gic_interrupt(t_array);
+ }
+ t_array += stm32_gic.cells;
+ } else {
+ if (fdt32_to_cpu(*t_array) == stm32_gic.phandle_node) {
+ t_array++;
+ if ((index == -1) || (i == index)) {
+ id = enable_gic_interrupt(t_array);
+ }
+ t_array += stm32_gic.cells;
+ } else {
+ find_next_interrupt(&t_array);
+ }
+ }
+ i++;
+ }
+
+ return id;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
index b0ea0d8..1adaaee 100644
--- a/plat/st/stm32mp1/stm32mp1_helper.S
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -8,17 +8,20 @@
#include <asm_macros.S>
#include <bl_common.h>
#include <platform_def.h>
+#include <smccc_helpers.h>
#include <stm32_gpio.h>
#include <stm32mp1_rcc.h>
-#define GPIO_BANK_G_ADDRESS 0x50008000
-#define GPIO_TX_PORT 11
-#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1)
-#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2)
-#define STM32MP1_HSI_CLK 64000000
+#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1)
+#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)
.globl platform_mem_init
.globl plat_report_exception
+#if AARCH32_EXCEPTION_DEBUG
+ .globl plat_report_undef_inst
+ .globl plat_report_prefetch_abort
+ .globl plat_report_data_abort
+#endif
.globl plat_get_my_entrypoint
.globl plat_secondary_cold_boot_setup
.globl plat_reset_handler
@@ -28,6 +31,7 @@
.globl plat_crash_console_flush
.globl plat_crash_console_putc
.globl plat_panic_handler
+ .globl wfi_svc_int_enable
func platform_mem_init
/* Nothing to do, don't need to init SYSRAM */
@@ -35,9 +39,138 @@ func platform_mem_init
endfunc platform_mem_init
func plat_report_exception
+#if DEBUG
+ mov r8, lr
+
+ /* Test if an abort occurred */
+ cmp r0, #MODE32_abt
+ bne undef_inst_lbl
+ ldr r4, =abort_str
+ bl asm_print_str
+ b print_excpetion_info
+
+undef_inst_lbl:
+ /* Test for an undefined instruction */
+ cmp r0, #MODE32_und
+ bne other_excpetion_lbl
+ ldr r4, =undefined_str
+ bl asm_print_str
+ b print_excpetion_info
+
+other_excpetion_lbl:
+ /* Other exceptions */
+ mov r9, r0
+ ldr r4, =exception_start_str
+ bl asm_print_str
+ mov r4, r9
+ bl asm_print_hex
+ ldr r4, =exception_end_str
+ bl asm_print_str
+
+print_excpetion_info:
+ mrs r4, lr_svc
+ sub r4, r4, #4
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+#else
bx lr
+#endif
endfunc plat_report_exception
+#if AARCH32_EXCEPTION_DEBUG
+func plat_report_undef_inst
+#if DEBUG
+ mov r8, lr
+
+ mov r9, r0
+
+ ldr r4, =undefined_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #4
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+#else
+ bx lr
+#endif
+endfunc plat_report_undef_inst
+
+func plat_report_prefetch_abort
+#if DEBUG
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =prefetch_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #4
+ bl asm_print_hex
+
+ ldr r4, =ifsr_str
+ bl asm_print_str
+
+ ldcopr r4, IFSR
+ bl asm_print_hex
+
+ ldr r4, =ifar_str
+ bl asm_print_str
+
+ ldcopr r4, IFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+#else
+ bx lr
+#endif
+endfunc plat_report_prefetch_abort
+
+func plat_report_data_abort
+#if DEBUG
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =data_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #8
+ bl asm_print_hex
+
+ ldr r4, =dfsr_str
+ bl asm_print_str
+
+ ldcopr r4, DFSR
+ bl asm_print_hex
+
+ ldr r4, =dfar_str
+ bl asm_print_str
+
+ ldcopr r4, DFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+#else
+ bx lr
+#endif
+endfunc plat_report_data_abort
+#endif
+
func plat_reset_handler
bx lr
endfunc plat_reset_handler
@@ -76,7 +209,7 @@ func plat_is_my_cpu_primary
ldcopr r0, MPIDR
ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
and r0, r1
- cmp r0, #STM32MP1_PRIMARY_CPU
+ cmp r0, #STM32MP_PRIMARY_CPU
moveq r0, #1
movne r0, #0
bx lr
@@ -111,13 +244,13 @@ endfunc plat_my_core_pos
* ---------------------------------------------
*/
func plat_crash_console_init
- /* Enable GPIOs for UART4 TX */
- ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR)
+ /* Enable GPIOs for UART TX */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
ldr r2, [r1]
- /* Configure GPIO G11 */
- orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN
+ /* Configure GPIO */
+ orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
str r2, [r1]
- ldr r1, =GPIO_BANK_G_ADDRESS
+ ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS
/* Set GPIO mode alternate */
ldr r2, [r1, #GPIO_MODE_OFFSET]
bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
@@ -131,25 +264,24 @@ func plat_crash_console_init
ldr r2, [r1, #GPIO_PUPD_OFFSET]
bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
str r2, [r1, #GPIO_PUPD_OFFSET]
- /* Set alternate AF6 */
+ /* Set alternate */
ldr r2, [r1, #GPIO_AFRH_OFFSET]
bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT)
- orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT)
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT)
str r2, [r1, #GPIO_AFRH_OFFSET]
-
- /* Enable UART clock, with HSI source */
- ldr r1, =(RCC_BASE + RCC_UART24CKSELR)
- mov r2, #RCC_UART24CKSELR_HSI
+ /* Enable UART clock, with its source */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
+ mov r2, #DEBUG_UART_TX_CLKSRC
str r2, [r1]
- ldr r1, =(RCC_BASE + RCC_MP_APB1ENSETR)
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
ldr r2, [r1]
- orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN
+ orr r2, r2, #DEBUG_UART_TX_EN
str r2, [r1]
- ldr r0, =STM32MP1_DEBUG_USART_BASE
- ldr r1, =STM32MP1_HSI_CLK
- ldr r2, =STM32MP1_UART_BAUDRATE
- b console_core_init
+ ldr r0, =STM32MP_DEBUG_USART_BASE
+ ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ
+ ldr r2, =STM32MP_UART_BAUDRATE
+ b console_stm32_core_init
endfunc plat_crash_console_init
/* ---------------------------------------------
@@ -159,8 +291,8 @@ endfunc plat_crash_console_init
* ---------------------------------------------
*/
func plat_crash_console_flush
- ldr r1, =STM32MP1_DEBUG_USART_BASE
- b console_core_flush
+ ldr r1, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_flush
endfunc plat_crash_console_flush
/* ---------------------------------------------
@@ -175,6 +307,68 @@ endfunc plat_crash_console_flush
* ---------------------------------------------
*/
func plat_crash_console_putc
- ldr r1, =STM32MP1_DEBUG_USART_BASE
- b console_core_putc
+ ldr r1, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_putc
endfunc plat_crash_console_putc
+
+ /* -----------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Report exception + endless loop.
+ * -----------------------------------------------------
+ */
+func plat_panic_handler
+ mrs r0, cpsr
+ and r0, #MODE32_MASK
+ bl plat_report_exception
+ b .
+endfunc plat_panic_handler
+
+#if DEBUG
+.section .rodata.rev_err_str, "aS"
+abort_str:
+ .asciz "\nAbort at: 0x"
+#if AARCH32_EXCEPTION_DEBUG
+prefetch_abort_str:
+ .asciz "\nPrefetch Abort at: 0x"
+data_abort_str:
+ .asciz "\nData Abort at: 0x"
+#endif
+undefined_str:
+ .asciz "\nUndefined instruction at: 0x"
+exception_start_str:
+ .asciz "\nException mode=0x"
+exception_end_str:
+ .asciz " at: 0x"
+#if AARCH32_EXCEPTION_DEBUG
+dfsr_str:
+ .asciz " DFSR = 0x"
+dfar_str:
+ .asciz " DFAR = 0x"
+ifsr_str:
+ .asciz " IFSR = 0x"
+ifar_str:
+ .asciz " IFAR = 0x"
+#endif
+end_error_str:
+ .asciz "\n\r"
+#endif
+
+func wfi_svc_int_enable
+ push {r4,r8,lr}
+ ldcopr r4, SCR
+ mov r8, sp
+ mov sp, r0
+ add r0, r0, #STM32MP_INT_STACK_SIZE
+ str r0, [sp, #SMC_CTX_SP_MON]
+ str r4, [sp, #SMC_CTX_SCR]
+ cps #MODE32_svc
+ cpsie af
+ isb
+ dsb
+ wfi
+ cpsid af
+ cps #MODE32_mon
+ mov sp, r8
+ pop {r4,r8,lr}
+ bx lr
+endfunc wfi_svc_int_enable
diff --git a/plat/st/stm32mp1/stm32mp1_helper_dbg.S b/plat/st/stm32mp1/stm32mp1_helper_dbg.S
new file mode 100644
index 0000000..32a86fb
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_helper_dbg.S
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*****************************************************************************
+ * This file is only needed for current Soc revision which has a limitation on
+ * debug reset halt. This can be removed when using the Soc revision that
+ * fixes the limitation. Anyway, this source code identifies the Soc revision
+ * and is only executed if it corresponds, so it can be kept on other
+ * revisions without any consequence.
+ ****************************************************************************/
+
+/*****************************************************************************
+ * This file has been intentionally transformed in order to use only ASM
+ * standard macros and instructions. It could then be easily back-ported to
+ * other pieces of software.
+ ****************************************************************************/
+
+#define BIT_(nr) ((1) << (nr))
+
+#define BSEC_BASE 0x5C005000
+#define BSEC_OTP_DATA_OFF (BSEC_BASE + 0x200)
+#define BSEC_OTP_DATA0 BSEC_OTP_DATA_OFF
+#define BSEC_OTP_DATA0_CLOSED BIT_(6)
+
+#define DBGMCU_BASE 0x50081000
+#define DBGMCU_IDC 0x00
+#define DBGMCU_IDC_REV_ID_DEV_ID_MSK 0xFFFF0FFF
+#define DBGMCU_IDC_REV_ID_DEV_ID_VALUE 0x20000500
+
+#define RCC_BASE 0x50000000
+#define RCC_MP_APB5ENSETR 0x208
+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT_(8)
+#define RCC_DBGCFGR 0x80C
+#define RCC_DBGCFGR_DBGCKEN BIT_(8)
+
+#define PWR_BASE 0x50001000
+#define PWR_CR1 0x00
+#define PWR_CR1_DBP BIT_(8)
+
+#define TAMP_BASE 0x5C00A000
+#define TAMP_BKP_REGISTER_BASE TAMP_BASE + 0x100
+#define TAMP_BKP_REGISTER_20 TAMP_BKP_REGISTER_BASE + (20 << 2)
+
+#define CA7_DBG0_BASE 0x500D0000
+#define DBG_DSCR 0x88
+#define DBG_DSCR_HDBGEN BIT_(14)
+
+#define FSBL_ENTRYPOINT bl2_entrypoint
+
+ .globl plat_dbg_attach_loop
+
+
+plat_dbg_attach_loop:
+ /*
+ * This function is the first call of FSBL_ENTRYPOINT.
+ * Boot rom parameters are stored in r0..r3, so we mustn't use them
+ * here. And because they are saved in r9..r12 just after the
+ * execution of this function, we should only use these registers.
+ * By this way, debug will be done in conditions closed to the initial
+ * context.
+ */
+
+ /*
+ * Check Sec Close bit in OTP (word 0 bit 6). If enabled, do not allow
+ * debug session and exit function.
+ */
+ ldr r12, =BSEC_OTP_DATA0
+ ldr r12, [r12]
+ ands r11, r12, #BSEC_OTP_DATA0_CLOSED
+ bne func_exit
+
+ /*
+ * Enable DBGMCU clock (only if not done).
+ * Initial register content will be saved in r10.
+ * So r10 mustn't be used before restore part.
+ */
+ ldr r12, =(RCC_BASE + RCC_DBGCFGR)
+ ldr r10, [r12]
+ tst r10, #RCC_DBGCFGR_DBGCKEN
+ bne dbgmcu_clk_enabled
+ orr r11, r10, #RCC_DBGCFGR_DBGCKEN
+ str r11, [r12]
+
+ /* Get SoC revision ID and device ID in r11 */
+dbgmcu_clk_enabled:
+ ldr r12, =(DBGMCU_BASE + DBGMCU_IDC)
+ ldr r12, [r12]
+ and r11, r12, #DBGMCU_IDC_REV_ID_DEV_ID_MSK
+
+ /* Restore initial RCC_DBGCFGR content saved in r10 */
+ ldr r12, =(RCC_BASE + RCC_DBGCFGR)
+ str r10, [r12]
+
+ /*
+ * Check SoC revision ID and device ID in r11,
+ * exit if different from REV_ID_DEV_ID_VALUE
+ */
+ ldr r12, =(DBGMCU_IDC_REV_ID_DEV_ID_VALUE)
+ teq r11, r12
+ bne func_exit
+
+ /*
+ * Enable RTC clock before reading tamper (only if not done).
+ * Initial register content will be saved in r10.
+ * So r10 mustn't be used before restore part.
+ */
+ ldr r12, =(RCC_BASE + RCC_MP_APB5ENSETR)
+ ldr r10, [r12]
+ tst r10, #RCC_MP_APB5ENSETR_RTCAPBEN
+ bne rtc_clk_enabled
+ orr r11, r10, #RCC_MP_APB5ENSETR_RTCAPBEN
+ str r11, [r12]
+
+rtc_clk_enabled:
+ /*
+ * Disable the backup domain write protection (only if not done).
+ * Initial register content will be saved in r9.
+ * So r9 mustn't be used before restore part.
+ */
+ ldr r12, =(PWR_BASE + PWR_CR1)
+ ldr r9, [r12]
+ tst r9, #PWR_CR1_DBP
+ bne poll_dbp
+ orr r11, r9, #PWR_CR1_DBP
+ str r11, [r12]
+poll_dbp:
+ /* poll loop to ensure write is effective */
+ ldr r11, [r12]
+ tst r11, #PWR_CR1_DBP
+ beq poll_dbp
+
+ /*
+ * Clear bit 16 of TAMPER backup register 20 (only if set).
+ * Firstly read the register value.
+ * - If bit = 0, r11 = 0 after 'ands' operation. Next step is to
+ * restore RCC_MP_APB5ENSETR and PWR_CR1 contents and exit.
+ * - If bit = 1, r11 != 0 after 'ands' operation, but could be
+ * equal to 0 after 'bic' operation. Here, after clearing the bit,
+ * r11 has to be set to a non-zero value. Next step is to restore
+ * register contents and continue.
+ *
+ * So r11 mustn't be used in restore part, to keep this information
+ * for the next step, i.e. decide to continue execution (r11 = 1) or
+ * exit function (r11 = 0).
+ */
+ ldr r12, =(TAMP_BKP_REGISTER_20)
+ ldr r11, [r12]
+ ands r11, r11, #(BIT_(16))
+ beq restore_reg
+ ldr r11, [r12]
+ bic r11, #(BIT_(16))
+ str r11, [r12]
+ ldr r11, =(1)
+
+restore_reg:
+ /* Restore initial RCC_MP_APB5ENSETR content saved in r10 */
+ ldr r12, =(RCC_BASE + RCC_MP_APB5ENSETR)
+ str r10, [r12]
+
+ /* Restore initial PWR_CR1 content saved in r9 */
+ ldr r12, =(PWR_BASE + PWR_CR1)
+ str r9, [r12]
+poll_cr1:
+ /* poll loop to ensure write is effective */
+ ldr r12, =(PWR_BASE + PWR_CR1)
+ ldr r12, [r12]
+ teq r12, r9
+ bne poll_cr1
+
+ /*
+ * Exit if bit 16 of TAMPER backup register 20 has been cleared.
+ * Information is saved in r11 register.
+ */
+ teq r11, #0
+ beq func_exit
+
+ /* Get time counter frequency */
+ mrc 15, 0, r12, cr14, cr0, 0
+ /* Get current time counter value, save it in r11 as start value */
+ mrrc 15, 0, r11, r10, cr14
+ /*
+ * Compute (current time + 1 second) counter value, save it in r12 as
+ * end value.
+ */
+ add r12, r12, r11
+
+loop:
+ /*
+ * Read CA7_DBG0 DBG_DSCR HDBGEN bit value.
+ * If set, put a software breakpoint and branch to FSBL_ENTRYPOINT.
+ * If cleared, continue and check loop time expiry
+ */
+ ldr r10, =(CA7_DBG0_BASE + DBG_DSCR)
+ ldr r10, [r10]
+ tst r10, #DBG_DSCR_HDBGEN
+ beq loop_continue
+ /* Set a software breakpoint (ID 5) */
+ bkpt 5
+ /* Jump to entrypoint */
+ b FSBL_ENTRYPOINT
+loop_continue:
+ /*
+ * Check 1 second expiry by using r11 and r12 saved values.
+ * Get current time counter value, save it in r10 as current value.
+ */
+ mrrc 15, 0, r10, r9, cr14
+ /* Check if MSB 64-bit increment done between start and end values */
+ cmp r12, r11
+ bmi msb_incr
+ /* No increment, simply check if current < end, exit if yes */
+ cmp r12, r10
+ bmi func_exit
+ b loop
+msb_incr:
+ /*
+ * Increment happened between start and end, here we need to check if
+ * (current > end) && (current < start). Exit if yes.
+ */
+ cmp r12, r10
+ bpl loop
+ cmp r11, r10
+ bmi loop
+func_exit:
+ bx lr
diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c
new file mode 100644
index 0000000..de9035c
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_low_power.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stm32_iwdg.h>
+#include <stm32_rtc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_pmic.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_context.h>
+#include <stm32mp1_ddr_helpers.h>
+#include <stm32mp1_low_power.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_pwr.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
+#include <stpmic1.h>
+
+static unsigned int gicc_pmr;
+static struct stm32_rtc_calendar sleep_time, current_calendar;
+static unsigned long long stdby_time_in_ms;
+static bool enter_cstop_done;
+static uint8_t int_stack[STM32MP_INT_STACK_SIZE];
+
+extern void wfi_svc_int_enable(uintptr_t stack_addr);
+
+struct pwr_lp_config {
+ uint32_t pwr_cr1;
+ uint32_t pwr_mpucr;
+ const char *regul_suspend_node_name;
+};
+
+#define PWR_CR1_MASK (PWR_CR1_LPDS | PWR_CR1_LPCFG | PWR_CR1_LVDS)
+#define PWR_MPUCR_MASK (PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF | PWR_MPUCR_PDDS)
+
+static const struct pwr_lp_config config_pwr[STM32_PM_MAX_SOC_MODE] = {
+ [STM32_PM_CSLEEP_RUN] = {
+ .pwr_cr1 = 0U,
+ .pwr_mpucr = PWR_MPUCR_CSSF,
+ .regul_suspend_node_name = NULL,
+ },
+ [STM32_PM_CSTOP_ALLOW_STOP] = {
+ .pwr_cr1 = 0U,
+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF,
+ .regul_suspend_node_name = NULL,
+ },
+ [STM32_PM_CSTOP_ALLOW_LP_STOP] = {
+ .pwr_cr1 = PWR_CR1_LPDS,
+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF,
+ .regul_suspend_node_name = "lp-stop",
+ },
+ [STM32_PM_CSTOP_ALLOW_LPLV_STOP] = {
+ .pwr_cr1 = PWR_CR1_LVDS | PWR_CR1_LPDS | PWR_CR1_LPCFG,
+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF,
+ .regul_suspend_node_name = "lplv-stop",
+ },
+ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR] = {
+ .pwr_cr1 = 0U,
+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF |
+ PWR_MPUCR_PDDS,
+ .regul_suspend_node_name = "standby-ddr-sr",
+ },
+ [STM32_PM_CSTOP_ALLOW_STANDBY_DDR_OFF] = {
+ .pwr_cr1 = 0U,
+ .pwr_mpucr = PWR_MPUCR_CSTDBYDIS | PWR_MPUCR_CSSF |
+ PWR_MPUCR_PDDS,
+ .regul_suspend_node_name = "standby-ddr-off",
+ },
+ [STM32_PM_SHUTDOWN] = {
+ .pwr_cr1 = 0U,
+ .pwr_mpucr = 0U,
+ .regul_suspend_node_name = "standby-ddr-off",
+ },
+};
+
+#define GICC_PMR_PRIORITY_8 U(0x8)
+
+void stm32_apply_pmic_suspend_config(uint32_t mode)
+{
+ const char *node_name = config_pwr[mode].regul_suspend_node_name;
+
+ assert(mode < ARRAY_SIZE(config_pwr));
+
+ if (node_name != NULL) {
+ if (!initialize_pmic_i2c()) {
+ panic();
+ }
+
+ if (dt_pmic_set_lp_config(node_name) != 0) {
+ panic();
+ }
+
+ if (dt_pmic_configure_boot_on_regulators() != 0) {
+ panic();
+ }
+ }
+}
+
+/*
+ * stm32_enter_cstop - Prepare CSTOP mode
+ *
+ * @mode - Target low power mode
+ * @nsec_addr - Non secure resume entry point
+ * Return 0 if succeed to suspend, non 0 else.
+ */
+static void enter_cstop(uint32_t mode, uint32_t nsec_addr)
+{
+ uint32_t zq0cr0_zdata;
+ uint32_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uint32_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+ uint32_t pwr_cr1 = config_pwr[mode].pwr_cr1;
+ uintptr_t pwr_base = stm32mp_pwr_base();
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ dcsw_op_all(DC_OP_CISW);
+
+ stm32_clean_context();
+
+ if (mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) {
+ /*
+ * The first 64 bytes of DDR need to be saved for DDR DQS
+ * training
+ */
+ stm32_save_ddr_training_area();
+ }
+
+ if (dt_pmic_status() > 0) {
+ stm32_apply_pmic_suspend_config(mode);
+
+ if (mode == STM32_PM_CSTOP_ALLOW_LP_STOP) {
+ pwr_cr1 |= PWR_CR1_LPCFG;
+ }
+ }
+
+ /* Clear RCC interrupt before enabling it */
+ mmio_setbits_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_WKUPF);
+
+ /* Enable RCC Wake-up */
+ mmio_setbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF);
+
+ /* Configure low power mode */
+ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK,
+ config_pwr[mode].pwr_mpucr);
+ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK,
+ pwr_cr1);
+
+ /* Clear RCC pending interrupt flags */
+ mmio_write_32(rcc_base + RCC_MP_CIFR, RCC_MP_CIFR_MASK);
+
+ /* Request CSTOP mode to RCC */
+ mmio_setbits_32(rcc_base + RCC_MP_SREQSETR,
+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1);
+
+ stm32_iwdg_refresh(IWDG2_INST);
+
+ gicc_pmr = plat_ic_set_priority_mask(GICC_PMR_PRIORITY_8);
+
+ /*
+ * Set DDR in Self-refresh, even if no return address is given.
+ * This is also the procedure awaited when switching off power supply.
+ */
+ if (ddr_standby_sr_entry(&zq0cr0_zdata) != 0) {
+ return;
+ }
+
+ stm32mp_clk_enable(RTCAPB);
+
+ mmio_write_32(bkpr_core1_addr, 0);
+ 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
+ */
+ mmio_write_32(bkpr_core1_addr, nsec_addr);
+ mmio_write_32(bkpr_core1_magic,
+ BOOT_API_A7_CORE0_MAGIC_NUMBER);
+
+ if (stm32_save_context(zq0cr0_zdata) != 0) {
+ panic();
+ }
+ }
+
+ stm32mp_clk_disable(RTCAPB);
+
+ stm32_rtc_get_calendar(&sleep_time);
+
+ enter_cstop_done = true;
+}
+
+/*
+ * stm32_exit_cstop - Exit from CSTOP mode
+ */
+void stm32_exit_cstop(void)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (!enter_cstop_done) {
+ return;
+ }
+
+ enter_cstop_done = false;
+
+ if (ddr_sw_self_refresh_exit() != 0) {
+ panic();
+ }
+
+ plat_ic_set_priority_mask(gicc_pmr);
+
+ /* Disable RCC Wake-up */
+ mmio_clrbits_32(rcc_base + RCC_MP_CIER, RCC_MP_CIFR_WKUPF);
+
+ /* Disable STOP request */
+ mmio_setbits_32(rcc_base + RCC_MP_SREQCLRR,
+ RCC_MP_SREQSETR_STPREQ_P0 | RCC_MP_SREQSETR_STPREQ_P1);
+
+ dsb();
+ isb();
+
+ /* Update STGEN counter with low power mode duration */
+ stm32_rtc_get_calendar(&current_calendar);
+
+ stdby_time_in_ms = stm32_rtc_diff_calendar(&current_calendar,
+ &sleep_time);
+
+ stm32mp1_stgen_increment(stdby_time_in_ms);
+}
+
+static void enter_shutdown(void)
+{
+ if (dt_pmic_status() > 0) {
+ if (!initialize_pmic_i2c()) {
+ panic();
+ }
+
+ stpmic1_switch_off();
+
+ udelay(100);
+
+ /* Shouldn't be reached */
+ panic();
+ }
+}
+
+static void enter_csleep(void)
+{
+ uintptr_t pwr_base = stm32mp_pwr_base();
+
+ mmio_clrsetbits_32(pwr_base + PWR_MPUCR, PWR_MPUCR_MASK,
+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_mpucr);
+ mmio_clrsetbits_32(pwr_base + PWR_CR1, PWR_CR1_MASK,
+ config_pwr[STM32_PM_CSLEEP_RUN].pwr_cr1);
+
+ stm32_pwr_down_wfi();
+}
+
+void stm32_enter_low_power(uint32_t mode, uint32_t nsec_addr)
+{
+ switch (mode) {
+ case STM32_PM_SHUTDOWN:
+ enter_shutdown();
+ break;
+
+ case STM32_PM_CSLEEP_RUN:
+ enter_csleep();
+ break;
+
+ default:
+ enter_cstop(mode, nsec_addr);
+ break;
+ }
+}
+
+void stm32_pwr_down_wfi(void)
+{
+ uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
+
+ stm32mp1_rcc_set_wakeup(false);
+
+ while (interrupt == GIC_SPURIOUS_INTERRUPT &&
+ !stm32mp1_rcc_get_wakeup()) {
+ wfi_svc_int_enable((uintptr_t)&int_stack[0]);
+
+ interrupt = gicv2_acknowledge_interrupt();
+
+ if (interrupt != GIC_SPURIOUS_INTERRUPT) {
+ gicv2_end_of_interrupt(interrupt);
+ }
+
+ stm32_iwdg_refresh(IWDG2_INST);
+ }
+}
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index e24af0e..20a2f5c 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -7,7 +7,9 @@
#include <arch_helpers.h>
#include <assert.h>
#include <boot_api.h>
+#include <bsec.h>
#include <debug.h>
+#include <delay_timer.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <errno.h>
#include <gic_common.h>
@@ -16,14 +18,16 @@
#include <platform_def.h>
#include <platform.h>
#include <psci.h>
-#include <stm32mp1_clk.h>
+#include <stm32mp_common.h>
+#include <stm32mp1_low_power.h>
+#include <stm32mp1_power_config.h>
#include <stm32mp1_private.h>
#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
-static uint32_t stm32_sec_entrypoint;
+static uintptr_t stm32_sec_entrypoint;
static uint32_t cntfrq_core0;
-
-#define SEND_SECURE_IT_TO_CORE_1 0x20000U
+static uintptr_t saved_entrypoint;
/*******************************************************************************
* STM32MP1 handler called when a CPU is about to enter standby.
@@ -39,6 +43,7 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state)
* Enter standby state
* dsb is good practice before using wfi to enter low power states
*/
+ isb();
dsb();
while (interrupt == GIC_SPURIOUS_INTERRUPT) {
wfi();
@@ -56,33 +61,43 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state)
/*******************************************************************************
* STM32MP1 handler called when a power domain is about to be turned on. The
* mpidr determines the CPU to be turned on.
- * call by core 0 to activate core 1
+ * call by core 0 to activate core 1
******************************************************************************/
static int stm32_pwr_domain_on(u_register_t mpidr)
{
unsigned long current_cpu_mpidr = read_mpidr_el1();
- uint32_t tamp_clk_off = 0;
uint32_t bkpr_core1_addr =
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
uint32_t bkpr_core1_magic =
tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+ int result;
+
+ result = stm32mp_is_single_core();
+ if (result < 0) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ if (result == 1) {
+ return PSCI_E_INTERN_FAIL;
+ }
if (mpidr == current_cpu_mpidr) {
return PSCI_E_INVALID_PARAMS;
}
- if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) ||
- (stm32_sec_entrypoint > (STM32MP1_SRAM_BASE +
- (STM32MP1_SRAM_SIZE - 1)))) {
+ /* Need to send additional IT 0 after individual core 1 reset */
+ gicv2_raise_sgi(ARM_IRQ_NON_SEC_SGI_0, STM32MP_SECONDARY_CPU);
+
+ /* Wait for this IT to be acknowledged by ROM code. */
+ udelay(10);
+
+ if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) ||
+ (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE +
+ (STM32MP_SYSRAM_SIZE - 1)))) {
return PSCI_E_INVALID_ADDRESS;
}
- if (!stm32mp1_clk_is_enabled(RTCAPB)) {
- tamp_clk_off = 1;
- if (stm32mp1_clk_enable(RTCAPB) != 0) {
- panic();
- }
- }
+ stm32mp_clk_enable(RTCAPB);
cntfrq_core0 = read_cntfrq_el0();
@@ -92,15 +107,10 @@ static int stm32_pwr_domain_on(u_register_t mpidr)
/* Write magic number in backup register */
mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
- if (tamp_clk_off != 0U) {
- if (stm32mp1_clk_disable(RTCAPB) != 0) {
- panic();
- }
- }
+ stm32mp_clk_disable(RTCAPB);
/* Generate an IT to core 1 */
- mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR,
- SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0);
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU);
return PSCI_E_SUCCESS;
}
@@ -120,7 +130,9 @@ static void stm32_pwr_domain_off(const psci_power_state_t *target_state)
******************************************************************************/
static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- /* Nothing to do, power domain is not disabled */
+ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_SUSPEND);
+
+ stm32_enter_low_power(soc_mode, saved_entrypoint);
}
/*******************************************************************************
@@ -147,22 +159,63 @@ static void stm32_pwr_domain_suspend_finish(const psci_power_state_t
/* Nothing to do, power domain is not disabled */
}
+/*******************************************************************************
+ * STM32MP1 handler called when a core tries to power itself down. If this
+ * call is made by core 0, it is a return from stop mode. In this case, we
+ * should restore previous context and jump to secure entrypoint.
+ ******************************************************************************/
static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
*target_state)
{
- ERROR("stm32mpu1 Power Down WFI: operation not handled.\n");
+ if (MPIDR_AFFLVL0_VAL(read_mpidr_el1()) == STM32MP_PRIMARY_CPU) {
+ void (*warm_entrypoint)(void) =
+ (void (*)(void))stm32_sec_entrypoint;
+
+ stm32_pwr_down_wfi();
+
+ stm32_exit_cstop();
+
+ disable_mmu_icache_secure();
+
+ warm_entrypoint();
+ }
+
+ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPUP1RST);
+
+ /* wfi is required for an auto-reset */
+ isb();
+ dsb();
+ wfi();
+
+ /* This shouldn't be reached */
panic();
}
static void __dead2 stm32_system_off(void)
{
- ERROR("stm32mpu1 System Off: operation not handled.\n");
+ uint32_t soc_mode = stm32mp1_get_lp_soc_mode(PSCI_MODE_SYSTEM_OFF);
+
+ if (stm32mp_is_single_core() == 0) {
+ /* Prepare Core 1 reset */
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPUP1RST);
+ /* Send IT to core 1 to put itself in WFI */
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, STM32MP_SECONDARY_CPU);
+ }
+
+ stm32_enter_low_power(soc_mode, 0);
+
+ stm32_pwr_down_wfi();
+
+ /* This shouldn't be reached */
panic();
}
static void __dead2 stm32_system_reset(void)
{
- mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST);
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPSYSRST);
/* Loop in case system reset is not immediately caught */
for ( ; ; ) {
@@ -196,10 +249,12 @@ static int stm32_validate_power_state(unsigned int power_state,
static int stm32_validate_ns_entrypoint(uintptr_t entrypoint)
{
/* The non-secure entry point must be in DDR */
- if (entrypoint < STM32MP1_DDR_BASE) {
+ if (entrypoint < STM32MP_DDR_BASE) {
return PSCI_E_INVALID_ADDRESS;
}
+ saved_entrypoint = entrypoint;
+
return PSCI_E_SUCCESS;
}
@@ -223,6 +278,12 @@ static int stm32_node_hw_state(u_register_t target_cpu,
return (int)HW_ON;
}
+static void stm32_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_OFF;
+ req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_OFF;
+}
+
/*******************************************************************************
* Export the platform handlers. The ARM Standard platform layer will take care
* of registering the handlers with PSCI.
@@ -239,7 +300,8 @@ static const plat_psci_ops_t stm32_psci_ops = {
.system_reset = stm32_system_reset,
.validate_power_state = stm32_validate_power_state,
.validate_ns_entrypoint = stm32_validate_ns_entrypoint,
- .get_node_hw_state = stm32_node_hw_state
+ .get_node_hw_state = stm32_node_hw_state,
+ .get_sys_suspend_power_state = stm32_get_sys_suspend_power_state,
};
/*******************************************************************************
diff --git a/plat/st/stm32mp1/stm32mp1_power_config.c b/plat/st/stm32mp1/stm32mp1_power_config.c
new file mode 100644
index 0000000..ec7ecb1
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_power_config.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <dt-bindings/power/stm32mp1-power.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <limits.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_power_config.h>
+
+#define DT_PWR_COMPAT "st,stm32mp1-pwr"
+#define SYSTEM_SUSPEND_SUPPORTED_MODES "system_suspend_supported_soc_modes"
+#define SYSTEM_OFF_MODE "system_off_soc_mode"
+
+static uint32_t deepest_system_suspend_mode;
+static uint32_t system_off_mode;
+static uint8_t stm32mp1_supported_soc_modes[STM32_PM_MAX_SOC_MODE];
+
+static int dt_get_pwr_node(void *fdt)
+{
+ return fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+}
+
+static void save_supported_mode(void *fdt, int pwr_node)
+{
+ int len;
+ uint32_t count;
+ unsigned int i;
+ uint32_t supported[ARRAY_SIZE(stm32mp1_supported_soc_modes)];
+ const void *prop;
+
+ prop = fdt_getprop(fdt, pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES, &len);
+ if (prop == NULL) {
+ panic();
+ }
+
+ count = (uint32_t)len / sizeof(uint32_t);
+ if (count > STM32_PM_MAX_SOC_MODE) {
+ panic();
+ }
+
+ if (fdt_read_uint32_array(pwr_node, SYSTEM_SUSPEND_SUPPORTED_MODES,
+ &supported[0], count) < 0) {
+ ERROR("PWR DT\n");
+ panic();
+ }
+
+ for (i = 0; i < count; i++) {
+ if (supported[i] >= STM32_PM_MAX_SOC_MODE) {
+ ERROR("Invalid mode\n");
+ panic();
+ }
+ stm32mp1_supported_soc_modes[supported[i]] = 1U;
+ }
+
+ /* Initialize to deepest possible mode */
+ for (i = STM32_PM_MAX_SOC_MODE - 1U; i != STM32_PM_CSLEEP_RUN; i--) {
+ if (stm32mp1_supported_soc_modes[i] == 1U) {
+ deepest_system_suspend_mode = i;
+ break;
+ }
+ }
+}
+
+static int dt_fill_lp_state(uint32_t *lp_state_config, const char *lp_state)
+{
+ int pwr_node;
+ void *fdt;
+ const fdt32_t *cuint;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ pwr_node = dt_get_pwr_node(fdt);
+ if (pwr_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ cuint = fdt_getprop(fdt, pwr_node, lp_state, NULL);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ *lp_state_config = fdt32_to_cpu(*cuint);
+
+ save_supported_mode(fdt, pwr_node);
+
+ return 0;
+}
+
+void stm32mp1_init_lp_states(void)
+{
+ if (dt_fill_lp_state(&system_off_mode, SYSTEM_OFF_MODE) < 0) {
+ ERROR("Node %s not found\n", SYSTEM_OFF_MODE);
+ panic();
+ }
+}
+
+/* Init with all domains ON */
+static bool pm_dom[STM32MP1_PD_MAX_PM_DOMAIN] = {
+ [STM32MP1_PD_VSW] = false,
+ [STM32MP1_PD_CORE_RET] = false,
+ [STM32MP1_PD_CORE] = false
+};
+
+static bool stm32mp1_get_pm_domain_state(uint8_t mode)
+{
+ bool res = true;
+ enum stm32mp1_pm_domain id = STM32MP1_PD_MAX_PM_DOMAIN;
+
+ while (res && (id > mode)) {
+ id--;
+ res &= pm_dom[id];
+ }
+
+ return res;
+}
+
+int stm32mp1_set_pm_domain_state(enum stm32mp1_pm_domain domain, bool status)
+{
+ if (domain >= STM32MP1_PD_MAX_PM_DOMAIN) {
+ return -EINVAL;
+ }
+
+ pm_dom[domain] = status;
+
+ return 0;
+}
+
+static bool is_supported_mode(uint32_t soc_mode)
+{
+ assert(soc_mode < ARRAY_SIZE(stm32mp1_supported_soc_modes));
+
+ return stm32mp1_supported_soc_modes[soc_mode] == 1U;
+}
+
+uint32_t stm32mp1_get_lp_soc_mode(uint32_t psci_mode)
+{
+ uint32_t mode;
+
+ if (psci_mode == PSCI_MODE_SYSTEM_OFF) {
+ return system_off_mode;
+ }
+
+ mode = deepest_system_suspend_mode;
+
+ if ((mode == STM32_PM_CSTOP_ALLOW_STANDBY_DDR_SR) &&
+ ((!stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE_RET)) ||
+ (!is_supported_mode(mode)))) {
+ mode = STM32_PM_CSTOP_ALLOW_LPLV_STOP;
+ }
+
+ if ((mode == STM32_PM_CSTOP_ALLOW_LPLV_STOP) &&
+ ((!stm32mp1_get_pm_domain_state(STM32MP1_PD_CORE)) ||
+ (!is_supported_mode(mode)))) {
+ mode = STM32_PM_CSTOP_ALLOW_LP_STOP;
+ }
+
+ if ((mode == STM32_PM_CSTOP_ALLOW_LP_STOP) &&
+ (!is_supported_mode(mode))) {
+ mode = STM32_PM_CSTOP_ALLOW_STOP;
+ }
+
+ if ((mode == STM32_PM_CSTOP_ALLOW_STOP) &&
+ (!is_supported_mode(mode))) {
+ mode = STM32_PM_CSLEEP_RUN;
+ }
+
+ return mode;
+}
+
+int stm32mp1_set_lp_deepest_soc_mode(uint32_t psci_mode, uint32_t soc_mode)
+{
+ if (soc_mode >= STM32_PM_MAX_SOC_MODE) {
+ return -EINVAL;
+ }
+
+ if (psci_mode == PSCI_MODE_SYSTEM_SUSPEND) {
+ deepest_system_suspend_mode = soc_mode;
+ }
+
+ if (psci_mode == PSCI_MODE_SYSTEM_OFF) {
+ system_off_mode = soc_mode;
+ }
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
new file mode 100644
index 0000000..c1f4c82
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32_iwdg.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <xlat_tables_v2.h>
+
+#define MAP_ROM MAP_REGION_FLAT(STM32MP_ROM_BASE, \
+ STM32MP_ROM_SIZE, \
+ MT_MEMORY | \
+ MT_RO | \
+ MT_SECURE | \
+ MT_EXECUTE)
+
+#define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+ STM32MP_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_SRAM_MCU MAP_REGION_FLAT(STM32MP_SRAM_MCU_BASE, \
+ STM32MP_SRAM_MCU_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_NS | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_RETRAM MAP_REGION_FLAT(STM32MP_RETRAM_BASE, \
+ STM32MP_RETRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_NS | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
+ STM32MP1_DEVICE1_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
+ STM32MP1_DEVICE2_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#if defined(IMAGE_BL2)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_ROM,
+ MAP_SRAM,
+#if defined(STM32MP_USB)
+ MAP_SRAM_MCU,
+#endif
+ MAP_DEVICE1,
+ MAP_DEVICE2,
+ {0}
+};
+#endif
+#if defined(IMAGE_BL32)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_ROM,
+ MAP_SRAM,
+ MAP_DEVICE1,
+ MAP_DEVICE2,
+ {0}
+};
+#endif
+
+void configure_mmu(void)
+{
+#ifndef MMU_OFF
+ unsigned int flags = 0;
+
+ mmap_add(stm32mp1_mmap);
+ init_xlat_tables();
+#ifdef DCACHE_OFF
+ flags |= DISABLE_DCACHE;
+#endif
+ enable_mmu_svc_mon(flags);
+#endif
+}
+
+#if STM32MP_UART_PROGRAMMER
+/*
+ * UART Management
+ */
+static const uintptr_t stm32mp1_uart_addresses[8] = {
+ USART1_BASE,
+ USART2_BASE,
+ USART3_BASE,
+ UART4_BASE,
+ UART5_BASE,
+ USART6_BASE,
+ UART7_BASE,
+ UART8_BASE,
+};
+
+uintptr_t get_uart_address(uint32_t instance_nb)
+{
+ if (!instance_nb || instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))
+ return 0;
+
+ return stm32mp1_uart_addresses[instance_nb - 1];
+}
+#endif
+
+void __dead2 stm32mp_plat_reset(int cpu)
+{
+ uint32_t reg = RCC_MP_GRSTCSETR_MPUP0RST;
+
+ if (stm32mp_is_single_core() == 0) {
+ unsigned int sec_cpu = (cpu == STM32MP_PRIMARY_CPU) ?
+ STM32MP_SECONDARY_CPU : STM32MP_PRIMARY_CPU;
+
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_1, sec_cpu);
+ reg |= RCC_MP_GRSTCSETR_MPUP1RST;
+ }
+
+ mmio_write_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, reg);
+
+ isb();
+ dsb();
+
+ /* Flush L1/L2 data caches */
+ write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
+ dcsw_op_all(DC_OP_CISW);
+
+ for ( ; ; ) {
+ wfi();
+ }
+}
+
+static uint32_t get_part_number(void)
+{
+ uint32_t part_number = 0;
+
+ if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) {
+ ERROR("BSEC: PART_NUMBER_OTP Error\n");
+ return -1;
+ }
+
+ part_number = (part_number & PART_MASK) >> PART_SHIFT;
+
+ return (part_number | (stm32mp1_dbgmcu_get_chip_dev_id() << 16));
+}
+
+static uint32_t get_cpu_package(void)
+{
+ uint32_t package = 0;
+
+ if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) {
+ ERROR("BSEC: PART_NUMBER_OTP Error\n");
+ return -1;
+ }
+
+ return ((package & PKG_MASK) >> PKG_SHIFT);
+}
+
+void stm32mp_print_cpuinfo(void)
+{
+ const char *cpu_s, *cpu_r, *pkg;
+
+ /* MPUs Part Numbers */
+ switch (get_part_number()) {
+ case STM32MP157C_PART_NB:
+ cpu_s = "157C";
+ break;
+ case STM32MP157A_PART_NB:
+ cpu_s = "157A";
+ break;
+ case STM32MP153C_PART_NB:
+ cpu_s = "153C";
+ break;
+ case STM32MP153A_PART_NB:
+ cpu_s = "153A";
+ break;
+ case STM32MP151C_PART_NB:
+ cpu_s = "151C";
+ break;
+ case STM32MP151A_PART_NB:
+ cpu_s = "151A";
+ break;
+ default:
+ cpu_s = "????";
+ break;
+ }
+
+ /* Package */
+ switch (get_cpu_package()) {
+ case PKG_AA_LBGA448:
+ pkg = "AA";
+ break;
+ case PKG_AB_LBGA354:
+ pkg = "AB";
+ break;
+ case PKG_AC_TFBGA361:
+ pkg = "AC";
+ break;
+ case PKG_AD_TFBGA257:
+ pkg = "AD";
+ break;
+ default:
+ pkg = "??";
+ break;
+ }
+
+ /* REVISION */
+ switch (stm32mp1_dbgmcu_get_chip_version()) {
+ case STM32MP1_REV_A:
+ cpu_r = "A";
+ break;
+ case STM32MP1_REV_B:
+ cpu_r = "B";
+ break;
+ default:
+ cpu_r = "?";
+ break;
+ }
+
+ NOTICE("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r);
+}
+
+void stm32mp_print_boardinfo(void)
+{
+ uint32_t board;
+ int res = 0;
+
+ if (bsec_shadow_read_otp(&board, BOARD_OTP) != BSEC_OK) {
+ ERROR("BSEC: PART_NUMBER_OTP Error\n");
+ res = -1;
+ }
+
+ if ((res == 0) && (board != 0U)) {
+ char rev[1];
+
+ *rev = ((board >> 8) & 0xF) - 1 + 'A';
+ NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n",
+ board >> 16,
+ (board >> 12) & 0xF,
+ rev,
+ board & 0xF);
+ }
+}
+
+/*
+ * This function determines if one single core is presently running. This is
+ * done by OTP read.
+ * Returns 1 if yes, 0 if more that one core is running, -1 if error.
+ */
+int stm32mp_is_single_core(void)
+{
+ uint32_t part_number = get_part_number();
+
+ /* STM32MP151x is a single core */
+ if ((part_number == STM32MP151A_PART_NB) ||
+ (part_number == STM32MP151C_PART_NB)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+uint8_t stm32_iwdg_get_instance(uintptr_t base)
+{
+ switch (base) {
+ case IWDG1_BASE:
+ return IWDG1_INST;
+ case IWDG2_BASE:
+ return IWDG2_INST;
+ default:
+ panic();
+ }
+}
+
+uint32_t stm32_iwdg_get_otp_config(uintptr_t base)
+{
+ uint8_t idx;
+ uint32_t iwdg_cfg = 0;
+ uint32_t otp_value;
+
+#if defined(IMAGE_BL2)
+ if (bsec_shadow_read_otp(&otp_value, HW2_OTP) != BSEC_OK) {
+ panic();
+ }
+#elif defined(IMAGE_BL32)
+ if (bsec_read_otp(&otp_value, HW2_OTP) != BSEC_OK) {
+ panic();
+ }
+#endif
+
+ idx = stm32_iwdg_get_instance(base);
+
+ if ((otp_value & BIT(idx + IWDG_HW_POS)) != 0U) {
+ 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_STANDBY_POS)) == 0U) {
+ iwdg_cfg |= IWDG_ENABLE_ON_STANDBY;
+ }
+
+ return iwdg_cfg;
+}
+
+#if defined(IMAGE_BL2)
+uint32_t stm32_iwdg_shadow_update(uintptr_t base, uint32_t flags)
+{
+ uint32_t idx;
+ uint32_t otp;
+ uint32_t result;
+
+ if (bsec_shadow_read_otp(&otp, HW2_OTP) != BSEC_OK) {
+ panic();
+ }
+
+ idx = stm32_iwdg_get_instance(base);
+
+ if ((flags & IWDG_ENABLE_ON_STOP) != 0) {
+ otp |= BIT(idx + IWDG_FZ_STOP_POS);
+ }
+
+ if ((flags & IWDG_ENABLE_ON_STANDBY) != 0) {
+ otp |= BIT(idx + IWDG_FZ_STANDBY_POS);
+ }
+
+ result = bsec_write_otp(otp, HW2_OTP);
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ /* Sticky lock OTP_IWDG (read and write) */
+ if (!bsec_write_sr_lock(HW2_OTP, 1U) ||
+ !bsec_write_sw_lock(HW2_OTP, 1U)) {
+ return BSEC_LOCK_FAIL;
+ }
+
+ return BSEC_OK;
+}
+#endif
+
+/*
+ * This function allows to split bindings between platform and ETZPC
+ * HW mapping. If this conversion was done at driver level, the driver
+ * should include all supported platform bindings. ETZPC may be used on
+ * other platforms.
+ */
+enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode)
+{
+ switch (mode) {
+ case DECPROT_S_RW:
+ return TZPC_DECPROT_S_RW;
+ case DECPROT_NS_R_S_W:
+ return TZPC_DECPROT_NS_R_S_W;
+ case DECPROT_MCU_ISOLATION:
+ return TZPC_DECPROT_MCU_ISOLATION;
+ case DECPROT_NS_RW:
+ return TZPC_DECPROT_NS_RW;
+ default:
+ panic();
+ }
+}
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index e783c14..8dfbe71 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -8,10 +8,10 @@
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <mmio.h>
#include <stdint.h>
-#include <stm32mp1_clk.h>
-#include <stm32mp1_dt.h>
+#include <stm32mp_dt.h>
#include <stm32mp1_private.h>
#include <stm32mp1_rcc.h>
+#include <stm32mp1_shared_resources.h>
#include <tzc400.h>
#include "platform_def.h"
@@ -22,13 +22,63 @@
static void init_tzc400(void)
{
unsigned long long region_base, region_top;
- unsigned long long ddr_base = STM32MP1_DDR_BASE;
+ unsigned long long ddr_base = STM32MP_DDR_BASE;
unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size();
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
+#ifdef AARCH32_SP_OPTEE
+ /* 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;
+ region_top = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE - 1U);
+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
+ region_base,
+ region_top,
+ 0,
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
+
+ /* Region 2 set to cover all secure DRAM. */
+ region_base = ddr_base + (ddr_size - STM32MP_DDR_S_SIZE);
+ region_top = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE - 1U);
+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
+ region_base,
+ region_top,
+ TZC_REGION_S_RDWR,
+ 0);
+
+ /* Region 3 set to cover non-secure shared memory DRAM. */
+ region_base = ddr_base + (ddr_size - STM32MP_DDR_SHMEM_SIZE);
+ region_top = ddr_base + (ddr_size - 1U);
+ tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
+ region_base,
+ region_top,
+ 0,
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
+ 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
* same configuration to all filters in the TZC.
*/
@@ -42,12 +92,14 @@ static void init_tzc400(void)
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
+#endif
/* Raise an exception if a NS device tries to access secure memory */
tzc400_set_action(TZC_ACTION_ERR);
@@ -62,30 +114,8 @@ static void init_tzc400(void)
******************************************************************************/
static void early_init_tzc400(void)
{
- uint32_t rstsr, rst_standby;
-
- rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
-
- /* No warning if return from (C)STANDBY */
- rst_standby = rstsr &
- (RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF);
-
- if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) {
- WARN("TZC400 port 1 clock already enable\n");
- }
-
- if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) {
- WARN("TZC400 port 2 clock already enable\n");
- }
-
- if (stm32mp1_clk_enable(TZC1) != 0) {
- ERROR("Cannot enable TZC1 clock\n");
- panic();
- }
- if (stm32mp1_clk_enable(TZC2) != 0) {
- ERROR("Cannot enable TZC2 clock\n");
- panic();
- }
+ stm32mp_clk_enable(TZC1);
+ stm32mp_clk_enable(TZC2);
tzc400_init(STM32MP1_TZC_BASE);
@@ -96,10 +126,11 @@ static void early_init_tzc400(void)
* same configuration to all filters in the TZC.
*/
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
- STM32MP1_DDR_BASE,
- STM32MP1_DDR_BASE +
- (STM32MP1_DDR_MAX_SIZE - 1U),
+ STM32MP_DDR_BASE,
+ STM32MP_DDR_BASE +
+ (STM32MP_DDR_MAX_SIZE - 1U),
TZC_REGION_S_RDWR,
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
/* Raise an exception if a NS device tries to access secure memory */
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..2c95de0
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,833 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stm32_gpio.h>
+#include <stm32mp_dt.h>
+#include <stm32mp_shres_helpers.h>
+
+static bool registering_locked;
+static int8_t gpioz_nbpin = -1;
+
+/*
+ * Generic clock enable/disable from secure world.
+ * Some drivers may use non secure resources in specific execution context:
+ * when the other SMP core(s) are offline and non secure is never reached.
+ * In such cases, drivers shall enable/disable the HW clock only if it was not
+ * left enabled by the non secure world.
+ *
+ * During driver initializations, before registering_locked is locked, all
+ * driver simply enable/disable the clock as if the peripheral was secure.
+ */
+void stm32mp_clk_enable(unsigned long id)
+{
+ if (registering_locked) {
+ if (stm32mp1_clock_is_non_secure(id)) {
+ assert(stm32mp1_clk_get_refcount(id) == 0U);
+
+ if (stm32mp1_clk_is_enabled(id)) {
+ return;
+ }
+ }
+ }
+
+ stm32mp1_clk_enable_secure(id);
+}
+
+void stm32mp_clk_disable(unsigned long id)
+{
+ if (registering_locked) {
+ if (stm32mp1_clock_is_non_secure(id)) {
+ if (stm32mp1_clk_get_refcount(id) == 0U) {
+ return;
+ }
+ }
+ }
+
+ stm32mp1_clk_disable_secure(id);
+}
+
+/*
+ * Shared peripherals and resources.
+ * Defines resource that may be non secure, secure or shared.
+ * May be a device, a bus, a clock, a memory.
+ *
+ * State default to PERIPH_UNREGISTERED resource is not explicitly
+ * set here.
+ *
+ * Resource driver not built, the resource defaults
+ * to non secure ownership.
+ *
+ * Each IO of the GPIOZ IO can be secure or non secure.
+ * When the GPIO driver is enabled, the GPIOZ bank is fully non secure
+ * only if each IO is non secure and the GPIOZ bank is shared if it
+ * includes secure and non secure IOs.
+ *
+ * BKPSRAM is assumed shared.
+ * DDR control (DDRC and DDRPHY) is secure.
+ * Inits will define the resource state according the device tree
+ * and the driver initialization sequences.
+ *
+ * The platform initialization uses these information to set the ETZPC
+ * configuration. Non secure services (as clocks or regulator accesses)
+ * rely on these information to drive the related service execution.
+ */
+#define SHRES_NON_SECURE 3
+#define SHRES_SHARED 2
+#define SHRES_SECURE 1
+#define SHRES_UNREGISTERED 0
+
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = {
+ [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+ [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+ [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+ [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+ [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+ [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+ [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+ [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+ [STM32MP1_SHRES_IWDG1] = "IWDG1",
+ [STM32MP1_SHRES_USART1] = "USART1",
+ [STM32MP1_SHRES_SPI6] = "SPI6",
+ [STM32MP1_SHRES_I2C4] = "I2C4",
+ [STM32MP1_SHRES_RNG1] = "RNG1",
+ [STM32MP1_SHRES_HASH1] = "HASH1",
+ [STM32MP1_SHRES_CRYP1] = "CRYP1",
+ [STM32MP1_SHRES_I2C6] = "I2C6",
+ [STM32MP1_SHRES_RTC] = "RTC",
+ [STM32MP1_SHRES_MCU] = "MCU",
+ [STM32MP1_SHRES_HSI] = "HSI",
+ [STM32MP1_SHRES_LSI] = "LSI",
+ [STM32MP1_SHRES_HSE] = "HSE",
+ [STM32MP1_SHRES_LSE] = "LSE",
+ [STM32MP1_SHRES_CSI] = "CSI",
+ [STM32MP1_SHRES_PLL1] = "PLL1",
+ [STM32MP1_SHRES_PLL1_P] = "PLL1_P",
+ [STM32MP1_SHRES_PLL1_Q] = "PLL1_Q",
+ [STM32MP1_SHRES_PLL1_R] = "PLL1_R",
+ [STM32MP1_SHRES_PLL2] = "PLL2",
+ [STM32MP1_SHRES_PLL2_P] = "PLL2_P",
+ [STM32MP1_SHRES_PLL2_Q] = "PLL2_Q",
+ [STM32MP1_SHRES_PLL2_R] = "PLL2_R",
+ [STM32MP1_SHRES_PLL3] = "PLL3",
+ [STM32MP1_SHRES_PLL3_P] = "PLL3_P",
+ [STM32MP1_SHRES_PLL3_Q] = "PLL3_Q",
+ [STM32MP1_SHRES_PLL3_R] = "PLL3_R",
+};
+
+static const char *shres2str_id(unsigned int id)
+{
+ return shres2str_id_tbl[id];
+}
+
+static const char *shres2str_state_tbl[4] = {
+ [SHRES_SHARED] = "shared",
+ [SHRES_NON_SECURE] = "non secure",
+ [SHRES_SECURE] = "secure",
+ [SHRES_UNREGISTERED] = "unregistered",
+};
+
+static const char *shres2str_state(unsigned int id)
+{
+ return shres2str_state_tbl[id];
+}
+
+struct shres2decprot {
+ unsigned int shres_id;
+ unsigned int decprot_id;
+ const char *decprot_str;
+};
+
+#define SHRES2DECPROT(shres, decprot, str) { \
+ .shres_id = shres, \
+ .decprot_id = decprot, \
+ .decprot_str = str, \
+ }
+
+#define SHRES_INVALID ~0U
+static const struct shres2decprot shres2decprot_tbl[] = {
+ SHRES2DECPROT(STM32MP1_SHRES_IWDG1, STM32MP1_ETZPC_IWDG1_ID, "IWDG1"),
+ SHRES2DECPROT(STM32MP1_SHRES_USART1, STM32MP1_ETZPC_USART1_ID, "UART1"),
+ SHRES2DECPROT(STM32MP1_SHRES_SPI6, STM32MP1_ETZPC_SPI6_ID, "SPI6"),
+ SHRES2DECPROT(STM32MP1_SHRES_I2C4, STM32MP1_ETZPC_I2C4_ID, "I2C4"),
+ SHRES2DECPROT(STM32MP1_SHRES_RNG1, STM32MP1_ETZPC_RNG1_ID, "RNG1"),
+ SHRES2DECPROT(STM32MP1_SHRES_HASH1, STM32MP1_ETZPC_HASH1_ID, "HASH1"),
+ SHRES2DECPROT(STM32MP1_SHRES_CRYP1, STM32MP1_ETZPC_CRYP1_ID, "CRYP1"),
+ SHRES2DECPROT(STM32MP1_SHRES_I2C6, STM32MP1_ETZPC_I2C6_ID, "I2C6"),
+ /* Below are specific IDs without a 1-to-1 mapping to SHRES IDs */
+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_STGENC_ID, "STGEN"),
+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_BKPSRAM_ID, "BKPSRAM"),
+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRCTRL_ID, "DDRCTRL"),
+ SHRES2DECPROT(SHRES_INVALID, STM32MP1_ETZPC_DDRPHYC_ID, "DDRPHY"),
+};
+
+static unsigned int decprot2shres(unsigned int decprot_id)
+{
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) {
+ if (shres2decprot_tbl[i].decprot_id == decprot_id) {
+ return shres2decprot_tbl[i].shres_id;
+ }
+ }
+
+ VERBOSE("No shared resource %u", decprot_id);
+ return SHRES_INVALID;
+}
+
+static const char *decprot2str(unsigned int decprot_id)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) {
+ if (shres2decprot_tbl[i].decprot_id == decprot_id) {
+ return shres2decprot_tbl[i].decprot_str;
+ }
+ }
+
+ ERROR("Invalid ID %u", decprot_id);
+ panic();
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+ if (gpioz_nbpin < 0) {
+ gpioz_nbpin = (int8_t)fdt_get_gpioz_nbpins_from_dt();
+ assert((gpioz_nbpin == 0) ||
+ (gpioz_nbpin == STM32MP_GPIOZ_PIN_MAX_COUNT));
+ }
+
+ return (unsigned int)gpioz_nbpin;
+}
+
+static bool shareable_resource(unsigned int id)
+{
+ switch (id) {
+ default:
+ /* Currently no shareable resource */
+ return false;
+ }
+}
+
+static void register_periph(unsigned int id, unsigned int state)
+{
+ assert(id < STM32MP1_SHRES_COUNT &&
+ state > SHRES_UNREGISTERED &&
+ state <= SHRES_NON_SECURE);
+
+ if (registering_locked) {
+ if (shres_state[id] == state) {
+ return;
+ }
+
+ panic();
+ }
+
+ if ((state == SHRES_SHARED && !shareable_resource(id)) ||
+ ((shres_state[id] != SHRES_UNREGISTERED) &&
+ (shres_state[id] != state))) {
+ VERBOSE("Cannot change %s from %s to %s\n",
+ shres2str_id(id),
+ shres2str_state(shres_state[id]),
+ shres2str_state(state));
+ panic();
+ }
+
+ shres_state[id] = (uint8_t)state;
+
+ if (shres_state[id] == SHRES_UNREGISTERED) {
+ VERBOSE("Register %s as %s\n",
+ shres2str_id(id), shres2str_state(state));
+ }
+
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0) ... STM32MP1_SHRES_GPIOZ(7):
+ if ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin()) {
+ ERROR("Invalid GPIO pin %u, %u pin(s) available\n",
+ id - STM32MP1_SHRES_GPIOZ(0),
+ get_gpioz_nbpin());
+ panic();
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Explore clock tree to lock dependencies */
+ if ((state == SHRES_SECURE) || (state == SHRES_SHARED)) {
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0) ... STM32MP1_SHRES_GPIOZ(7):
+ stm32mp1_register_clock_parents_secure(GPIOZ);
+ break;
+ case STM32MP1_SHRES_IWDG1:
+ stm32mp1_register_clock_parents_secure(IWDG1);
+ break;
+ case STM32MP1_SHRES_USART1:
+ stm32mp1_register_clock_parents_secure(USART1_K);
+ break;
+ case STM32MP1_SHRES_SPI6:
+ stm32mp1_register_clock_parents_secure(SPI6_K);
+ break;
+ case STM32MP1_SHRES_I2C4:
+ stm32mp1_register_clock_parents_secure(I2C4_K);
+ break;
+ case STM32MP1_SHRES_RNG1:
+ stm32mp1_register_clock_parents_secure(RNG1_K);
+ break;
+ case STM32MP1_SHRES_HASH1:
+ stm32mp1_register_clock_parents_secure(HASH1);
+ break;
+ case STM32MP1_SHRES_CRYP1:
+ stm32mp1_register_clock_parents_secure(CRYP1);
+ break;
+ case STM32MP1_SHRES_I2C6:
+ stm32mp1_register_clock_parents_secure(I2C6_K);
+ break;
+ case STM32MP1_SHRES_RTC:
+ stm32mp1_register_clock_parents_secure(RTC);
+ break;
+ case STM32MP1_SHRES_PLL1_P:
+ case STM32MP1_SHRES_PLL1_Q:
+ case STM32MP1_SHRES_PLL1_R:
+ register_periph(STM32MP1_SHRES_PLL1, SHRES_SECURE);
+ stm32mp1_register_clock_parents_secure(PLL1);
+ break;
+ case STM32MP1_SHRES_PLL2_P:
+ case STM32MP1_SHRES_PLL2_Q:
+ case STM32MP1_SHRES_PLL2_R:
+ register_periph(STM32MP1_SHRES_PLL2, SHRES_SECURE);
+ stm32mp1_register_clock_parents_secure(PLL2);
+ break;
+ case STM32MP1_SHRES_PLL3_P:
+ case STM32MP1_SHRES_PLL3_Q:
+ case STM32MP1_SHRES_PLL3_R:
+ register_periph(STM32MP1_SHRES_PLL3, SHRES_SECURE);
+ stm32mp1_register_clock_parents_secure(PLL3);
+ break;
+ default:
+ /* No expected resource dependency */
+ break;
+ }
+ }
+}
+
+static bool stm32mp1_mckprot_resource(unsigned int id)
+{
+ switch (id) {
+ case STM32MP1_SHRES_MCU:
+ case STM32MP1_SHRES_PLL3:
+ case STM32MP1_SHRES_PLL3_P:
+ case STM32MP1_SHRES_PLL3_Q:
+ case STM32MP1_SHRES_PLL3_R:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Register resource by ID */
+void stm32mp1_register_secure_periph(unsigned int id)
+{
+ register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp1_register_shared_periph(unsigned int id)
+{
+ register_periph(id, SHRES_SHARED);
+}
+
+void stm32mp1_register_non_secure_periph(unsigned int id)
+{
+ register_periph(id, SHRES_NON_SECURE);
+}
+
+/* Register resource by IO memory base address */
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+ unsigned int id;
+
+ switch (base) {
+ case IWDG1_BASE:
+ id = STM32MP1_SHRES_IWDG1;
+ break;
+ case USART1_BASE:
+ id = STM32MP1_SHRES_USART1;
+ break;
+ case SPI6_BASE:
+ id = STM32MP1_SHRES_SPI6;
+ break;
+ case I2C4_BASE:
+ id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_BASE:
+ id = STM32MP1_SHRES_I2C6;
+ break;
+ case RTC_BASE:
+ id = STM32MP1_SHRES_RTC;
+ break;
+ case RNG1_BASE:
+ id = STM32MP1_SHRES_RNG1;
+ break;
+ case CRYP1_BASE:
+ id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1_BASE:
+ id = STM32MP1_SHRES_HASH1;
+ break;
+
+ case GPIOA_BASE:
+ case GPIOB_BASE:
+ case GPIOC_BASE:
+ case GPIOD_BASE:
+ case GPIOE_BASE:
+ case GPIOF_BASE:
+ case GPIOG_BASE:
+ case GPIOH_BASE:
+ case GPIOI_BASE:
+ case GPIOJ_BASE:
+ case GPIOK_BASE:
+ case USART2_BASE:
+ case USART3_BASE:
+ case UART4_BASE:
+ case UART5_BASE:
+ case USART6_BASE:
+ case UART7_BASE:
+ case UART8_BASE:
+ case IWDG2_BASE:
+ /* Allow drivers to register some non secure resources */
+ VERBOSE("IO for non secure resource 0x%x\n",
+ (unsigned int)base);
+ if (state != SHRES_NON_SECURE) {
+ panic();
+ }
+
+ return;
+
+ default:
+ panic();
+ break;
+ }
+
+ register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+/* Register GPIO resource */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+ break;
+ default:
+ ERROR("GPIO bank %u cannot be secured\n", bank);
+ panic();
+ }
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+ break;
+ default:
+ break;
+ }
+}
+
+void stm32mp1_register_etzpc_decprot(unsigned int id,
+ enum etzpc_decprot_attributes attr)
+{
+ unsigned int state = SHRES_SECURE;
+ unsigned int id_shres;
+
+ switch (attr) {
+ case TZPC_DECPROT_S_RW:
+ break;
+ case TZPC_DECPROT_NS_R_S_W:
+ case TZPC_DECPROT_MCU_ISOLATION:
+ case TZPC_DECPROT_NS_RW:
+ state = SHRES_NON_SECURE;
+ break;
+ default:
+ panic();
+ }
+
+ id_shres = decprot2shres(id);
+ if (id_shres == SHRES_INVALID) {
+ if (state == SHRES_SECURE) {
+ panic();
+ }
+ } else {
+ register_periph(id_shres, state);
+ }
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+ registering_locked = true;
+}
+
+bool stm32mp1_periph_is_shared(unsigned long id)
+{
+ lock_registering();
+
+ return shres_state[id] == SHRES_SHARED;
+}
+
+bool stm32mp1_periph_is_non_secure(unsigned long id)
+{
+ lock_registering();
+
+ return shres_state[id] == SHRES_NON_SECURE;
+}
+
+bool stm32mp1_periph_is_secure(unsigned long id)
+{
+ lock_registering();
+
+ return shres_state[id] == SHRES_SECURE;
+}
+
+bool stm32mp1_periph_is_unregistered(unsigned long id)
+{
+ lock_registering();
+
+ return shres_state[id] == SHRES_UNREGISTERED;
+}
+
+bool stm32mp_gpio_bank_is_shared(unsigned int bank)
+{
+ unsigned int non_secure = 0;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return false;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) ||
+ stm32mp1_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) {
+ non_secure++;
+ }
+ }
+
+ return (non_secure != 0) && (non_secure < get_gpioz_nbpin());
+}
+
+bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+ unsigned int non_secure = 0;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return true;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (stm32mp1_periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i)) ||
+ stm32mp1_periph_is_unregistered(STM32MP1_SHRES_GPIOZ(i))) {
+ non_secure++;
+ }
+ }
+
+ return non_secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+ unsigned int secure = 0;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return false;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (stm32mp1_periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ secure++;
+ }
+ }
+
+ return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp1_clock_is_shareable(unsigned long clock_id)
+{
+ switch (clock_id) {
+ case GPIOZ:
+ return get_gpioz_nbpin() > 0;
+ case RTCAPB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool stm32mp1_clock_is_shared(unsigned long clock_id)
+{
+ lock_registering();
+
+ switch (clock_id) {
+ case GPIOZ:
+ if (get_gpioz_nbpin() > 0) {
+ return stm32mp_gpio_bank_is_shared(GPIO_BANK_Z);
+ } else {
+ return false;
+ }
+ case RTCAPB:
+ /* RTCAPB is shared for non secure backup registers */
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool stm32mp1_clock_is_non_secure(unsigned long clock_id)
+{
+ unsigned int shres_id;
+
+ lock_registering();
+
+ if (stm32mp1_clock_is_shared(clock_id)) {
+ return false;
+ }
+
+ switch (clock_id) {
+ case BSEC:
+ case BKPSRAM:
+ case TZPC:
+ case TZC1:
+ case TZC2:
+ case STGEN_K:
+ case DDRC1:
+ case DDRC1LP:
+ case DDRC2:
+ case DDRC2LP:
+ case DDRPHYC:
+ case DDRPHYCLP:
+ case DDRCAPB:
+ case DDRCAPBLP:
+ case AXIDCG:
+ case DDRPHYCAPB:
+ case DDRPHYCAPBLP:
+ return false;
+ case IWDG1:
+ shres_id = STM32MP1_SHRES_IWDG1;
+ break;
+ case USART1_K:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ case SPI6_K:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case I2C4_K:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case RNG1_K:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case HASH1:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case CRYP1:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case I2C6_K:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case RTC:
+ shres_id = STM32MP1_SHRES_RTC;
+ break;
+ default:
+ return true;
+ }
+
+ return stm32mp1_periph_is_non_secure(shres_id);
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes decprot_periph_attr(unsigned int id)
+{
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0) ... STM32MP1_SHRES_GPIOZ(7):
+ assert((id - STM32MP1_SHRES_GPIOZ(0)) < get_gpioz_nbpin());
+ return TZPC_DECPROT_NS_RW;
+ default:
+ if (stm32mp1_periph_is_non_secure(id)) {
+ return TZPC_DECPROT_NS_RW;
+ }
+
+ return TZPC_DECPROT_S_RW;
+ }
+}
+
+static bool check_decprot(unsigned int id, enum etzpc_decprot_attributes exp)
+{
+ enum etzpc_decprot_attributes cur = etzpc_get_decprot(id);
+
+ if (cur == exp) {
+ return true;
+ }
+
+ switch (exp) {
+ case TZPC_DECPROT_NS_RW:
+ if (cur == TZPC_DECPROT_S_RW) {
+ WARN("ETZPC: %s (%d) could be non secure\n",
+ decprot2str(id), id);
+ }
+ return true;
+
+ case TZPC_DECPROT_S_RW:
+ ERROR("ETZPC: %s (%d) expected secure but DECPROT = %d\n",
+ decprot2str(id), id, cur);
+ break;
+
+ case TZPC_DECPROT_NS_R_S_W:
+ case TZPC_DECPROT_MCU_ISOLATION:
+ default:
+ panic();
+ }
+
+ return false;
+}
+
+static void check_etzpc_secure_configuration(void)
+{
+ bool error = false;
+
+ assert(registering_locked);
+
+ error |= !check_decprot(STM32MP1_ETZPC_STGENC_ID, TZPC_DECPROT_S_RW);
+
+ error |= !check_decprot(STM32MP1_ETZPC_BKPSRAM_ID, TZPC_DECPROT_S_RW);
+
+ error |= !check_decprot(STM32MP1_ETZPC_USART1_ID,
+ decprot_periph_attr(STM32MP1_SHRES_USART1));
+
+ error |= !check_decprot(STM32MP1_ETZPC_SPI6_ID,
+ decprot_periph_attr(STM32MP1_SHRES_SPI6));
+
+ error |= !check_decprot(STM32MP1_ETZPC_I2C4_ID,
+ decprot_periph_attr(STM32MP1_SHRES_I2C4));
+
+ error |= !check_decprot(STM32MP1_ETZPC_RNG1_ID,
+ decprot_periph_attr(STM32MP1_SHRES_RNG1));
+
+ error |= !check_decprot(STM32MP1_ETZPC_HASH1_ID,
+ decprot_periph_attr(STM32MP1_SHRES_HASH1));
+
+ error |= !check_decprot(STM32MP1_ETZPC_CRYP1_ID,
+ decprot_periph_attr(STM32MP1_SHRES_CRYP1));
+
+ error |= !check_decprot(STM32MP1_ETZPC_DDRCTRL_ID, TZPC_DECPROT_S_RW);
+
+ error |= !check_decprot(STM32MP1_ETZPC_DDRPHYC_ID, TZPC_DECPROT_S_RW);
+
+ error |= !check_decprot(STM32MP1_ETZPC_I2C6_ID,
+ decprot_periph_attr(STM32MP1_SHRES_I2C6));
+
+ if (error) {
+ panic();
+ }
+}
+
+static void check_rcc_secure_configuration(void)
+{
+ uint32_t n;
+ uint32_t error = 0;
+ 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)) {
+ if ((stm32mp1_mckprot_resource(n) && (!mckprot)) ||
+ !secure) {
+ ERROR("RCC %s MCKPROT %s and %s (%u) secure\n",
+ secure ? "secure" : "non secure",
+ mckprot ? "set" : "not set",
+ shres2str_id(n), n);
+ error++;
+ }
+ }
+ }
+
+ if (error != 0U) {
+ panic();
+ }
+}
+
+static void check_gpio_secure_configuration(void)
+{
+ uint32_t pin;
+
+ for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+ bool secure =
+ stm32mp1_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+ set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure);
+ }
+}
+
+void stm32mp1_driver_init_late(void)
+{
+ uint32_t __unused id;
+
+ registering_locked = true;
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+ for (id = 0; id < STM32MP1_SHRES_COUNT; id++) {
+ uint8_t *state = &shres_state[id];
+
+ /* Display only the secure and shared resources */
+ if ((*state == SHRES_NON_SECURE) ||
+ ((*state == SHRES_UNREGISTERED))) {
+ continue;
+ }
+
+ INFO("stm32mp %s (%u): %s\n",
+ shres2str_id(id), id,
+ *state == SHRES_SECURE ? "Secure only" :
+ *state == SHRES_SHARED ? "Shared" :
+ *state == SHRES_NON_SECURE ? "Non secure" :
+ *state == SHRES_UNREGISTERED ? "Unregistered" :
+ "<Invalid>");
+ }
+#endif
+
+ stm32mp1_update_earlyboot_clocks_state();
+
+ check_rcc_secure_configuration();
+ check_etzpc_secure_configuration();
+ check_gpio_secure_configuration();
+}
+
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
new file mode 100644
index 0000000..3eb9893
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bsec.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_private.h>
+#include <stpmic1.h>
+
+/*
+ * SYSCFG REGISTER OFFSET (base relative)
+ */
+#define SYSCFG_BOOTR 0x00U
+#define SYSCFG_IOCTRLSETR 0x18U
+#define SYSCFG_ICNR 0x1CU
+#define SYSCFG_CMPCR 0x20U
+#define SYSCFG_CMPENSETR 0x24U
+
+/*
+ * SYSCFG_BOOTR Register
+ */
+#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
+/*
+ * SYSCFG_IOCTRLSETR Register
+ */
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
+
+/*
+ * SYSCFG_ICNR Register
+ */
+#define SYSCFG_ICNR_AXI_M9 BIT(9)
+
+/*
+ * SYSCFG_CMPCR Register
+ */
+#define SYSCFG_CMPCR_SW_CTRL BIT(1)
+#define SYSCFG_CMPCR_READY BIT(8)
+
+/*
+ * SYSCFG_CMPENSETR Register
+ */
+#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
+
+#define PRODUCT_BELOW_2V5 BIT(13)
+
+void stm32mp1_syscfg_init(void)
+{
+ uint32_t bootr;
+ uint32_t otp = 0;
+ uint32_t vdd_voltage;
+ uintptr_t syscfg_base = dt_get_syscfg_base();
+
+ /*
+ * Interconnect update : select master using the port 1.
+ * LTDC = AXI_M9.
+ */
+ mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
+ VERBOSE("[0x%x] SYSCFG.icnr = 0x%08x (LTDC)\n",
+ (uint32_t)syscfg_base + SYSCFG_ICNR,
+ mmio_read_32(syscfg_base + SYSCFG_ICNR));
+
+ /* Disable Pull-Down for boot pin connected to VDD */
+ bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR);
+ bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
+ bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
+ mmio_write_32(syscfg_base + SYSCFG_BOOTR, bootr);
+ VERBOSE("[0x%x] SYSCFG.bootr = 0x%08x\n",
+ (uint32_t)syscfg_base + SYSCFG_BOOTR,
+ mmio_read_32(syscfg_base + SYSCFG_BOOTR));
+
+ /*
+ * 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.
+ *
+ * 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)
+ * but this value needs to be consistent with board design.
+ */
+ if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) {
+ otp = otp & PRODUCT_BELOW_2V5;
+ }
+
+ /* Get VDD = pwr-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");
+ } else if (vdd_voltage < 2700000U) {
+ mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR,
+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+ SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+ SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+
+ if (otp == 0U) {
+ INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
+ }
+ } else {
+ if (otp != 0U) {
+ INFO("Product_below_2v5=1: HSLVEN update is\n");
+ INFO(" destructive, no update as VDD>2.7V\n");
+ }
+ }
+
+ VERBOSE("[0x%x] SYSCFG.IOCTRLSETR = 0x%08x\n",
+ (uint32_t)syscfg_base + SYSCFG_IOCTRLSETR,
+ mmio_read_32(syscfg_base + SYSCFG_IOCTRLSETR));
+
+ /*
+ * Activate automatic I/O compensation.
+ * Warning: need to ensure CSI enabled and ready in clock driver.
+ */
+ mmio_write_32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN);
+
+ while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) &
+ SYSCFG_CMPCR_READY) != 0U) {
+ ;
+ }
+
+ mmio_clrbits_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));
+}
diff --git a/plat/st/stm32mp1/stm32mp1_usb_desc.c b/plat/st/stm32mp1/stm32mp1_usb_desc.c
new file mode 100644
index 0000000..410cfa1
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_usb_desc.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bsec.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <stm32mp1_usb_desc.h>
+#include <string.h>
+#include <usb_core.h>
+#include <usb_st_dfu.h>
+
+/* USB Standard Device Descriptor */
+static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
+ USB_LEN_DEV_DESC, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* bDescriptorType */
+ 0x00, /* bcdUSB */
+ 0x02, /* version */
+ 0x00, /* bDeviceClass */
+ 0x00, /* bDeviceSubClass */
+ 0x00, /* bDeviceProtocol */
+ USB_MAX_EP0_SIZE, /* bMaxPacketSize */
+ LOBYTE(USBD_VID), /* idVendor */
+ HIBYTE(USBD_VID), /* idVendor */
+ LOBYTE(USBD_PID), /* idVendor */
+ HIBYTE(USBD_PID), /* idVendor */
+ 0x00, /* bcdDevice rel. 2.00 */
+ 0x02,
+ USBD_IDX_MFC_STR, /* Index of manufacturer string */
+ USBD_IDX_PRODUCT_STR, /* Index of product string */
+ USBD_IDX_SERIAL_STR, /* Index of serial number string */
+ USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
+}; /* USB_DeviceDescriptor */
+
+/* USB Standard String Descriptor */
+static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
+ USB_LEN_LANGID_STR_DESC,
+ USB_DESC_TYPE_STRING,
+ LOBYTE(USBD_LANGID_STRING),
+ HIBYTE(USBD_LANGID_STRING),
+};
+
+/* USB Standard Device Descriptor */
+static const uint8_t
+usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x01,
+ 0x00,
+};
+
+static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1] = {
+ USB_SIZ_STRING_SERIAL,
+ USB_DESC_TYPE_STRING,
+};
+
+/* USB DFU device Configuration Descriptor */
+static uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
+ 0x09, /* bLength: Configuation Descriptor size */
+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+ USB_DFU_CONFIG_DESC_SIZ,
+ /* wTotalLength: Bytes returned */
+ 0x00,
+ 0x01,/* bNumInterfaces: 1 interface*/
+ 0x01,/* bConfigurationValue: Configuration value*/
+ 0x02,/* iConfiguration: Index of string descriptor
+ * describing the configuration
+ */
+ 0xC0,/* bmAttributes: bus powered and Supprts Remote Wakeup */
+ 0x32,/* MaxPower 100 mA: this current is used for detecting Vbus */
+ /* 09 */
+
+ /* Descriptor of DFU interface 0 Alternate setting 0 */
+ USBD_DFU_IF_DESC(0), /* This interface is mandatory for all devices */
+
+ /* Descriptor of DFU interface 0 Alternate setting 1 */
+ USBD_DFU_IF_DESC(1),
+
+ /* Descriptor of DFU interface 0 Alternate setting 2 */
+ USBD_DFU_IF_DESC(2),
+
+ /* Descriptor of DFU interface 0 Alternate setting 3 */
+ USBD_DFU_IF_DESC(3),
+
+ /* Descriptor of DFU interface 0 Alternate setting 4 */
+ USBD_DFU_IF_DESC(4),
+
+ /* Descriptor of DFU interface 0 Alternate setting 5 */
+ USBD_DFU_IF_DESC(5),
+
+ /* DFU Functional Descriptor */
+ 0x09,/* blength = 9 Bytes */
+ DFU_DESCRIPTOR_TYPE,/* DFU Functional Descriptor*/
+ DFU_BM_ATTRIBUTE,/* bmAttribute
+ * bitCanDnload = 1 (bit 0)
+ * bitCanUpload = 1 (bit 1)
+ * bitManifestationTolerant = 1 (bit 2)
+ * bitWillDetach = 1 (bit 3)
+ * Reserved (bit4-6)
+ * bitAcceleratedST = 0 (bit 7)
+ */
+ 0xFF,/* DetachTimeOut = 255 ms */
+ 0x00,
+ /* WARNING: In DMA mode the multiple MPS packets feature
+ * is still not supported ==> In this case,
+ * when using DMA USBD_DFU_XFER_SIZE should be set
+ * to 64 in usbd_conf.h
+ */
+ TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE),/* TransferSize = 1024 Byte*/
+ ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion*/
+ ((USB_DFU_VERSION >> 8) & 0xFF)
+};
+
+static uint8_t usb_local_string_dec[USBD_MAX_STR_DESC_SIZ];
+
+/*
+ * Convert Hex 32Bits value into char
+ * value: value to convert
+ * pbuf: pointer to the buffer
+ * len: buffer length
+ */
+static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len)
+{
+ uint8_t idx = 0;
+
+ for (idx = 0; idx < len; idx++) {
+ if (((value >> 28)) < 0xA)
+ pbuf[2 * idx] = (value >> 28) + '0';
+ else
+ pbuf[2 * idx] = (value >> 28) + 'A' - 10;
+ value = value << 4;
+ pbuf[(2 * idx) + 1] = 0;
+ }
+}
+
+/*
+ * Create the serial number string descriptor
+ */
+static void update_serial_num_string(void)
+{
+ /* serial number is set to 0*/
+ uint8_t i;
+ uint32_t deviceserial[3] = {0, 0, 0};
+
+ for (i = 0; i < 3; i++) {
+ if (bsec_shadow_read_otp(&deviceserial[i], i + UID0_OTP) !=
+ BSEC_OK) {
+ ERROR("BSEC: UID%d Error\n", i);
+ return;
+ }
+ }
+
+ int_to_unicode(deviceserial[0], (uint8_t *)&usb_stm32mp1_serial[2], 8);
+ int_to_unicode(deviceserial[1], (uint8_t *)&usb_stm32mp1_serial[18], 8);
+ int_to_unicode(deviceserial[2], (uint8_t *)&usb_stm32mp1_serial[34], 8);
+}
+
+/*
+ * usb_get_qualifier_desc
+ * return Device Qualifier descriptor
+ * param : length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
+{
+ *length = sizeof(usbd_stm32mp1_qualifier_desc);
+ return (uint8_t *)usbd_stm32mp1_qualifier_desc;
+}
+
+/*
+ * stm32mp1_get_dfu_desc
+ * return Device Qualifier descriptor
+ * param : length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_dfu_desc(uint16_t *len)
+{
+ *len = USB_DFU_DESC_SIZ;
+ return ((uint8_t *)usb_stm32mp1_config_desc + (9 * 7));
+}
+
+/*
+ * stm32mp1_get_config_desc
+ * return configuration descriptor
+ * param : speed : current device speed
+ * param : length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_config_desc);
+ return (uint8_t *)usb_stm32mp1_config_desc;
+}
+
+/*
+ * stm32mp1_get_string
+ * Convert Ascii string into unicode one
+ * param : desc : descriptor buffer
+ * param : unicode : Formatted string buffer (unicode)
+ * param : len : descriptor length
+ * return : None
+ */
+static void stm32mp1_get_string(uint8_t *desc, uint8_t *unicode, uint16_t *len)
+{
+ uint8_t idx = 0;
+
+ if (!desc)
+ return;
+
+ *len = strlen((char *)desc) * 2 + 2;
+ unicode[idx++] = *len;
+ unicode[idx++] = USB_DESC_TYPE_STRING;
+
+ while (*desc != '\0') {
+ unicode[idx++] = *desc++;
+ unicode[idx++] = 0x00;
+ }
+}
+
+/*
+ * stm32mp1_device_desc
+ * Returns the device descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_device_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_desc);
+ return (uint8_t *)usb_stm32mp1_desc;
+}
+
+/*
+ * stm32mp1_lang_id_desc
+ * Returns the LangID string descriptor.
+ * speed: Current device speed
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_lang_id_desc);
+
+ return (uint8_t *)usb_stm32mp1_lang_id_desc;
+}
+
+/*
+ * stm32mp1_product_desc
+ * Returns the product string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_product_desc(uint16_t *length)
+{
+ stm32mp1_get_string((uint8_t *)USBD_PRODUCT_HS_STRING,
+ usb_local_string_dec, length);
+
+ return usb_local_string_dec;
+}
+
+/*
+ * stm32mp1_manufacturer_desc
+ * Returns the manufacturer string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
+{
+ stm32mp1_get_string((uint8_t *)USBD_MANUFACTURER_STRING,
+ usb_local_string_dec, length);
+
+ return usb_local_string_dec;
+}
+
+/*
+ * stm32mp1_serial_desc
+ * Returns the serial number string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_serial_desc(uint16_t *length)
+{
+ *length = USB_SIZ_STRING_SERIAL;
+
+ /* Update the serial number string descriptor
+ * with the data from the unique ID
+ */
+ update_serial_num_string();
+
+ return (uint8_t *)usb_stm32mp1_serial;
+}
+
+/*
+ * stm32mp1_Config_desc
+ * Returns the configuration string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_config_desc(uint16_t *length)
+{
+ stm32mp1_get_string((uint8_t *)USBD_CONFIGURATION_HS_STRING,
+ usb_local_string_dec, length);
+
+ return usb_local_string_dec;
+}
+
+/*
+ * stm32mp1_interface_desc
+ * Returns the interface string descriptor.
+ * length : Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_interface_desc(uint16_t *length)
+{
+ stm32mp1_get_string((uint8_t *)USBD_INTERFACE_HS_STRING,
+ usb_local_string_dec, length);
+
+ return usb_local_string_dec;
+}
+
+/*
+ * stm32mp1_get_usr_desc
+ * Manages the transfer of memory interfaces string descriptors.
+ * param : index: descriptor index
+ * param : length : pointer data length
+ * return : pointer to the descriptor table or NULL if the descriptor
+ * is not supported.
+ */
+static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
+{
+ uint8_t *ret;
+
+ if (index > (USBD_IDX_INTERFACE_STR + USBD_DESC_MAX_ITF_NUM))
+ return NULL;
+
+ switch (index) {
+ case 6:
+ stm32mp1_get_string((uint8_t *)"@Partition0 /0x00/1*256Ke",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ case 7:
+ stm32mp1_get_string((uint8_t *)"@FSBL /0x01/1*1Me",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ case 8:
+ stm32mp1_get_string((uint8_t *)"@Partition2 /0x02/1*1Me",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ case 9:
+ stm32mp1_get_string((uint8_t *)"@Partition3 /0x03/1*16Me",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ case 10:
+ stm32mp1_get_string((uint8_t *)"@Partition4 /0x04/1*16Me",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ case 11:
+ stm32mp1_get_string((uint8_t *)"@virtual /0xF1/1*512Ba",
+ usb_local_string_dec, length);
+ ret = usb_local_string_dec;
+ break;
+ default:
+ ret = NULL;
+ break;
+ }
+
+ return ret;
+}
+
+static const usb_desc_t dfu_desc = {
+ .get_device_desc = stm32mp1_device_desc,
+ .get_lang_id_desc = stm32mp1_lang_id_desc,
+ .get_manufacturer_desc = stm32mp1_manufacturer_desc,
+ .get_product_desc = stm32mp1_product_desc,
+ .get_configuration_desc = stm32mp1_config_desc,
+ .get_serial_desc = stm32mp1_serial_desc,
+ .get_interface_desc = stm32mp1_interface_desc,
+ .get_usr_desc = stm32mp1_get_usr_desc,
+ .get_hs_config_desc = stm32mp1_get_config_desc,
+ .get_fs_config_desc = stm32mp1_get_config_desc,
+ .get_other_speed_config_desc = stm32mp1_get_config_desc,
+ .get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
+ .get_dfu_desc = stm32mp1_get_dfu_desc
+};
+
+void stm32mp_usb_init_desc(usb_handle_t *pdev)
+{
+ register_platform(pdev, &dfu_desc);
+}
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index 7b10e3e..c03629a 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -22,7 +22,7 @@ OBJECTS := src/cert.o \
src/tbbr/tbb_ext.o \
src/tbbr/tbb_key.o
-CFLAGS := -Wall -std=c99
+HOSTCCFLAGS := -Wall -std=c99
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
@@ -46,9 +46,9 @@ endif
endif
ifeq (${DEBUG},1)
- CFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
+ HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
else
- CFLAGS += -O2 -DLOG_LEVEL=20
+ HOSTCCFLAGS += -O2 -DLOG_LEVEL=20
endif
ifeq (${V},0)
Q := @
@@ -57,7 +57,7 @@ else
endif
$(eval $(call add_define,USE_TBBR_DEFS))
-CFLAGS += ${DEFINES}
+HOSTCCFLAGS += ${DEFINES}
# Make soft links and include from local directory otherwise wrong headers
# could get pulled in from firmware tree.
@@ -72,15 +72,15 @@ HOSTCC ?= gcc
all: clean ${BINARY}
${BINARY}: ${OBJECTS} Makefile
- @echo " LD $@"
+ @echo " HOSTLD $@"
@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
const char platform_msg[] = "${PLAT_MSG}";' | \
- ${HOSTCC} -c ${CFLAGS} -xc - -o src/build_msg.o
+ ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
%.o: %.c
- @echo " CC $<"
- ${Q}${HOSTCC} -c ${CFLAGS} ${INC_DIR} $< -o $@
+ @echo " HOSTCC $<"
+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
clean:
$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
diff --git a/tools/doimage/Makefile b/tools/doimage/Makefile
index bc74369..9f0d89d 100644
--- a/tools/doimage/Makefile
+++ b/tools/doimage/Makefile
@@ -7,11 +7,11 @@
PROJECT = doimage
OBJECTS = doimage.o
-CFLAGS = -Wall -Werror
+HOSTCCFLAGS = -Wall -Werror
ifeq (${DEBUG},1)
- CFLAGS += -g -O0 -DDEBUG
+ HOSTCCFLAGS += -g -O0 -DDEBUG
else
- CFLAGS += -O2
+ HOSTCCFLAGS += -O2
endif
ifeq (${MARVELL_SECURE_BOOT},1)
@@ -19,13 +19,13 @@ DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT
DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509
endif
-CFLAGS += ${DOIMAGE_CC_FLAGS}
+HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS}
# Make soft links and include from local directory otherwise wrong headers
# could get pulled in from firmware tree.
INCLUDE_PATHS = -I.
-CC := gcc
+HOSTCC ?= gcc
RM := rm -rf
.PHONY: all clean
@@ -33,15 +33,15 @@ RM := rm -rf
all: ${PROJECT}
${PROJECT}: ${OBJECTS} Makefile
- @echo " LD $@"
- ${Q}${CC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@
+ @echo " HOSTLD $@"
+ ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@
@echo
@echo "Built $@ successfully"
@echo
-%.o: %.c %.h Makefile
- @echo " CC $<"
- ${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+%.o: %.c Makefile
+ @echo " HOSTCC $<"
+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
clean:
${Q}${RM} ${PROJECT}
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index 9bdafe0..ef35014 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -13,11 +13,11 @@ OBJECTS := fiptool.o tbbr_config.o
V ?= 0
override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700
-CFLAGS := -Wall -Werror -pedantic -std=c99
+HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99
ifeq (${DEBUG},1)
- CFLAGS += -g -O0 -DDEBUG
+ HOSTCCFLAGS += -g -O0 -DDEBUG
else
- CFLAGS += -O2
+ HOSTCCFLAGS += -O2
endif
LDLIBS := -lcrypto
@@ -36,15 +36,15 @@ HOSTCC ?= gcc
all: ${PROJECT}
${PROJECT}: ${OBJECTS} Makefile
- @echo " LD $@"
+ @echo " HOSTLD $@"
${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS}
@${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@${ECHO_BLANK_LINE}
%.o: %.c %.h Makefile
- @echo " CC $<"
- ${Q}${HOSTCC} -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+ @echo " HOSTCC $<"
+ ${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
clean:
$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
diff --git a/tools/stm32image/Makefile b/tools/stm32image/Makefile
index 80dfbec..9c9b7b5 100644
--- a/tools/stm32image/Makefile
+++ b/tools/stm32image/Makefile
@@ -12,12 +12,12 @@ PROJECT := stm32image${BIN_EXT}
OBJECTS := stm32image.o
V := 0
-override CPPFLAGS += -D_GNU_SOURCE
-CFLAGS := -Wall -Werror -pedantic -std=c99
+HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE
+
ifeq (${DEBUG},1)
- CFLAGS += -g -O0 -DDEBUG
+ HOSTCCFLAGS += -g -O0 -DDEBUG
else
- CFLAGS += -O2
+ HOSTCCFLAGS += -O2
endif
ifeq (${V},0)
@@ -26,22 +26,22 @@ else
Q :=
endif
-CC := gcc
+HOSTCC := gcc
.PHONY: all clean distclean
all: ${PROJECT}
${PROJECT}: ${OBJECTS} Makefile
- @echo " LD $@"
- ${Q}${CC} ${OBJECTS} -o $@
+ @echo " HOSTLD $@"
+ ${Q}${HOSTCC} ${OBJECTS} -o $@
@${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@${ECHO_BLANK_LINE}
-%.o: %.c %.h Makefile
- @echo " CC $<"
- ${Q}${CC} -c ${CFLAGS} $< -o $@
+%.o: %.c Makefile
+ @echo " HOSTCC $<"
+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@
clean:
$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
diff --git a/tools/stm32image/stm32image.c b/tools/stm32image/stm32image.c
index 2607928..41024e2 100644
--- a/tools/stm32image/stm32image.c
+++ b/tools/stm32image/stm32image.c
@@ -22,7 +22,7 @@
#define VER_MINOR 1
#define VER_VARIANT 0
#define HEADER_VERSION_V1 0x1
-#define TF_BINARY_TYPE 0x0
+#define TF_BINARY_TYPE 0x10
/* Default option : bit0 => no signature */
#define HEADER_DEFAULT_OPTION (__cpu_to_le32(0x00000001))
--
2.7.4