From d8e8fa304aa54d7444adb26579b3acd902abfac0 Mon Sep 17 00:00:00 2001 From: Hanan Arshad Date: Mon, 16 Jun 2025 11:50:39 +0500 Subject: [PATCH 1/3] drivers: flash: rpi_pico: add support for rp2350 flash controller The Raspberry Pi Pico 2 uses a QMI flash controller, which differs from the SSI controller used in the original Pico. Zephyr already has support for the SSI controller, but lacked support for QMI. This change adds the QMI flash controller implementation in the flash_rpi_pico.c driver file. Additionally, the RP2350 SoC devicetree file (rp2350.dtsi) has been updated to enable and describe the flash controller for Pico 2. Signed-off-by: Hanan Arshad --- boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi | 1 + drivers/flash/flash_rpi_pico.c | 155 -------------------- dts/arm/raspberrypi/rpi_pico/rp2350.dtsi | 3 +- 3 files changed, 2 insertions(+), 157 deletions(-) diff --git a/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi b/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi index 522413c94f1a..85defeb758c8 100644 --- a/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi +++ b/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi @@ -16,6 +16,7 @@ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &qmi; zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,code-partition = &code_partition; diff --git a/drivers/flash/flash_rpi_pico.c b/drivers/flash/flash_rpi_pico.c index de86ea7cdd70..fe7c7c4113b7 100644 --- a/drivers/flash/flash_rpi_pico.c +++ b/drivers/flash/flash_rpi_pico.c @@ -13,15 +13,8 @@ #include #include #include -#include #include -#include -#include -#include -#include -#include -#include LOG_MODULE_REGISTER(flash_rpi_pico, CONFIG_FLASH_LOG_LEVEL); @@ -31,162 +24,14 @@ LOG_MODULE_REGISTER(flash_rpi_pico, CONFIG_FLASH_LOG_LEVEL); #define SECTOR_SIZE DT_PROP(DT_CHOSEN(zephyr_flash), erase_block_size) #define ERASE_VALUE 0xff #define FLASH_SIZE KB(CONFIG_FLASH_SIZE) -#define FLASH_BASE CONFIG_FLASH_BASE_ADDRESS -#define SSI_BASE_ADDRESS DT_REG_ADDR(DT_CHOSEN(zephyr_flash_controller)) static const struct flash_parameters flash_rpi_parameters = { .write_block_size = 1, .erase_value = ERASE_VALUE, }; -/** - * Low level flash functions are based on: - * github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c - * and - * github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_flash/flash.c - */ - -#define FLASHCMD_PAGE_PROGRAM 0x02 -#define FLASHCMD_READ_STATUS 0x05 -#define FLASHCMD_WRITE_ENABLE 0x06 -#define BOOT2_SIZE_WORDS 64 - -enum outover { - OUTOVER_NORMAL = 0, - OUTOVER_INVERT, - OUTOVER_LOW, - OUTOVER_HIGH -}; - -static ssi_hw_t *const ssi = (ssi_hw_t *)SSI_BASE_ADDRESS; -static uint32_t boot2_copyout[BOOT2_SIZE_WORDS]; -static bool boot2_copyout_valid; static uint8_t flash_ram_buffer[PAGE_SIZE]; -static void __no_inline_not_in_flash_func(flash_init_boot2_copyout)(void) -{ - if (boot2_copyout_valid) { - return; - } - for (int i = 0; i < BOOT2_SIZE_WORDS; ++i) { - boot2_copyout[i] = ((uint32_t *)FLASH_BASE)[i]; - } - __compiler_memory_barrier(); - boot2_copyout_valid = true; -} - -static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) -{ - ((void (*)(void))((uint32_t)boot2_copyout+1))(); -} - -void __no_inline_not_in_flash_func(flash_cs_force)(enum outover over) -{ - io_rw_32 *reg = (io_rw_32 *) (IO_QSPI_BASE + IO_QSPI_GPIO_QSPI_SS_CTRL_OFFSET); - *reg = (*reg & ~IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS) - | (over << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB); - (void) *reg; -} - -int __no_inline_not_in_flash_func(flash_was_aborted)() -{ - return *(io_rw_32 *) (IO_QSPI_BASE + IO_QSPI_GPIO_QSPI_SD1_CTRL_OFFSET) - & IO_QSPI_GPIO_QSPI_SD1_CTRL_INOVER_BITS; -} - -void __no_inline_not_in_flash_func(flash_put_get)(const uint8_t *tx, uint8_t *rx, size_t count, - size_t rx_skip) -{ - const uint max_in_flight = 16 - 2; - size_t tx_count = count; - size_t rx_count = count; - bool did_something; - uint32_t tx_level; - uint32_t rx_level; - uint8_t rxbyte; - - while (tx_count || rx_skip || rx_count) { - tx_level = ssi_hw->txflr; - rx_level = ssi_hw->rxflr; - did_something = false; - if (tx_count && tx_level + rx_level < max_in_flight) { - ssi->dr0 = (uint32_t) (tx ? *tx++ : 0); - --tx_count; - did_something = true; - } - if (rx_level) { - rxbyte = ssi->dr0; - did_something = true; - if (rx_skip) { - --rx_skip; - } else { - if (rx) { - *rx++ = rxbyte; - } - --rx_count; - } - } - - if (!did_something && __builtin_expect(flash_was_aborted(), 0)) { - break; - } - } - flash_cs_force(OUTOVER_HIGH); -} - -void __no_inline_not_in_flash_func(flash_put_get_wrapper)(uint8_t cmd, const uint8_t *tx, - uint8_t *rx, size_t count) -{ - flash_cs_force(OUTOVER_LOW); - ssi->dr0 = cmd; - flash_put_get(tx, rx, count, 1); -} - -static ALWAYS_INLINE void flash_put_cmd_addr(uint8_t cmd, uint32_t addr) -{ - flash_cs_force(OUTOVER_LOW); - addr |= cmd << 24; - for (int i = 0; i < 4; ++i) { - ssi->dr0 = addr >> 24; - addr <<= 8; - } -} - -void __no_inline_not_in_flash_func(flash_write_partial_internal)(uint32_t addr, const uint8_t *data, - size_t size) -{ - uint8_t status_reg; - - flash_put_get_wrapper(FLASHCMD_WRITE_ENABLE, NULL, NULL, 0); - flash_put_cmd_addr(FLASHCMD_PAGE_PROGRAM, addr); - flash_put_get(data, NULL, size, 4); - - do { - flash_put_get_wrapper(FLASHCMD_READ_STATUS, NULL, &status_reg, 1); - } while (status_reg & 0x1 && !flash_was_aborted()); -} - -void __no_inline_not_in_flash_func(flash_write_partial)(uint32_t flash_offs, const uint8_t *data, - size_t count) -{ - rom_connect_internal_flash_fn connect_internal_flash = (rom_connect_internal_flash_fn) - rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH); - rom_flash_exit_xip_fn exit_xip = (rom_flash_exit_xip_fn) - rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP); - rom_flash_flush_cache_fn flush_cache = (rom_flash_flush_cache_fn) - rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE); - - flash_init_boot2_copyout(); - - __compiler_memory_barrier(); - - connect_internal_flash(); - exit_xip(); - flash_write_partial_internal(flash_offs, data, count); - flush_cache(); - flash_enable_xip_via_boot2(); -} - static bool is_valid_range(off_t offset, uint32_t size) { return (offset >= 0) && ((offset + size) <= FLASH_SIZE); diff --git a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi index 62da179b6679..65553e401b01 100644 --- a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi +++ b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi @@ -192,7 +192,7 @@ qmi: flash-controller@400d0000 { compatible = "raspberrypi,pico-flash-controller"; - reg = <0x400d0000 0xfc>; + reg = <0x400d0000 0x54>; #address-cells = <1>; #size-cells = <1>; @@ -202,7 +202,6 @@ write-block-size = <1>; erase-block-size = ; }; - status = "disabled"; }; reset: reset-controller@40020000 { From bae535ea27bc2a966a7320049377426d0cbe0a72 Mon Sep 17 00:00:00 2001 From: Hanan Arshad Date: Mon, 16 Jun 2025 11:50:50 +0500 Subject: [PATCH 2/3] drivers: flash: flash_rpi_pico: fix indentation and remove unused variables Cleaned up the flash_rpi_pico driver to improve code readability and compliance with Zephyr coding standards. Fixed inconsistent indentation across the file and removed variables that were declared but not used. A few improvements are credited to Manu3l0us. Signed-off-by: Hanan Arshad --- drivers/flash/flash_rpi_pico.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/flash/flash_rpi_pico.c b/drivers/flash/flash_rpi_pico.c index fe7c7c4113b7..527fc5bf78f0 100644 --- a/drivers/flash/flash_rpi_pico.c +++ b/drivers/flash/flash_rpi_pico.c @@ -20,10 +20,10 @@ LOG_MODULE_REGISTER(flash_rpi_pico, CONFIG_FLASH_LOG_LEVEL); #define DT_DRV_COMPAT raspberrypi_pico_flash_controller -#define PAGE_SIZE 256 +#define PAGE_SIZE 256 #define SECTOR_SIZE DT_PROP(DT_CHOSEN(zephyr_flash), erase_block_size) #define ERASE_VALUE 0xff -#define FLASH_SIZE KB(CONFIG_FLASH_SIZE) +#define FLASH_SIZE KB(CONFIG_FLASH_SIZE) static const struct flash_parameters flash_rpi_parameters = { .write_block_size = 1, @@ -39,6 +39,8 @@ static bool is_valid_range(off_t offset, uint32_t size) static int flash_rpi_read(const struct device *dev, off_t offset, void *data, size_t size) { + ARG_UNUSED(dev); + if (size == 0) { return 0; } @@ -59,13 +61,15 @@ static int flash_rpi_write(const struct device *dev, off_t offset, const void *d size_t bytes_to_write; uint8_t *data_pointer = (uint8_t *)data; + ARG_UNUSED(dev); + if (size == 0) { return 0; } if (!is_valid_range(offset, size)) { - LOG_ERR("Write range exceeds the flash boundaries. Offset=%#lx, Size=%u", - offset, size); + LOG_ERR("Write range exceeds the flash boundaries. Offset=%#lx, Size=%u", offset, + size); return -EINVAL; } @@ -108,14 +112,14 @@ static int flash_rpi_erase(const struct device *dev, off_t offset, size_t size) } if (!is_valid_range(offset, size)) { - LOG_ERR("Erase range exceeds the flash boundaries. Offset=%#lx, Size=%u", - offset, size); + LOG_ERR("Erase range exceeds the flash boundaries. Offset=%#lx, Size=%u", offset, + size); return -EINVAL; } if ((offset % SECTOR_SIZE) || (size % SECTOR_SIZE)) { LOG_ERR("Erase range is not a multiple of the sector size. Offset=%#lx, Size=%u", - offset, size); + offset, size); return -EINVAL; } @@ -143,7 +147,7 @@ static const struct flash_pages_layout flash_rpi_pages_layout = { }; void flash_rpi_page_layout(const struct device *dev, const struct flash_pages_layout **layout, - size_t *layout_size) + size_t *layout_size) { *layout = &flash_rpi_pages_layout; *layout_size = 1; @@ -161,5 +165,5 @@ static DEVICE_API(flash, flash_rpi_driver_api) = { #endif /* CONFIG_FLASH_PAGE_LAYOUT */ }; -DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, - CONFIG_FLASH_INIT_PRIORITY, &flash_rpi_driver_api); +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, + &flash_rpi_driver_api); From 63fc23a00e16b8ff210a9e3a19447a7a471eedc3 Mon Sep 17 00:00:00 2001 From: Hanan Arshad Date: Mon, 16 Jun 2025 11:50:57 +0500 Subject: [PATCH 3/3] manifest: hal_rpi_pico: Pull partial flash write changes from hal_rpi_pico This commit links the hal_rpi_pico PR required for the flash driver. west.yml is updated Signed-off-by: Hanan Arshad --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 3c57f452369a..ace97a69a748 100644 --- a/west.yml +++ b/west.yml @@ -231,7 +231,7 @@ manifest: - hal - name: hal_rpi_pico path: modules/hal/rpi_pico - revision: 7b57b24588797e6e7bf18b6bda168e6b96374264 + revision: 5a981c7c29e3846646549a1902183684f0147e1d groups: - hal - name: hal_silabs