diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c index b0314d2ab..6069e5fb7 100644 --- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -99,7 +99,7 @@ static io_mtd_dev_spec_t spi_nand_dev_spec = { static const io_dev_connector_t *spi_dev_con; #endif -#if STM32MP_USB_PROGRAMMER +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER static const io_dev_connector_t *memmap_dev_con; #endif @@ -136,6 +136,9 @@ static void print_boot_device(boot_api_context_t *boot_context) case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: INFO("Using SPI NAND\n"); break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + INFO("Using UART\n"); + break; case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: INFO("Using USB\n"); break; @@ -257,7 +260,7 @@ static void boot_spi_nand(boot_api_context_t *boot_context) } #endif /* STM32MP_SPI_NAND */ -#if STM32MP_USB_PROGRAMMER +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER static void mmap_io_setup(void) { int io_result __unused; @@ -270,6 +273,21 @@ static void mmap_io_setup(void) assert(io_result == 0); } +#if STM32MP_UART_PROGRAMMER +static void stm32cubeprogrammer_uart(void) +{ + int ret __unused; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + uintptr_t uart_base; + + uart_base = get_uart_address(boot_context->boot_interface_instance); + ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE); + assert(ret == 0); +} +#endif + +#if STM32MP_USB_PROGRAMMER static void stm32cubeprogrammer_usb(void) { int ret __unused; @@ -282,6 +300,8 @@ static void stm32cubeprogrammer_usb(void) assert(ret == 0); } #endif +#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ + void stm32mp_io_setup(void) { @@ -334,8 +354,13 @@ void stm32mp_io_setup(void) boot_spi_nand(boot_context); break; #endif +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: +#endif #if STM32MP_USB_PROGRAMMER case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: +#endif dmbsy(); mmap_io_setup(); break; @@ -400,6 +425,16 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id) break; #endif +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + if (image_id == FW_CONFIG_ID) { + stm32cubeprogrammer_uart(); + /* FIP loaded at DWL address */ + image_block_spec.offset = DWL_BUFFER_BASE; + image_block_spec.length = DWL_BUFFER_SIZE; + } + break; +#endif #if STM32MP_USB_PROGRAMMER case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: if (image_id == FW_CONFIG_ID) { diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 8a5fe48ad..6183964c0 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -48,6 +48,11 @@ uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst); uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags); #endif +#if STM32MP_UART_PROGRAMMER +/* Get the UART address from its instance number */ +uintptr_t get_uart_address(uint32_t instance_nb); +#endif + /* * Platform util functions for the GPIO driver * @bank: Target GPIO bank ID as per DT bindings diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 7eaf0ed98..218f28d12 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -493,12 +493,13 @@ void bl2_el3_plat_prepare_exit(void) uint16_t boot_itf = stm32mp_get_boot_itf_selected(); switch (boot_itf) { -#if STM32MP_USB_PROGRAMMER +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: /* Invalidate the downloaded buffer used with io_memmap */ inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE); break; -#endif +#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ default: /* Do nothing in default case */ break; diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h index 52b1d1aa0..198ffa9bb 100644 --- a/plat/st/stm32mp1/include/boot_api.h +++ b/plat/st/stm32mp1/include/boot_api.h @@ -39,6 +39,9 @@ /* 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 diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index badc926c0..2a4ab7835 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -55,6 +55,7 @@ STM32MP_EMMC_BOOT ?= 0 # Serial boot devices STM32MP_USB_PROGRAMMER ?= 0 +STM32MP_UART_PROGRAMMER ?= 0 # Device tree DTB_FILE_NAME ?= stm32mp157c-ev1.dtb @@ -130,6 +131,7 @@ $(eval $(call assert_booleans,\ STM32MP_SPI_NOR \ STM32MP_EMMC_BOOT \ PLAT_XLAT_TABLES_DYNAMIC \ + STM32MP_UART_PROGRAMMER \ STM32MP_USB_PROGRAMMER \ STM32MP_USE_STM32IMAGE \ ))) @@ -138,10 +140,12 @@ $(eval $(call assert_numerics,\ $(sort \ STM32_TF_A_COPIES \ PLAT_PARTITION_MAX_ENTRIES \ + STM32_TF_VERSION \ ))) $(eval $(call add_defines,\ $(sort \ + STM32_TF_VERSION \ STM32MP_EMMC \ STM32MP_SDMMC \ STM32MP_RAW_NAND \ @@ -151,6 +155,7 @@ $(eval $(call add_defines,\ PLAT_XLAT_TABLES_DYNAMIC \ STM32_TF_A_COPIES \ PLAT_PARTITION_MAX_ENTRIES \ + STM32MP_UART_PROGRAMMER \ STM32MP_USB_PROGRAMMER \ STM32MP_USE_STM32IMAGE \ ))) @@ -260,11 +265,19 @@ ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c endif +ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),) +BL2_SOURCES += drivers/io/io_memmap.c +endif + +ifeq (${STM32MP_UART_PROGRAMMER},1) +BL2_SOURCES += drivers/st/uart/stm32_uart.c \ + plat/st/common/stm32cubeprogrammer_uart.c +endif + ifeq (${STM32MP_USB_PROGRAMMER},1) #The DFU stack uses only one end point, reduce the USB stack footprint $(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U)) -BL2_SOURCES += drivers/io/io_memmap.c \ - drivers/st/usb/stm32mp1_usb.c \ +BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \ drivers/usb/usb_device.c \ plat/st/common/stm32cubeprogrammer_usb.c \ plat/st/common/usb_dfu.c \ @@ -295,6 +308,7 @@ check_boot_device: [ ${STM32MP_RAW_NAND} != 1 ] && \ [ ${STM32MP_SPI_NAND} != 1 ] && \ [ ${STM32MP_SPI_NOR} != 1 ] && \ + [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \ [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \ echo "No boot device driver is enabled"; \ false; \ diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index e4065c1c9..0165cfedf 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -153,6 +153,32 @@ int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank) } } +#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 == 0U) || + (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) { + return 0U; + } + + return stm32mp1_uart_addresses[instance_nb - 1U]; +} +#endif + uint32_t stm32mp_get_chip_version(void) { uint32_t version = 0U;