diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml index cfe2b7bf06b2..4bbb0cfe33f4 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml @@ -23,6 +23,7 @@ supported: - watchdog - adc - dac + - qspi - dma ram: 96 flash: 1024 diff --git a/boards/arm/stm32h747i_disco/doc/index.rst b/boards/arm/stm32h747i_disco/doc/index.rst index d8c670aae52f..2f8d543d4464 100644 --- a/boards/arm/stm32h747i_disco/doc/index.rst +++ b/boards/arm/stm32h747i_disco/doc/index.rst @@ -27,6 +27,7 @@ Additionally, the board features: - USB OTG HS - Stereo speaker outputs - ST-MEMS digital microphones +- 2 x 512-Mbit QUAD-SPI NOR Flash memory - 256-Mbit SDRAM - 4 color user LEDs - 1 user and reset push-button @@ -71,6 +72,8 @@ The current Zephyr stm32h747i_disco board configuration supports the following h +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ | SDMMC | on-chip | disk access | +-----------+------------+-------------------------------------+ | IPM | on-chip | virtual mailbox based on HSEM | diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts index fb3e4972b282..6104a7c17659 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts @@ -19,6 +19,7 @@ zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &mt25ql512ab1; }; sdram2: sdram@d0000000 { @@ -53,6 +54,7 @@ led0 = &green_led_1; led1 = &orange_led_2; sw0 = &wake_up; + spi-flash0 = &mt25ql512ab1; }; }; @@ -206,4 +208,41 @@ zephyr_udc0: &usbotg_hs { cd-gpios = <&gpioi 8 GPIO_ACTIVE_LOW>; }; +&quadspi { + pinctrl-0 = <&quadspi_clk_pb2 &quadspi_bk1_ncs_pg6 + &quadspi_bk1_io0_pd11 &quadspi_bk1_io1_pf9 + &quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6 + &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 + &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; + pinctrl-names = "default"; + status = "okay"; + + mt25ql512ab1: qspi-nor-flash-1@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <72000000>; + size = ; /* 64 MBytes */ + spi-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 DT_SIZE_M(64)>; + }; + }; + }; + + mt25ql512ab2: qspi-nor-flash-2@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <72000000>; + size = ; /* 64 MBytes */ + status = "okay"; + }; +}; + arduino_spi: &spi5 {}; diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml index 93939e9f8305..fb67ae1e3988 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml @@ -14,6 +14,7 @@ supported: - arduino_spi - spi - netif:eth + - qspi - memc - usb_cdc - usb_device diff --git a/boards/arm/stm32l496g_disco/doc/index.rst b/boards/arm/stm32l496g_disco/doc/index.rst index a469a84823cd..681969f08afc 100644 --- a/boards/arm/stm32l496g_disco/doc/index.rst +++ b/boards/arm/stm32l496g_disco/doc/index.rst @@ -142,6 +142,8 @@ The Zephyr stm32l496g_disco board configuration supports the following hardware +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ | PWM | on-chip | pwm | +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts index fba2c2a8da02..95453135ee44 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts @@ -18,6 +18,7 @@ zephyr,shell-uart = &usart2; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &mx25r6435; }; leds { @@ -61,6 +62,7 @@ sw4 = &joy_left; volt-sensor0 = &vref; volt-sensor1 = &vbat; + spi-flash0 = &mx25r6435; }; }; @@ -174,3 +176,30 @@ zephyr_udc0: &usbotg_fs { &vbat { status = "okay"; }; + +&dma2 { + status = "okay"; +}; + +&quadspi { + pinctrl-0 = <&quadspi_bk1_io0_pb1 &quadspi_bk1_io1_pb0 + &quadspi_bk1_io2_pa7 &quadspi_bk1_io3_pa6 + &quadspi_bk1_ncs_pb11 &quadspi_clk_pa3>; + pinctrl-names = "default"; + + dmas = <&dma2 7 3 0x480>; /* channel 7 request 3 on DMA2 */ + dma-names = "tx_rx"; + + flash-id = <1>; + status = "okay"; + + mx25r6435: qspi-nor-flash@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <8000000>; + size = ; /* 8 MBytes */ + status = "okay"; + spi-bus-width = <4>; + writeoc = "PP_1_4_4"; + }; +}; diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml index be69f323831a..edf64edc3a45 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml @@ -17,3 +17,4 @@ supported: - counter - sdhc - adc + - qspi diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index e9f26a94780b..74ea8bab7c7a 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -91,6 +91,9 @@ struct flash_stm32_qspi_config { #if STM32_QSPI_RESET_GPIO const struct gpio_dt_spec reset; #endif +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_qspi_nor), jedec_id) + uint8_t jedec_id[DT_INST_PROP_LEN(0, jedec_id)]; +#endif /* jedec_id */ }; struct flash_stm32_qspi_data { @@ -284,12 +287,57 @@ static int qspi_write_access(const struct device *dev, QSPI_CommandTypeDef *cmd, return dev_data->cmd_status; } +#if defined(CONFIG_FLASH_JESD216_API) +/* + * Read Serial Flash ID : + * perform a read access over SPI bus for read Identification (DataMode is already set) + * and compare to the jedec-id from the DTYS table exists + */ +static int qspi_read_jedec_id(const struct device *dev, uint8_t *id) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + uint8_t data[JESD216_READ_ID_LEN]; + + QSPI_CommandTypeDef cmd = { + .Instruction = JESD216_CMD_READ_ID, + .AddressSize = QSPI_ADDRESS_NONE, + .DummyCycles = 8, + .InstructionMode = QSPI_INSTRUCTION_1_LINE, + .AddressMode = QSPI_ADDRESS_1_LINE, + .DataMode = QSPI_DATA_1_LINE, + .NbData = JESD216_READ_ID_LEN, + }; + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_QSPI_Command_IT(&dev_data->hqspi, &cmd); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send OSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_QSPI_Receive(&dev_data->hqspi, data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + dev_data->cmd_status = 0; + id = &data[0]; + + return 0; +} +#endif /* CONFIG_FLASH_JESD216_API */ + /* * Read Serial Flash Discovery Parameter */ -static int qspi_read_sfdp(const struct device *dev, off_t addr, uint8_t *data, +static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, size_t size) { + __ASSERT(data != NULL, "null destination"); + QSPI_CommandTypeDef cmd = { .Instruction = JESD216_CMD_READ_SFDP, .Address = addr, @@ -300,7 +348,7 @@ static int qspi_read_sfdp(const struct device *dev, off_t addr, uint8_t *data, .DataMode = QSPI_DATA_1_LINE, }; - return qspi_read_access(dev, &cmd, data, size); + return qspi_read_access(dev, &cmd, (uint8_t *)data, size); } static bool qspi_address_is_valid(const struct device *dev, off_t addr, @@ -666,6 +714,10 @@ static const struct flash_driver_api flash_stm32_qspi_driver_api = { #if defined(CONFIG_FLASH_PAGE_LAYOUT) .page_layout = flash_stm32_qspi_pages_layout, #endif +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = qspi_read_sfdp, + .read_jedec_id = qspi_read_jedec_id, +#endif /* CONFIG_FLASH_JESD216_API */ }; #if defined(CONFIG_FLASH_PAGE_LAYOUT) @@ -1346,6 +1398,9 @@ static const struct flash_stm32_qspi_config flash_stm32_qspi_cfg = { #if STM32_QSPI_RESET_GPIO .reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios), #endif +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_qspi_nor), jedec_id) + .jedec_id = DT_INST_PROP(0, jedec_id), +#endif /* jedec_id */ }; static struct flash_stm32_qspi_data flash_stm32_qspi_dev_data = { diff --git a/samples/drivers/jesd216/boards/disco_l475_iot1.conf b/samples/drivers/jesd216/boards/disco_l475_iot1.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/disco_l475_iot1.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf b/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32l496g_disco.conf b/samples/drivers/jesd216/boards/stm32l496g_disco.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/stm32l496g_disco.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 7675e25e776e..059dc7d5a274 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -26,7 +26,7 @@ #endif #define SPI_FLASH_SECTOR_SIZE 4096 -#if defined CONFIG_FLASH_STM32_OSPI +#if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif