diff --git a/boards/renesas/ek_ra8d1/doc/index.rst b/boards/renesas/ek_ra8d1/doc/index.rst index 183ed37acbdb..196c6239c48d 100644 --- a/boards/renesas/ek_ra8d1/doc/index.rst +++ b/boards/renesas/ek_ra8d1/doc/index.rst @@ -123,6 +123,8 @@ The below features are currently supported on Zephyr OS for EK-RA8D1 board: +--------------+------------+-----------------------------------+ | SDHC | on-chip | sdhc | +--------------+------------+-----------------------------------+ +| OSPI | on-chip | ospi flash | ++--------------+------------+-----------------------------------+ **Note:** diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi index b4d3168b9033..377598ed4a66 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi @@ -261,4 +261,22 @@ drive-strength = "highspeed-high"; }; }; + + ospi0_default: ospi0_default { + group1 { + /* sclk dqs sio0-7 */ + psels = , , + , , + , , + , , + , ; + drive-strength = "highspeed-high"; + }; + group2 { + /* cs1 rst ecsint1 */ + psels = , , + ; + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1.dts b/boards/renesas/ek_ra8d1/ek_ra8d1.dts index a89c31f09404..984cf03fc0a2 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1.dts +++ b/boards/renesas/ek_ra8d1/ek_ra8d1.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include #include #include @@ -111,6 +112,17 @@ }; }; +&pll2 { + status = "okay"; + clocks = <&xtal>; + div = <2>; + mul = <80 0>; + pll2p { + status = "okay"; + freq = ; + div = <2>; + }; +}; &sciclk { clocks = <&pllp>; @@ -130,6 +142,12 @@ status = "okay"; }; +&octaspiclk { + clocks = <&pll2p>; + div = <2>; + status = "okay"; +}; + &ioport0 { status = "okay"; }; @@ -300,3 +318,43 @@ zephyr_mipi_dsi: &mipi_dsi {}; renesas_mipi_i2c: &iic1{}; pmod_sd_shield: &sdhc1 {}; + +&ospi0 { + pinctrl-0 = <&ospi0_default>; + pinctrl-names = "default"; + status = "okay"; + s28hl512t: s28hl512t@90000000 { + compatible = "renesas,ra-ospi-b-nor"; + protocol-mode = ; + data-rate = ; + ospi-max-frequency = ; + reg = <0x90000000 DT_SIZE_M(64)>; + write-block-size = <1>; + pages_layout: pages_layout { + pages_layout_4k: pages_layout_4k { + pages-count = <32>; + pages-size = ; + }; + pages_layout_128k: pages_layout_128k { + pages-count = <1>; + pages-size = ; + }; + pages_layout_256k: pages_layout_256k { + pages-count = <255>; + pages-size = ; + }; + }; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "nor"; + reg = <0x00000000 DT_SIZE_M(64)>; + }; + }; + }; +}; diff --git a/boards/renesas/ek_ra8m1/doc/index.rst b/boards/renesas/ek_ra8m1/doc/index.rst index 55890ac3fcc2..745b13db56c9 100644 --- a/boards/renesas/ek_ra8m1/doc/index.rst +++ b/boards/renesas/ek_ra8m1/doc/index.rst @@ -120,6 +120,8 @@ The below features are currently supported on Zephyr OS for EK-RA8M1 board: +-----------+------------+----------------------+ | SDHC | on-chip | sdhc | +-----------+------------+----------------------+ +| OSPI | on-chip | ospi flash | ++-----------+------------+----------------------+ **Note:** diff --git a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi index f3c3ec3ebd9c..912b71d074e5 100644 --- a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi @@ -138,4 +138,22 @@ drive-strength = "highspeed-high"; }; }; + + ospi0_default: ospi0_default { + group1 { + /* sclk dqs sio0-7 */ + psels = , , + , , + , , + , , + , ; + drive-strength = "highspeed-high"; + }; + group2 { + /* cs1 rst ecsint1 */ + psels = , , + ; + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/ek_ra8m1/ek_ra8m1.dts b/boards/renesas/ek_ra8m1/ek_ra8m1.dts index 96e952cd0990..d7b8f2eab999 100644 --- a/boards/renesas/ek_ra8m1/ek_ra8m1.dts +++ b/boards/renesas/ek_ra8m1/ek_ra8m1.dts @@ -7,6 +7,7 @@ #include #include +#include #include #include #include "ek_ra8m1-pinctrl.dtsi" @@ -148,6 +149,17 @@ }; }; +&pll2 { + status = "okay"; + clocks = <&xtal>; + div = <2>; + mul = <80 0>; + pll2p { + status = "okay"; + freq = ; + div = <2>; + }; +}; &sciclk { clocks = <&pllp>; @@ -161,6 +173,12 @@ status = "okay"; }; +&octaspiclk { + clocks = <&pll2p>; + div = <2>; + status = "okay"; +}; + &ioport0 { status = "okay"; }; @@ -349,3 +367,43 @@ pmod_header: &pmod1_header {}; }; pmod_sd_shield: &sdhc0 {}; + +&ospi0 { + pinctrl-0 = <&ospi0_default>; + pinctrl-names = "default"; + status = "okay"; + s28hl512t: s28hl512t@90000000 { + compatible = "renesas,ra-ospi-b-nor"; + protocol-mode = ; + data-rate = ; + ospi-max-frequency = ; + reg = <0x90000000 DT_SIZE_M(64)>; + write-block-size = <1>; + pages_layout: pages_layout { + pages_layout_4k: pages_layout_4k { + pages-count = <32>; + pages-size = ; + }; + pages_layout_128k: pages_layout_128k { + pages-count = <1>; + pages-size = ; + }; + pages_layout_256k: pages_layout_256k { + pages-count = <255>; + pages-size = ; + }; + }; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "nor"; + reg = <0x00000000 DT_SIZE_M(64)>; + }; + }; + }; +}; diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 617f1422a90d..77464566be98 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -158,3 +158,4 @@ if(CONFIG_RA_FLASH_HP) zephyr_library_sources(flash_hp_ra.c) zephyr_library_sources_ifdef(CONFIG_FLASH_EX_OP_ENABLED flash_hp_ra_ex_op.c) endif() +zephyr_library_sources_ifdef(CONFIG_FLASH_OSPI_B_RENESAS_RA flash_renesas_ra_ospi_b.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index bc9f6e69d7e3..4553455639ba 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -191,6 +191,7 @@ source "drivers/flash/Kconfig.numaker" source "drivers/flash/Kconfig.numaker_rmc" source "drivers/flash/Kconfig.nxp_s32" source "drivers/flash/Kconfig.renesas_ra" +source "drivers/flash/Kconfig.renesas_ra_flash_ospi_b" source "drivers/flash/Kconfig.rpi_pico" source "drivers/flash/Kconfig.rv32m1" source "drivers/flash/Kconfig.sam" diff --git a/drivers/flash/Kconfig.renesas_ra_flash_ospi_b b/drivers/flash/Kconfig.renesas_ra_flash_ospi_b new file mode 100644 index 000000000000..ac02645e3ba8 --- /dev/null +++ b/drivers/flash/Kconfig.renesas_ra_flash_ospi_b @@ -0,0 +1,18 @@ +# Renesas RA Family + +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_OSPI_B_RENESAS_RA + bool "Renesas RA Octal-SPI driver" + default y + depends on DT_HAS_RENESAS_RA_OSPI_B_NOR_ENABLED + select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE + select USE_RA_FSP_OSPI_B_NOR_FLASH + select FLASH_JESD216 + select FLASH_HAS_EX_OP + select PINCTRL + help + Enable Octal-SPI Nor flash driver for RA series diff --git a/drivers/flash/flash_renesas_ra_ospi_b.c b/drivers/flash/flash_renesas_ra_ospi_b.c new file mode 100644 index 000000000000..09ba03c79929 --- /dev/null +++ b/drivers/flash/flash_renesas_ra_ospi_b.c @@ -0,0 +1,775 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_ospi_b_nor + +#include +#include +#include +#include +#include +#include +#include +#include "flash_renesas_ra_ospi_b.h" + +LOG_MODULE_REGISTER(flash_renesas_ra_ospi_b, CONFIG_FLASH_LOG_LEVEL); + +struct flash_renesas_ra_ospi_b_data { + ospi_b_instance_ctrl_t ospi_b_ctrl; + spi_flash_cfg_t ospi_b_cfg; + ospi_b_timing_setting_t ospi_b_timing_settings; + ospi_b_xspi_command_set_t ospi_b_high_speed_command_set; + ospi_b_extended_cfg_t ospi_b_config_extend; + struct k_sem sem; +}; + +struct flash_renesas_ra_ospi_b_config { + size_t flash_size; + int protocol; + int data_rate; + uint32_t max_frequency; + const struct device *clock_dev; + struct clock_control_ra_subsys_cfg clock_subsys; + const struct pinctrl_dev_config *pcfg; +}; + +static const struct flash_parameters ospi_b_ra_param = { + .write_block_size = DT_PROP(RA_OSPI_B_NOR_NODE, write_block_size), + .erase_value = ERASE_VALUE, +}; + +static void acquire_device(const struct device *dev) +{ + struct flash_renesas_ra_ospi_b_data *dev_data = dev->data; + + k_sem_take(&dev_data->sem, K_FOREVER); +} + +static void release_device(const struct device *dev) +{ + struct flash_renesas_ra_ospi_b_data *dev_data = dev->data; + + k_sem_give(&dev_data->sem); +} + +static fsp_err_t flash_renesas_ra_ospi_b_wait_operation(ospi_b_instance_ctrl_t *p_ctrl, + uint32_t timeout) +{ + fsp_err_t err = FSP_SUCCESS; + spi_flash_status_t status = {RESET_VALUE}; + + status.write_in_progress = true; + while (status.write_in_progress) { + /* Get device status */ + R_OSPI_B_StatusGet(p_ctrl, &status); + if (timeout == RESET_VALUE) { + LOG_ERR("Time out for operation"); + return FSP_ERR_TIMEOUT; + } + k_sleep(K_USEC(50)); + timeout--; + } + + return err; +} + +static fsp_err_t flash_renesas_ra_ospi_b_write_enable(ospi_b_instance_ctrl_t *p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + + /* Transfer write enable command */ + transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == p_ctrl->spi_protocol) + ? direct_transfer[TRANSFER_WRITE_ENABLE_SPI] + : direct_transfer[TRANSFER_WRITE_ENABLE_OSPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + if (err != FSP_SUCCESS) { + return err; + } + /* Read Status Register */ + transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == p_ctrl->spi_protocol) + ? direct_transfer[TRANSFER_READ_STATUS_SPI] + : direct_transfer[TRANSFER_READ_STATUS_OSPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + if (err != FSP_SUCCESS) { + return err; + } + + /* Check Write Enable bit in Status Register */ + if (SPI_NOR_WREN_MASK != (transfer.data & SPI_NOR_WREN_MASK)) { + LOG_ERR("Write enable failed"); + return FSP_ERR_ABORTED; + } + + return err; +} + +static fsp_err_t flash_renesas_ra_ospi_b_setup_calibrate_data(ospi_b_instance_ctrl_t *p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + uint32_t autocalibration_data[] = {0xFFFF0000U, 0x000800FFU, 0x00FFF700U, 0xF700F708U}; + + /* Verify auto-calibration data */ + if (memcmp((uint8_t *)APP_ADDRESS(SECTOR_THREE), &autocalibration_data, + sizeof(autocalibration_data)) != RESET_VALUE) { + /* Erase the flash sector that stores auto-calibration data */ + err = R_OSPI_B_Erase(p_ctrl, (uint8_t *)APP_ADDRESS(SECTOR_THREE), + SPI_NOR_SECTOR_SIZE); + if (err != FSP_SUCCESS) { + return err; + } + + /* Wait until erase operation completes */ + err = flash_renesas_ra_ospi_b_wait_operation(p_ctrl, TIME_ERASE_4K); + if (err != FSP_SUCCESS) { + return err; + } + + /* Write auto-calibration data to the flash */ + err = R_OSPI_B_Write(p_ctrl, (uint8_t *)&autocalibration_data, + (uint8_t *)APP_ADDRESS(SECTOR_THREE), + sizeof(autocalibration_data)); + if (err != FSP_SUCCESS) { + return err; + } + + /* Wait until write operation completes */ + err = flash_renesas_ra_ospi_b_wait_operation(p_ctrl, TIME_WRITE); + if (err != FSP_SUCCESS) { + return err; + } + } + + return err; +} + +static fsp_err_t flash_renesas_ra_ospi_b_spi_mode_init(ospi_b_instance_ctrl_t *p_ctrl, + spi_flash_cfg_t *p_cfg) +{ + /* By default, the flash device is in SPI mode, so it is necessary to open the OSPI module + * in SPI mode + */ + fsp_err_t err = FSP_SUCCESS; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + + /* Open OSPI module */ + err = R_OSPI_B_Open(p_ctrl, p_cfg); + + /* DDR sampling window extend */ + R_XSPI->LIOCFGCS_b[p_ctrl->channel].DDRSMPEX = 1; + + /* Switch OSPI module to 1S-1S-1S mode to configure flash device */ + err = R_OSPI_B_SpiProtocolSet(p_ctrl, SPI_FLASH_PROTOCOL_EXTENDED_SPI); + if (err != FSP_SUCCESS) { + return err; + } + + /* Reset flash device by driving OM_RESET pin */ + R_XSPI->LIOCTL_b.RSTCS0 = 0; + k_sleep(K_USEC(500)); + R_XSPI->LIOCTL_b.RSTCS0 = 1; + k_sleep(K_NSEC(50)); + + /* Transfer write enable command */ + err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); + if (err != FSP_SUCCESS) { + return err; + } + + /* Write to CFR2V to configure Address Byte Length and Memory Array Read Latency */ + transfer = direct_transfer[TRANSFER_WRITE_CFR2V_SPI]; + transfer.address_length = ADDRESS_LENGTH_THREE; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + if (err != FSP_SUCCESS) { + return err; + } + + /* Transfer write enable command */ + err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); + if (err != FSP_SUCCESS) { + return err; + } + + /* Write to CFR3V to configure Volatile Register Read Latency */ + transfer = direct_transfer[TRANSFER_WRITE_CFR3V_SPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + if (err != FSP_SUCCESS) { + return err; + } + + /* Read back and verify CFR2V register data */ + transfer = direct_transfer[TRANSFER_READ_CFR2V_SPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + if (err != FSP_SUCCESS) { + return err; + } + + if (DATA_CFR2V_REGISTER != (uint8_t)transfer.data) { + LOG_ERR("Verify CFR2V register data Failed"); + return FSP_ERR_ABORTED; + } + + /* Read back and verify CFR3V register data */ + transfer = direct_transfer[TRANSFER_READ_CFR3V_SPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + if (err != FSP_SUCCESS) { + return err; + } + + if (DATA_CFR3V_REGISTER != (uint8_t)transfer.data) { + LOG_ERR("Verify CFR3V register data Failed"); + return FSP_ERR_ABORTED; + } + + /* Setup calibrate data */ + err = flash_renesas_ra_ospi_b_setup_calibrate_data(p_ctrl); + if (err != FSP_SUCCESS) { + return err; + } + + return err; +} + +static fsp_err_t flash_renesas_ra_ospi_b_set_protocol_to_opi(ospi_b_instance_ctrl_t *p_ctrl, + const struct device *dev) +{ + fsp_err_t err = FSP_SUCCESS; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + + /* Transfer write enable command */ + err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); + if (err != FSP_SUCCESS) { + return err; + } + + /* Write to CFR5V Register to Configure flash device interface mode */ + transfer = direct_transfer[TRANSFER_WRITE_CFR5V_SPI]; + transfer.data = DATA_SET_OSPI_CFR5V_REGISTER; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + if (err != FSP_SUCCESS) { + return err; + } + + /* Switch OSPI module mode to OPI mode */ + err = R_OSPI_B_SpiProtocolSet(p_ctrl, SPI_FLASH_PROTOCOL_8D_8D_8D); + if (err != FSP_SUCCESS) { + return err; + } + + /* Read back and verify CFR5V register data */ + transfer = direct_transfer[TRANSFER_READ_CFR5V_OSPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + if (err != FSP_SUCCESS) { + return err; + } + + if (DATA_SET_OSPI_CFR5V_REGISTER != (uint8_t)transfer.data) { + LOG_ERR("Verify CFR5V register data Failed"); + return FSP_ERR_ABORTED; + } + + return err; +} + +static inline bool flash_renesas_ra_ospi_b_is_valid_address(const struct device *dev, off_t offset, + size_t len) +{ + const struct flash_renesas_ra_ospi_b_config *config = dev->config; + + return (offset >= 0 && (offset < (config->flash_size)) && + (len <= (config->flash_size - offset))); +} + +#if defined(CONFIG_FLASH_EX_OP_ENABLED) + +static int flash_renesas_ra_ospi_b_ex_op(const struct device *dev, uint16_t code, + const uintptr_t in, void *out) +{ + struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + int err = -ENOTSUP; + + ARG_UNUSED(in); + ARG_UNUSED(out); + + acquire_device(dev); + + if (code == FLASH_EX_OP_RESET) { + err = flash_renesas_ra_ospi_b_write_enable(&ospi_b_data->ospi_b_ctrl); + if (err == FSP_SUCCESS) { + /* Enable reset */ + transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == + ospi_b_data->ospi_b_ctrl.spi_protocol) + ? direct_transfer[TRANSFER_RESET_ENABLE_SPI] + : direct_transfer[TRANSFER_RESET_ENABLE_OSPI]; + err = R_OSPI_B_DirectTransfer(&ospi_b_data->ospi_b_ctrl, &transfer, + SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + } + + if (err == FSP_SUCCESS) { + /* Reset Register */ + transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == + ospi_b_data->ospi_b_ctrl.spi_protocol) + ? direct_transfer[TRANSFER_RESET_MEM_SPI] + : direct_transfer[TRANSFER_RESET_MEM_OSPI]; + err = R_OSPI_B_DirectTransfer(&ospi_b_data->ospi_b_ctrl, &transfer, + SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); + } + + if (err != FSP_SUCCESS) { + err = -EIO; + } + } + + release_device(dev); + + return err; +} +#endif + +#if CONFIG_FLASH_PAGE_LAYOUT + +#define SET_PAGES(node_id) \ + {.pages_count = DT_PROP(node_id, pages_count), .pages_size = DT_PROP(node_id, pages_size)}, + +static const struct flash_pages_layout ospi_b_flash_ra_layout[] = { + DT_FOREACH_CHILD(DT_NODELABEL(pages_layout), SET_PAGES)}; + +void flash_renesas_ra_ospi_b_page_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + ARG_UNUSED(dev); + *layout = ospi_b_flash_ra_layout; + *layout_size = ARRAY_SIZE(ospi_b_flash_ra_layout); +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +#if defined(CONFIG_FLASH_JESD216_API) + +static fsp_err_t flash_renesas_ra_ospi_b_read_device_id(ospi_b_instance_ctrl_t *p_ctrl, + uint8_t *const p_id) +{ + fsp_err_t err = FSP_SUCCESS; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + + /* Read and check flash device ID */ + transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == p_ctrl->spi_protocol) + ? direct_transfer[TRANSFER_READ_DEVICE_ID_SPI] + : direct_transfer[TRANSFER_READ_DEVICE_ID_OSPI]; + err = R_OSPI_B_DirectTransfer(p_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + if (err != FSP_SUCCESS) { + return err; + } + + /* Get flash device ID */ + memcpy(p_id, &transfer.data, sizeof(transfer.data)); + + return err; +} + +static int flash_renesas_ra_ospi_b_read_jedec_id(const struct device *dev, uint8_t *id) +{ + struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; + int err = 0; + + if (id == NULL) { + return -EINVAL; + } + + acquire_device(dev); + + err = flash_renesas_ra_ospi_b_read_device_id(&ospi_b_data->ospi_b_ctrl, id); + if (err) { + LOG_ERR("Failed to read jedec id"); + err = -EIO; + + } else { + LOG_INF("Manuf ID = %02x Memory Type = %02x Memory Density = %02x ID Length " + "= %02x\n", + id[0], id[1], id[2], id[3]); + } + + release_device(dev); + + return err; +} + +static int flash_renesas_ra_ospi_b_sfdp_read(const struct device *dev, off_t offset, void *data, + size_t len) +{ + struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; + spi_flash_direct_transfer_t transfer = {RESET_VALUE}; + uint64_t size; + uint8_t *p_src; + int err = 0; + + if (len == 0) { + return 0; + } + + if (data != NULL) { + p_src = data; + } else { + return -EINVAL; + } + + acquire_device(dev); + + if (ospi_b_data->ospi_b_ctrl.spi_protocol == SPI_FLASH_PROTOCOL_EXTENDED_SPI) { + transfer = direct_transfer[TRANSFER_READ_SFDP_ID_SPI]; + } else { + transfer = direct_transfer[TRANSFER_READ_SFDP_ID_OSPI]; + } + + while (len > 0) { + size = len > transfer.data_length ? transfer.data_length : len; + transfer.address = offset; + transfer.data_length = size; + + err = R_OSPI_B_DirectTransfer(&ospi_b_data->ospi_b_ctrl, &transfer, + SPI_FLASH_DIRECT_TRANSFER_DIR_READ); + + if (err) { + LOG_ERR("Failed to read SFDP id"); + release_device(dev); + return -EIO; + } + + memcpy(p_src, &transfer.data, size); + + len -= size; + offset += size; + p_src += size; + } + + release_device(dev); + + return err; +} +#endif + +static int flash_renesas_ra_ospi_b_erase(const struct device *dev, off_t offset, size_t len) +{ + struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; + const struct flash_renesas_ra_ospi_b_config *config = dev->config; + uint32_t erase_size, erase_timeout; + int err = 0; + struct flash_pages_info page_info_start, page_info_end; + int rc; + + if (!len) { + return 0; + } else if (len % SPI_NOR_SECTOR_SIZE != 0) { + LOG_ERR("Wrong sector size 0x%x", len); + return -EINVAL; + } + + if (!flash_renesas_ra_ospi_b_is_valid_address(dev, offset, len)) { + LOG_ERR("Address or size exceeds expected values: " + "addr 0x%lx, size %u", + (long)offset, len); + return -EINVAL; + } + + /* check offset and len that valid in sector layout */ + rc = flash_get_page_info_by_offs(dev, offset, &page_info_start); + if ((rc != 0) || (offset != page_info_start.start_offset)) { + LOG_ERR("The offset 0x%lx is not aligned with the starting sector", (long)offset); + return -EINVAL; + } + + rc = flash_get_page_info_by_offs(dev, (offset + len), &page_info_end); + + if ((rc != 0) || ((offset + len) != page_info_end.start_offset)) { + LOG_ERR("The size %u is not aligned with the ending sector", len); + return -EINVAL; + } + + acquire_device(dev); + + while (len > 0) { + if (offset == 0 && len == config->flash_size) { + /* Chip erase */ + LOG_INF("Chip Erase"); + + erase_size = SPI_FLASH_ERASE_SIZE_CHIP_ERASE; + erase_timeout = UINT32_MAX; + } else if ((offset) <= (off_t)(ospi_b_flash_ra_layout[0].pages_size * + (ospi_b_flash_ra_layout[0].pages_count))) { + erase_size = SPI_NOR_SECTOR_SIZE; + erase_timeout = TIME_ERASE_4K; + } else { + erase_size = SECTOR_SIZE_256K; + erase_timeout = TIME_ERASE_256K; + } + + err = R_OSPI_B_Erase( + &ospi_b_data->ospi_b_ctrl, + (uint8_t *)(BSP_FEATURE_OSPI_B_DEVICE_1_START_ADDRESS + offset), + erase_size); + if (err != FSP_SUCCESS) { + err = -EIO; + break; + } + + err = flash_renesas_ra_ospi_b_wait_operation(&ospi_b_data->ospi_b_ctrl, + erase_timeout); + if (err != FSP_SUCCESS) { + err = -EIO; + break; + } + + offset += erase_size; + len -= len < erase_size ? len : erase_size; + } + + release_device(dev); + + return err; +} + +static int flash_renesas_ra_ospi_b_read(const struct device *dev, off_t offset, void *data, + size_t len) +{ + + if (!len) { + return 0; + } + + if (!flash_renesas_ra_ospi_b_is_valid_address(dev, offset, len)) { + LOG_ERR("address or size exceeds expected values: " + "addr 0x%lx, size %zu", + (long)offset, len); + return -EINVAL; + } + + memcpy(data, (uint8_t *)(BSP_FEATURE_OSPI_B_DEVICE_1_START_ADDRESS) + offset, len); + + return 0; +} + +static int flash_renesas_ra_ospi_b_write(const struct device *dev, off_t offset, const void *data, + size_t len) +{ + struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; + int err = 0; + uint32_t size; + const uint8_t *p_src; + + if (!len) { + return 0; + } + + if (data != NULL) { + p_src = data; + } else { + return -EINVAL; + } + + if (!flash_renesas_ra_ospi_b_is_valid_address(dev, offset, len)) { + LOG_ERR("address or size exceeds expected values: " + "addr 0x%lx, size %zu", + (long)offset, len); + return -EINVAL; + } + + acquire_device(dev); + + while (len > 0) { + size = len > ospi_b_data->ospi_b_cfg.page_size_bytes + ? ospi_b_data->ospi_b_cfg.page_size_bytes + : len; + + err = R_OSPI_B_Write( + &ospi_b_data->ospi_b_ctrl, p_src, + (uint8_t *)(BSP_FEATURE_OSPI_B_DEVICE_1_START_ADDRESS + offset), size); + if (err != FSP_SUCCESS) { + err = -EIO; + break; + } + + err = flash_renesas_ra_ospi_b_wait_operation(&ospi_b_data->ospi_b_ctrl, TIME_WRITE); + if (err != FSP_SUCCESS) { + err = -EIO; + break; + } + + len -= size; + offset += size; + p_src = p_src + size; + } + + release_device(dev); + + return err; +} + +static const struct flash_parameters * +flash_renesas_ra_ospi_b_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &ospi_b_ra_param; +} + +static int flash_renesas_ra_ospi_b_get_size(const struct device *dev, uint64_t *size) +{ + const struct flash_renesas_ra_ospi_b_config *config = dev->config; + *size = (uint64_t)config->flash_size; + + return 0; +} + +static DEVICE_API(flash, flash_renesas_ra_ospi_b_api) = { + .erase = flash_renesas_ra_ospi_b_erase, + .write = flash_renesas_ra_ospi_b_write, + .read = flash_renesas_ra_ospi_b_read, + .get_parameters = flash_renesas_ra_ospi_b_get_parameters, + .get_size = flash_renesas_ra_ospi_b_get_size, +#ifdef CONFIG_FLASH_PAGE_LAYOUT + .page_layout = flash_renesas_ra_ospi_b_page_layout, +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = flash_renesas_ra_ospi_b_sfdp_read, + .read_jedec_id = flash_renesas_ra_ospi_b_read_jedec_id, +#endif /* CONFIG_FLASH_JESD216_API */ +#if defined(CONFIG_FLASH_EX_OP_ENABLED) + .ex_op = flash_renesas_ra_ospi_b_ex_op, +#endif /* CONFIG_FLASH_EX_OP_ENABLED */ +}; + +static int flash_renesas_ra_ospi_b_init(const struct device *dev) +{ + const struct flash_renesas_ra_ospi_b_config *config = dev->config; + struct flash_renesas_ra_ospi_b_data *data = dev->data; + uint32_t clock_freq; + int err = 0; + + /* protocol/data_rate of XSPI checking */ + if (config->protocol == XSPI_DUAL_MODE || config->protocol == XSPI_QUAD_MODE) { + LOG_ERR("XSPI mode DUAL|QUAD currently not support"); + return -ENOTSUP; + } else if (((config->protocol != XSPI_OCTO_MODE) && + (config->data_rate == XSPI_DTR_TRANSFER)) || + ((config->protocol == XSPI_OCTO_MODE) && + (config->data_rate == XSPI_STR_TRANSFER))) { + LOG_ERR("XSPI mode SPI/DTR or OPI/STR is not valid"); + return -ENOTSUP; + } + + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_subsys); + if (err < 0) { + LOG_ERR("Could not initialize clock (%d)", err); + return err; + } + + err = clock_control_get_rate(config->clock_dev, + (clock_control_subsys_t)&config->clock_subsys, &clock_freq); + + if (err) { + LOG_ERR("Failed to get clock frequency (%d)", err); + return err; + } + + if ((config->protocol == XSPI_SPI_MODE && (config->max_frequency / 2) < clock_freq) || + (config->protocol == XSPI_OCTO_MODE && (config->max_frequency) < clock_freq)) { + LOG_ERR("Invalid clock frequency (%u)", clock_freq); + return -EINVAL; + } + + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err) { + LOG_ERR("Failed to configure pins (%d)", err); + return err; + } + + k_sem_init(&data->sem, 1, 1); + + err = flash_renesas_ra_ospi_b_spi_mode_init(&data->ospi_b_ctrl, &data->ospi_b_cfg); + + if (err) { + LOG_ERR("Init SPI mode failed"); + return -EIO; + } + + if (config->protocol == XSPI_OCTO_MODE) { + err = flash_renesas_ra_ospi_b_set_protocol_to_opi(&data->ospi_b_ctrl, dev); + if (err) { + LOG_ERR("Init OPI mode failed"); + return -EIO; + } + } + + LOG_INF("Mode: %d Freq: %u", config->protocol, clock_freq); + + return err; +} + +PINCTRL_DT_DEFINE(DT_INST_PARENT(0)); +static const struct flash_renesas_ra_ospi_b_config ospi_b_config = { + .flash_size = DT_REG_SIZE(RA_OSPI_B_NOR_NODE), + .protocol = DT_PROP(RA_OSPI_B_NOR_NODE, protocol_mode), + .data_rate = DT_PROP(RA_OSPI_B_NOR_NODE, data_rate), + .max_frequency = DT_PROP(RA_OSPI_B_NOR_NODE, ospi_max_frequency), + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(0))), + .clock_subsys = {.mstp = (uint32_t)DT_CLOCKS_CELL(DT_INST_PARENT(0), mstp), + .stop_bit = (uint32_t)DT_CLOCKS_CELL(DT_INST_PARENT(0), stop_bit)}, + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(DT_INST_PARENT(0))}; + +static struct flash_renesas_ra_ospi_b_data ospi_b_data = { + .ospi_b_timing_settings = {.command_to_command_interval = OSPI_B_COMMAND_INTERVAL_CLOCKS_2, + .cs_pullup_lag = OSPI_B_COMMAND_CS_PULLUP_CLOCKS_NO_EXTENSION, + .cs_pulldown_lead = + OSPI_B_COMMAND_CS_PULLDOWN_CLOCKS_NO_EXTENSION}, + .ospi_b_high_speed_command_set = {.protocol = SPI_FLASH_PROTOCOL_8D_8D_8D, + .command_bytes = OSPI_B_COMMAND_BYTES_2, + .read_command = SPI_NOR_OCMD_READ, + .page_program_command = SPI_NOR_OCMD_PP_4B, + .write_enable_command = SPI_NOR_OCMD_WEN, + .status_command = SPI_NOR_OCMD_RSR, + .read_dummy_cycles = SPI_NOR_DUMMY_RD_MEM_OCTAL, + .program_dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL, + .status_dummy_cycles = SPI_NOR_DUMMY_RD_REG_OCTAL, + .p_erase_command_list = high_speed_erase_command_list, + .erase_command_list_length = ERASE_COMMAND_LENGTH( + high_speed_erase_command_list)}, + .ospi_b_config_extend = {.channel = OSPI_B_DEVICE_NUMBER_1, + .data_latch_delay_clocks = 0, + .p_timing_settings = &ospi_b_data.ospi_b_timing_settings, + .p_xspi_command_set_list = + &ospi_b_data.ospi_b_high_speed_command_set, + .xspi_command_set_list_length = 1U, + .p_autocalibration_preamble_pattern_addr = + APP_ADDRESS(SECTOR_THREE), + .read_dummy_cycles = SPI_NOR_DUMMY_RD_MEM, + .program_dummy_cycles = SPI_NOR_DUMMY_WR, + .status_dummy_cycles = 0}, + .ospi_b_cfg = {.spi_protocol = SPI_FLASH_PROTOCOL_1S_1S_1S, + .read_mode = SPI_FLASH_READ_MODE_STANDARD, + .address_bytes = SPI_FLASH_ADDRESS_BYTES_4, + .dummy_clocks = SPI_FLASH_DUMMY_CLOCKS_DEFAULT, + .page_program_address_lines = (spi_flash_data_lines_t)0U, + .page_size_bytes = PAGE_SIZE_BYTE, + .write_status_bit = WRITE_STATUS_BIT, + .write_enable_bit = WRITE_ENABLE_BIT, + .page_program_command = SPI_NOR_CMD_PP_4B, + .write_enable_command = SPI_NOR_CMD_WREN, + .status_command = SPI_NOR_CMD_RDSR, + .read_command = SPI_NOR_CMD_READ_FAST, + .xip_enter_command = 0U, + .xip_exit_command = 0U, + .erase_command_list_length = ERASE_COMMAND_LENGTH(erase_command_list), + .p_erase_command_list = &erase_command_list[0], + .p_extend = &ospi_b_data.ospi_b_config_extend}}; + +DEVICE_DT_INST_DEFINE(0, flash_renesas_ra_ospi_b_init, NULL, &ospi_b_data, &ospi_b_config, + POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, &flash_renesas_ra_ospi_b_api); diff --git a/drivers/flash/flash_renesas_ra_ospi_b.h b/drivers/flash/flash_renesas_ra_ospi_b.h new file mode 100644 index 000000000000..14dc5bd31cc3 --- /dev/null +++ b/drivers/flash/flash_renesas_ra_ospi_b.h @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_FLASH_RENESAS_RA_OSPI_B_H_ +#define ZEPHYR_DRIVERS_FLASH_RENESAS_RA_OSPI_B_H_ + +#include +#include +#include +#include +#include +#include "spi_nor.h" + +/* Device node */ +#define RA_OSPI_B_NOR_NODE DT_INST(0, renesas_ra_ospi_b_nor) + +/* Flash erase value */ +#define ERASE_VALUE (0xff) + +/* Page size */ +#define PAGE_SIZE_BYTE 64 + +/* Flash device sector size */ +#define SECTOR_SIZE_128K (0x20000) +#define SECTOR_SIZE_256K (0x40000) + +/* Flash device timing */ +#define TIME_ERASE_256K (16000) +#define TIME_ERASE_4K (1000U) +#define TIME_WRITE (1000U) + +/* Bit status */ +#define WRITE_STATUS_BIT (0) +#define WRITE_ENABLE_BIT (1) + +/* Calibration sector */ +#define SECTOR_THREE (2U) + +/* Command length */ +#define COMMAND_LENGTH_SPI (1U) +#define COMMAND_LENGTH_OSPI (2U) + +/* Transfer address length */ +#define ADDRESS_DUMMY (0U) +#define ADDRESS_LENGTH_ZERO (0U) +#define ADDRESS_LENGTH_THREE (3U) +#define ADDRESS_LENGTH_FOUR (4U) + +/* Transfer data length */ +#define DATA_DUMMY (0U) +#define DATA_LENGTH_ZERO (0U) +#define DATA_LENGTH_ONE (1U) +#define DATA_LENGTH_TWO (2U) +#define DATA_LENGTH_FOUR (4U) +#define DATA_LENGTH_EIGHT (8U) + +/* Configure flash device */ +#define DATA_CFR2V_REGISTER (0x83) +#define DATA_CFR3V_REGISTER (0x40) +#define DATA_SET_SPI_CFR5V_REGISTER (0x40) +#define DATA_SET_OSPI_CFR5V_REGISTER (0x43) + +/* Flash device address space mapping */ +#define APP_ADDRESS(sector_no) \ + ((uint8_t *)(BSP_FEATURE_OSPI_B_DEVICE_1_START_ADDRESS + \ + ((sector_no) * SPI_NOR_SECTOR_SIZE))) + +/* Erase command */ +static const spi_flash_erase_command_t erase_command_list[] = { + {.command = SPI_NOR_CMD_SE_4B, .size = SPI_NOR_SECTOR_SIZE}, + {.command = SPI_NOR_CMD_SE_256KB, .size = SECTOR_SIZE_256K}, + {.command = SPI_NOR_CMD_ERCHP, .size = SPI_FLASH_ERASE_SIZE_CHIP_ERASE}}; + +static const spi_flash_erase_command_t high_speed_erase_command_list[] = { + {.command = SPI_NOR_OCMD_SE_4KB, .size = SPI_NOR_SECTOR_SIZE}, + {.command = SPI_NOR_OCMD_SE_256KB, .size = SECTOR_SIZE_256K}, + {.command = SPI_NOR_OCMD_ERCHP, .size = SPI_FLASH_ERASE_SIZE_CHIP_ERASE}}; + +/* Erase command length */ +#define ERASE_COMMAND_LENGTH(arr) (sizeof(arr) / sizeof((arr)[0])) + +/* Reset value */ +#define RESET_VALUE (0x00) + +/* Transfer table */ +typedef enum e_transfer { + TRANSFER_WRITE_ENABLE_SPI = 0, + TRANSFER_WRITE_CFR2V_SPI, + TRANSFER_WRITE_CFR3V_SPI, + TRANSFER_WRITE_CFR5V_SPI, + TRANSFER_READ_STATUS_SPI, + TRANSFER_READ_CFR2V_SPI, + TRANSFER_READ_CFR3V_SPI, + TRANSFER_READ_CFR5V_SPI, + TRANSFER_READ_DEVICE_ID_SPI, + TRANSFER_READ_SFDP_ID_SPI, + TRANSFER_RESET_ENABLE_SPI, + TRANSFER_RESET_MEM_SPI, + + TRANSFER_WRITE_ENABLE_OSPI, + TRANSFER_WRITE_CFR2V_OSPI, + TRANSFER_WRITE_CFR3V_OSPI, + TRANSFER_WRITE_CFR5V_OSPI, + TRANSFER_READ_STATUS_OSPI, + TRANSFER_READ_CFR2V_OSPI, + TRANSFER_READ_CFR3V_OSPI, + TRANSFER_READ_CFR5V_OSPI, + TRANSFER_READ_DEVICE_ID_OSPI, + TRANSFER_READ_SFDP_ID_OSPI, + TRANSFER_RESET_ENABLE_OSPI, + TRANSFER_RESET_MEM_OSPI, + TRANSFER_MAX +} transfer_t; + +spi_flash_direct_transfer_t direct_transfer[TRANSFER_MAX] = { + /* Transfer structure for SPI mode */ + [TRANSFER_WRITE_ENABLE_SPI] = {.command = SPI_NOR_CMD_WREN, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + [TRANSFER_WRITE_CFR2V_SPI] = {.command = SPI_NOR_CMD_WR_WRARG, + .address = SPI_NOR_CFR2V_ADDR, + .data = DATA_CFR2V_REGISTER, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + [TRANSFER_WRITE_CFR3V_SPI] = {.command = SPI_NOR_CMD_WR_WRARG, + .address = SPI_NOR_CFR3V_ADDR, + .data = DATA_CFR3V_REGISTER, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + [TRANSFER_WRITE_CFR5V_SPI] = {.command = SPI_NOR_CMD_WR_WRARG, + .address = SPI_NOR_CFR5V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + [TRANSFER_READ_STATUS_SPI] = {.command = SPI_NOR_CMD_RDSR, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_RD_STATUS}, + [TRANSFER_READ_CFR2V_SPI] = {.command = SPI_NOR_CMD_RREG, + .address = SPI_NOR_CFR2V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG}, + [TRANSFER_READ_CFR3V_SPI] = {.command = SPI_NOR_CMD_RREG, + .address = SPI_NOR_CFR3V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG}, + [TRANSFER_READ_CFR5V_SPI] = {.command = SPI_NOR_CMD_RREG, + .address = SPI_NOR_CFR5V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_ONE, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG}, + [TRANSFER_READ_DEVICE_ID_SPI] = {.command = SPI_NOR_CMD_RDID, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_FOUR, + .dummy_cycles = SPI_NOR_DUMMY_RD_STATUS}, + [TRANSFER_READ_SFDP_ID_SPI] = {.command = SPI_NOR_CMD_RSFDPID, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_THREE, + .data_length = DATA_LENGTH_EIGHT, + .dummy_cycles = SPI_NOR_DUMMY_RD_SFDP}, + [TRANSFER_RESET_ENABLE_SPI] = {.command = SPI_NOR_CMD_RESET_EN, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + [TRANSFER_RESET_MEM_SPI] = {.command = SPI_NOR_CMD_RESET_MEM, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_SPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR}, + /* Transfer structure for OPI mode */ + [TRANSFER_WRITE_ENABLE_OSPI] = {.command = SPI_NOR_OCMD_WEN, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, + [TRANSFER_WRITE_CFR2V_OSPI] = {.command = SPI_NOR_OCMD_WR_REG2, + .address = SPI_NOR_CFR2V_ADDR, + .data = DATA_CFR2V_REGISTER, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, + [TRANSFER_WRITE_CFR3V_OSPI] = {.command = SPI_NOR_OCMD_WR_REG2, + .address = SPI_NOR_CFR3V_ADDR, + .data = DATA_CFR3V_REGISTER, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, + [TRANSFER_WRITE_CFR5V_OSPI] = {.command = SPI_NOR_OCMD_WR_REG2, + .address = SPI_NOR_CFR5V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, + [TRANSFER_READ_STATUS_OSPI] = {.command = SPI_NOR_OCMD_RSR, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_RD_STATUS_OCTAL}, + [TRANSFER_READ_CFR2V_OSPI] = {.command = SPI_NOR_OCMD_RSR, + .address = SPI_NOR_CFR2V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG_OCTAL}, + [TRANSFER_READ_CFR3V_OSPI] = {.command = SPI_NOR_OCMD_RSR, + .address = SPI_NOR_CFR3V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG_OCTAL}, + [TRANSFER_READ_CFR5V_OSPI] = {.command = SPI_NOR_OCMD_RREG, + .address = SPI_NOR_CFR5V_ADDR, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_TWO, + .dummy_cycles = SPI_NOR_DUMMY_RD_REG_OCTAL}, + [TRANSFER_READ_DEVICE_ID_OSPI] = {.command = SPI_NOR_OCMD_RDID, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_FOUR, + .dummy_cycles = SPI_NOR_DUMMY_RD_STATUS_OCTAL}, + [TRANSFER_READ_SFDP_ID_OSPI] = {.command = SPI_NOR_OCMD_RSFDPID, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_FOUR, + .data_length = DATA_LENGTH_EIGHT, + .dummy_cycles = SPI_NOR_DUMMY_RD_SFDP_OCTAL}, + [TRANSFER_RESET_ENABLE_OSPI] = {.command = SPI_NOR_OCMD_RST_EN, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, + [TRANSFER_RESET_MEM_OSPI] = {.command = SPI_NOR_OCMD_RST_MEM, + .address = ADDRESS_DUMMY, + .data = DATA_DUMMY, + .command_length = COMMAND_LENGTH_OSPI, + .address_length = ADDRESS_LENGTH_ZERO, + .data_length = DATA_LENGTH_ZERO, + .dummy_cycles = SPI_NOR_DUMMY_WR_OCTAL}, +}; + +#endif /* ZEPHYR_DRIVERS_FLASH_RENESAS_RA_OSPI_B_H_ */ diff --git a/drivers/flash/spi_nor.h b/drivers/flash/spi_nor.h index a918e0a99d05..706cb3772c92 100644 --- a/drivers/flash/spi_nor.h +++ b/drivers/flash/spi_nor.h @@ -9,110 +9,146 @@ #include -#define SPI_NOR_MAX_ID_LEN 3 +#define SPI_NOR_MAX_ID_LEN 3 /* Status register bits */ -#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */ -#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */ +#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */ +#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */ /* Flash opcodes */ -#define SPI_NOR_CMD_WRSR 0x01 /* Write status register */ -#define SPI_NOR_CMD_RDSR 0x05 /* Read status register */ -#define SPI_NOR_CMD_WRSR2 0x31 /* Write status register 2 */ -#define SPI_NOR_CMD_RDSR2 0x35 /* Read status register 2 */ -#define SPI_NOR_CMD_RDSR3 0x15 /* Read status register 3 */ -#define SPI_NOR_CMD_WRSR3 0x11 /* Write status register 3 */ -#define SPI_NOR_CMD_READ 0x03 /* Read data */ -#define SPI_NOR_CMD_READ_FAST 0x0B /* Read data */ -#define SPI_NOR_CMD_DREAD 0x3B /* Read data (1-1-2) */ -#define SPI_NOR_CMD_2READ 0xBB /* Read data (1-2-2) */ -#define SPI_NOR_CMD_QREAD 0x6B /* Read data (1-1-4) */ -#define SPI_NOR_CMD_4READ 0xEB /* Read data (1-4-4) */ -#define SPI_NOR_CMD_WREN 0x06 /* Write enable */ -#define SPI_NOR_CMD_WRDI 0x04 /* Write disable */ -#define SPI_NOR_CMD_PP 0x02 /* Page program */ -#define SPI_NOR_CMD_PP_1_1_2 0xA2 /* Dual Page program (1-1-2) */ -#define SPI_NOR_CMD_PP_1_1_4 0x32 /* Quad Page program (1-1-4) */ -#define SPI_NOR_CMD_PP_1_4_4 0x38 /* Quad Page program (1-4-4) */ -#define SPI_NOR_CMD_RDCR 0x15 /* Read control register */ -#define SPI_NOR_CMD_SE 0x20 /* Sector erase */ -#define SPI_NOR_CMD_SE_4B 0x21 /* Sector erase 4 byte address*/ -#define SPI_NOR_CMD_BE_32K 0x52 /* Block erase 32KB */ -#define SPI_NOR_CMD_BE 0xD8 /* Block erase */ -#define SPI_NOR_CMD_BE_4B 0xDC /* Block erase 4 byte address*/ -#define SPI_NOR_CMD_CE 0xC7 /* Chip erase */ -#define SPI_NOR_CMD_RDID 0x9F /* Read JEDEC ID */ -#define SPI_NOR_CMD_ULBPR 0x98 /* Global Block Protection Unlock */ -#define SPI_NOR_CMD_4BA 0xB7 /* Enter 4-Byte Address Mode */ -#define SPI_NOR_CMD_DPD 0xB9 /* Deep Power Down */ -#define SPI_NOR_CMD_RDPD 0xAB /* Release from Deep Power Down */ -#define SPI_NOR_CMD_WR_CFGREG2 0x72 /* Write config register 2 */ -#define SPI_NOR_CMD_RD_CFGREG2 0x71 /* Read config register 2 */ -#define SPI_NOR_CMD_RESET_EN 0x66 /* Reset Enable */ -#define SPI_NOR_CMD_RESET_MEM 0x99 /* Reset Memory */ -#define SPI_NOR_CMD_BULKE 0x60 /* Bulk Erase */ -#define SPI_NOR_CMD_READ_4B 0x13 /* Read data 4 Byte Address */ -#define SPI_NOR_CMD_READ_FAST_4B 0x0C /* Fast Read 4 Byte Address */ -#define SPI_NOR_CMD_DREAD_4B 0x3C /* Read data (1-1-2) 4 Byte Address */ -#define SPI_NOR_CMD_2READ_4B 0xBC /* Read data (1-2-2) 4 Byte Address */ -#define SPI_NOR_CMD_QREAD_4B 0x6C /* Read data (1-1-4) 4 Byte Address */ -#define SPI_NOR_CMD_4READ_4B 0xEC /* Read data (1-4-4) 4 Byte Address */ -#define SPI_NOR_CMD_PP_4B 0x12 /* Page Program 4 Byte Address */ -#define SPI_NOR_CMD_PP_1_1_4_4B 0x34 /* Quad Page program (1-1-4) 4 Byte Address */ -#define SPI_NOR_CMD_PP_1_4_4_4B 0x3e /* Quad Page program (1-4-4) 4 Byte Address */ +#define SPI_NOR_CMD_WRSR 0x01 /* Write status register */ +#define SPI_NOR_CMD_RDSR 0x05 /* Read status register */ +#define SPI_NOR_CMD_WRSR2 0x31 /* Write status register 2 */ +#define SPI_NOR_CMD_RDSR2 0x35 /* Read status register 2 */ +#define SPI_NOR_CMD_RDSR3 0x15 /* Read status register 3 */ +#define SPI_NOR_CMD_WRSR3 0x11 /* Write status register 3 */ +#define SPI_NOR_CMD_READ 0x03 /* Read data */ +#define SPI_NOR_CMD_READ_FAST 0x0B /* Read data */ +#define SPI_NOR_CMD_DREAD 0x3B /* Read data (1-1-2) */ +#define SPI_NOR_CMD_2READ 0xBB /* Read data (1-2-2) */ +#define SPI_NOR_CMD_QREAD 0x6B /* Read data (1-1-4) */ +#define SPI_NOR_CMD_4READ 0xEB /* Read data (1-4-4) */ +#define SPI_NOR_CMD_WREN 0x06 /* Write enable */ +#define SPI_NOR_CMD_WRDI 0x04 /* Write disable */ +#define SPI_NOR_CMD_PP 0x02 /* Page program */ +#define SPI_NOR_CMD_PP_1_1_2 0xA2 /* Dual Page program (1-1-2) */ +#define SPI_NOR_CMD_PP_1_1_4 0x32 /* Quad Page program (1-1-4) */ +#define SPI_NOR_CMD_PP_1_4_4 0x38 /* Quad Page program (1-4-4) */ +#define SPI_NOR_CMD_RDCR 0x15 /* Read control register */ +#define SPI_NOR_CMD_SE 0x20 /* Sector erase */ +#define SPI_NOR_CMD_SE_4B 0x21 /* Sector erase 4 byte address*/ +#define SPI_NOR_CMD_BE_32K 0x52 /* Block erase 32KB */ +#define SPI_NOR_CMD_BE 0xD8 /* Block erase */ +#define SPI_NOR_CMD_BE_4B 0xDC /* Block erase 4 byte address*/ +#define SPI_NOR_CMD_CE 0xC7 /* Chip erase */ +#define SPI_NOR_CMD_RDID 0x9F /* Read JEDEC ID */ +#define SPI_NOR_CMD_ULBPR 0x98 /* Global Block Protection Unlock */ +#define SPI_NOR_CMD_4BA 0xB7 /* Enter 4-Byte Address Mode */ +#define SPI_NOR_CMD_DPD 0xB9 /* Deep Power Down */ +#define SPI_NOR_CMD_RDPD 0xAB /* Release from Deep Power Down */ +#define SPI_NOR_CMD_WR_CFGREG2 0x72 /* Write config register 2 */ +#define SPI_NOR_CMD_RD_CFGREG2 0x71 /* Read config register 2 */ +#define SPI_NOR_CMD_RESET_EN 0x66 /* Reset Enable */ +#define SPI_NOR_CMD_RESET_MEM 0x99 /* Reset Memory */ +#define SPI_NOR_CMD_BULKE 0x60 /* Bulk Erase */ +#define SPI_NOR_CMD_READ_4B 0x13 /* Read data 4 Byte Address */ +#define SPI_NOR_CMD_READ_FAST_4B 0x0C /* Fast Read 4 Byte Address */ +#define SPI_NOR_CMD_DREAD_4B 0x3C /* Read data (1-1-2) 4 Byte Address */ +#define SPI_NOR_CMD_2READ_4B 0xBC /* Read data (1-2-2) 4 Byte Address */ +#define SPI_NOR_CMD_QREAD_4B 0x6C /* Read data (1-1-4) 4 Byte Address */ +#define SPI_NOR_CMD_4READ_4B 0xEC /* Read data (1-4-4) 4 Byte Address */ +#define SPI_NOR_CMD_PP_4B 0x12 /* Page Program 4 Byte Address */ +#define SPI_NOR_CMD_PP_1_1_4_4B 0x34 /* Quad Page program (1-1-4) 4 Byte Address */ +#define SPI_NOR_CMD_PP_1_4_4_4B 0x3e /* Quad Page program (1-4-4) 4 Byte Address */ + +#define SPI_NOR_CMD_WR_WRARG 0x71 /* Write Any Register for S28Hx512T */ +#define SPI_NOR_CMD_RSFDPID 0x5A /* Read SFDP ID for S28Hx512T */ +#define SPI_NOR_CMD_RREG 0x65 /* Read Any Register for S28Hx512T */ +#define SPI_NOR_CMD_SE_256KB 0xDC /* Sector Erase 256KB for S28Hx512T */ +#define SPI_NOR_CMD_ERCHP 0x60 /* Erase Chip for S28Hx512T */ /* Flash octal opcodes */ -#define SPI_NOR_OCMD_SE 0x21DE /* Octal Sector erase */ -#define SPI_NOR_OCMD_CE 0xC738 /* Octal Chip erase */ -#define SPI_NOR_OCMD_RDSR 0x05FA /* Octal Read status register */ -#define SPI_NOR_OCMD_DTR_RD 0xEE11 /* Octal IO DTR read command */ -#define SPI_NOR_OCMD_RD 0xEC13 /* Octal IO read command */ -#define SPI_NOR_OCMD_PAGE_PRG 0x12ED /* Octal Page Prog */ -#define SPI_NOR_OCMD_WREN 0x06F9 /* Octal Write enable */ -#define SPI_NOR_OCMD_NOP 0x00FF /* Octal No operation */ -#define SPI_NOR_OCMD_RESET_EN 0x6699 /* Octal Reset Enable */ -#define SPI_NOR_OCMD_RESET_MEM 0x9966 /* Octal Reset Memory */ -#define SPI_NOR_OCMD_WR_CFGREG2 0x728D /* Octal Write configuration Register2 */ -#define SPI_NOR_OCMD_RD_CFGREG2 0x718E /* Octal Read configuration Register2 */ -#define SPI_NOR_OCMD_BULKE 0x609F /* Octa Bulk Erase */ - - /* Page, sector, and block size are standard, not configurable. */ - #define SPI_NOR_PAGE_SIZE 0x0100U - #define SPI_NOR_SECTOR_SIZE 0x1000U - #define SPI_NOR_BLOCK_SIZE 0x10000U +#define SPI_NOR_OCMD_SE 0x21DE /* Octal Sector erase */ +#define SPI_NOR_OCMD_CE 0xC738 /* Octal Chip erase */ +#define SPI_NOR_OCMD_RDSR 0x05FA /* Octal Read status register */ +#define SPI_NOR_OCMD_DTR_RD 0xEE11 /* Octal IO DTR read command */ +#define SPI_NOR_OCMD_RD 0xEC13 /* Octal IO read command */ +#define SPI_NOR_OCMD_PAGE_PRG 0x12ED /* Octal Page Prog */ +#define SPI_NOR_OCMD_WREN 0x06F9 /* Octal Write enable */ +#define SPI_NOR_OCMD_NOP 0x00FF /* Octal No operation */ +#define SPI_NOR_OCMD_RESET_EN 0x6699 /* Octal Reset Enable */ +#define SPI_NOR_OCMD_RESET_MEM 0x9966 /* Octal Reset Memory */ +#define SPI_NOR_OCMD_WR_CFGREG2 0x728D /* Octal Write configuration Register2 */ +#define SPI_NOR_OCMD_RD_CFGREG2 0x718E /* Octal Read configuration Register2 */ +#define SPI_NOR_OCMD_BULKE 0x609F /* Octa Bulk Erase */ + +#define SPI_NOR_OCMD_WEN 0x0606 /* Octal Write enable for S28Hx512T */ +#define SPI_NOR_OCMD_RSR 0x0505 /* Octal Read status register for S28Hx512T */ +#define SPI_NOR_OCMD_WR_REG2 0x7171 /* Octal Write config register 2 for S28Hx512T */ +#define SPI_NOR_OCMD_RDID 0x9F9F /* Octal Read JEDEC ID for S28Hx512T */ +#define SPI_NOR_OCMD_RSFDPID 0x5A5A /* Octal Read SFDP ID for S28Hx512T */ +#define SPI_NOR_OCMD_RREG 0x6565 /* Octal Read Any Register for S28Hx512T */ +#define SPI_NOR_OCMD_PP_4B 0x1212 /* Octal Page Program 4 Byte Address for S28Hx512T */ +#define SPI_NOR_OCMD_READ 0xEEEE /* Octal Read data for S28Hx512T */ +#define SPI_NOR_OCMD_RST_EN 0x6666 /* Octal Reset Enable for S28Hx512T */ +#define SPI_NOR_OCMD_RST_MEM 0x9999 /* Reset Memory for S28Hx512T */ +#define SPI_NOR_OCMD_SE_4KB 0x2121 /* Octal Sector Erase 4Kb address for S28Hx512T */ +#define SPI_NOR_OCMD_SE_256KB 0xDCDC /* Octal Sector Erase 256Kb address for S28Hx512T */ +#define SPI_NOR_OCMD_ERCHP 0x6060 /* Octal Erase Chip for S28Hx512T */ + +/* Page, sector, and block size are standard, not configurable. */ +#define SPI_NOR_PAGE_SIZE 0x0100U +#define SPI_NOR_SECTOR_SIZE 0x1000U +#define SPI_NOR_BLOCK_SIZE 0x10000U /* Flash Auto-polling values */ -#define SPI_NOR_WREN_MATCH 0x02 -#define SPI_NOR_WREN_MASK 0x02 +#define SPI_NOR_WREN_MATCH 0x02 +#define SPI_NOR_WREN_MASK 0x02 -#define SPI_NOR_WEL_MATCH 0x00 -#define SPI_NOR_WEL_MASK 0x02 +#define SPI_NOR_WEL_MATCH 0x00 +#define SPI_NOR_WEL_MASK 0x02 #define SPI_NOR_MEM_RDY_MATCH 0x00 #define SPI_NOR_MEM_RDY_MASK 0x01 -#define SPI_NOR_AUTO_POLLING_INTERVAL 0x10 +#define SPI_NOR_AUTO_POLLING_INTERVAL 0x10 /* Flash Dummy Cycles values */ -#define SPI_NOR_DUMMY_RD 8U -#define SPI_NOR_DUMMY_RD_OCTAL 6U -#define SPI_NOR_DUMMY_RD_OCTAL_DTR 6U -#define SPI_NOR_DUMMY_REG_OCTAL 4U -#define SPI_NOR_DUMMY_REG_OCTAL_DTR 5U - +#define SPI_NOR_DUMMY_RD 8U +#define SPI_NOR_DUMMY_RD_OCTAL 6U +#define SPI_NOR_DUMMY_RD_OCTAL_DTR 6U +#define SPI_NOR_DUMMY_REG_OCTAL 4U +#define SPI_NOR_DUMMY_REG_OCTAL_DTR 5U + +#define SPI_NOR_DUMMY_WR 0U +#define SPI_NOR_DUMMY_WR_OCTAL 0U +#define SPI_NOR_DUMMY_RD_STATUS 0U +#define SPI_NOR_DUMMY_RD_STATUS_OCTAL 4U +#define SPI_NOR_DUMMY_RD_REG 1U +#define SPI_NOR_DUMMY_RD_REG_OCTAL 4U +#define SPI_NOR_DUMMY_RD_MEM 3U +#define SPI_NOR_DUMMY_RD_MEM_OCTAL 10U +#define SPI_NOR_DUMMY_RD_SFDP 8U +#define SPI_NOR_DUMMY_RD_SFDP_OCTAL 8U /* Memory registers address */ -#define SPI_NOR_REG2_ADDR1 0x0000000 -#define SPI_NOR_CR2_STR_OPI_EN 0x01 -#define SPI_NOR_CR2_DTR_OPI_EN 0x02 -#define SPI_NOR_REG2_ADDR3 0x00000300 -#define SPI_NOR_CR2_DUMMY_CYCLES_66MHZ 0x07 +#define SPI_NOR_REG2_ADDR1 0x0000000 +#define SPI_NOR_CR2_STR_OPI_EN 0x01 +#define SPI_NOR_CR2_DTR_OPI_EN 0x02 +#define SPI_NOR_REG2_ADDR3 0x00000300 +#define SPI_NOR_CR2_DUMMY_CYCLES_66MHZ 0x07 + +#define SPI_NOR_CFR1V_ADDR 0x00800002 +#define SPI_NOR_CFR2V_ADDR 0x00800003 +#define SPI_NOR_CFR3V_ADDR 0x00800004 +#define SPI_NOR_CFR4V_ADDR 0x00800005 +#define SPI_NOR_CFR5V_ADDR 0x00800006 /* Test whether offset is aligned to a given number of bits. */ #define SPI_NOR_IS_ALIGNED(_ofs, _bits) (((_ofs) & BIT_MASK(_bits)) == 0) #define SPI_NOR_IS_SECTOR_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 12) -#define SPI_NOR_IS_32K_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 15) -#define SPI_NOR_IS_64K_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 16) +#define SPI_NOR_IS_32K_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 15) +#define SPI_NOR_IS_64K_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 16) #define CMD_RDCR 0x15 /* Read the configuration register. */ diff --git a/dts/arm/renesas/ra/ra8/ra8x1.dtsi b/dts/arm/renesas/ra/ra8/ra8x1.dtsi index a605542250b8..3ec1e33e6ff0 100644 --- a/dts/arm/renesas/ra/ra8/ra8x1.dtsi +++ b/dts/arm/renesas/ra/ra8/ra8x1.dtsi @@ -473,6 +473,15 @@ status = "disabled"; }; + ospi0: ospi@40268000 { + compatible = "renesas,ra-ospi-b"; + reg = <0x40268000 0x19c>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&octaspiclk MSTPB 16>; + status = "disabled"; + }; + option_setting_ofs: option_setting_ofs@300a100 { compatible = "zephyr,memory-region"; reg = <0x0300a100 0x18>; diff --git a/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml b/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml new file mode 100644 index 000000000000..07c83927259f --- /dev/null +++ b/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml @@ -0,0 +1,65 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA OSPI FLASH + +compatible: "renesas,ra-ospi-b-nor" + +include: [flash-controller.yaml] + +on-bus: ospi + +properties: + reg: + required: true + description: Flash Memory base address and size in bytes + + protocol-mode: + type: int + required: true + description: | + The width and rate of XSPI bus to which flash memory is connected. + + Possible values are : + - XSPI_SPI_MODE <1> = SPI mode on 1 data line + - XSPI_DUAL_MODE <2> = Dual mode on 2 data lines + - XSPI_QUAD_MODE <4> = Quad mode on 4 data lines + - XSPI_OCTO_MODE <8> = Octo mode on 8 data lines + enum: + - 1 + - 2 + - 4 + - 8 + + data-rate: + type: int + required: true + description: | + The SPI data Rate is STR or DTR + + Possible values are : + - XSPI_STR_TRANSFER <1> = Single Rate Transfer + - XSPI_DTR_TRANSFER <2> = Dual Rate Transfer (only with XSPI_OCTO_MODE) + + ospi-max-frequency: + type: int + required: true + description: Max frequency input on OSPI + + write-block-size: + type: int + description: Address alignment required by flash write operations + +child-binding: + description: OSPI Flash page layout description + child-binding: + description: Individual flash page layout entry + properties: + pages-count: + description: Number of consecutive pages with size pages-size bytes + type: int + required: true + + pages-size: + type: int + required: true diff --git a/dts/bindings/ospi/renesas,ra-ospi-b.yaml b/dts/bindings/ospi/renesas,ra-ospi-b.yaml new file mode 100644 index 000000000000..3484dd524eb0 --- /dev/null +++ b/dts/bindings/ospi/renesas,ra-ospi-b.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA OSPI + +compatible: "renesas,ra-ospi-b" + +include: [base.yaml, pinctrl-device.yaml] + +bus: ospi + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + clocks: + required: true diff --git a/modules/Kconfig.renesas_fsp b/modules/Kconfig.renesas_fsp index 62221025388c..669b9661ac83 100644 --- a/modules/Kconfig.renesas_fsp +++ b/modules/Kconfig.renesas_fsp @@ -142,6 +142,11 @@ config USE_RA_FSP_SDHI help Enable RA FSP SDHI driver +config USE_RA_FSP_OSPI_B_NOR_FLASH + bool + help + Enable RA FSP Octal-SPI driver + endif # HAS_RENESAS_RA_FSP if HAS_RENESAS_RZ_FSP diff --git a/samples/drivers/jesd216/src/main.c b/samples/drivers/jesd216/src/main.c index 480649397b6b..0c0098f5328b 100644 --- a/samples/drivers/jesd216/src/main.c +++ b/samples/drivers/jesd216/src/main.c @@ -26,6 +26,8 @@ #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_imx_flexspi_nor) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ospi_b_nor) +#define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(renesas_ra_ospi_b_nor) #else #error Unsupported flash driver #define FLASH_NODE DT_INVALID_NODE diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index b84359ae05bb..f3690e6d862c 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -21,14 +21,20 @@ #elif defined(CONFIG_BOARD_NPCX9M6F_EVB) || \ defined(CONFIG_BOARD_NPCX7M6FB_EVB) #define SPI_FLASH_TEST_REGION_OFFSET 0x7F000 +#elif defined(CONFIG_BOARD_EK_RA8M1) || defined(CONFIG_BOARD_EK_RA8D1) +#define SPI_FLASH_TEST_REGION_OFFSET 0x40000 #else #define SPI_FLASH_TEST_REGION_OFFSET 0xff000 #endif +#if defined(CONFIG_BOARD_EK_RA8M1) || defined(CONFIG_BOARD_EK_RA8D1) +#define SPI_FLASH_SECTOR_SIZE 262144 +#else #define SPI_FLASH_SECTOR_SIZE 4096 +#endif + +#if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) || \ + defined(CONFIG_FLASH_STM32_XSPI) || defined(CONFIG_FLASH_OSPI_B_RENESAS_RA) -#if defined(CONFIG_FLASH_STM32_OSPI) || \ - defined(CONFIG_FLASH_STM32_QSPI) || \ - defined(CONFIG_FLASH_STM32_XSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif @@ -42,15 +48,25 @@ #define SPI_FLASH_COMPAT st_stm32_xspi_nor #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor) #define SPI_FLASH_COMPAT nordic_qspi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ospi_b_nor) +#define SPI_FLASH_COMPAT renesas_ra_ospi_b_nor #else #define SPI_FLASH_COMPAT invalid #endif +#if defined(CONFIG_FLASH_OSPI_B_RENESAS_RA) +const uint8_t erased[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#else const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff }; +#endif void single_sector_test(const struct device *flash_dev) { +#if defined(CONFIG_FLASH_OSPI_B_RENESAS_RA) + const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; +#else const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 }; +#endif const size_t len = sizeof(expected); uint8_t buf[sizeof(expected)]; int rc; @@ -122,7 +138,11 @@ void single_sector_test(const struct device *flash_dev) #if defined SPI_FLASH_MULTI_SECTOR_TEST void multi_sector_test(const struct device *flash_dev) { +#if defined(CONFIG_FLASH_OSPI_B_RENESAS_RA) + const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; +#else const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 }; +#endif const size_t len = sizeof(expected); uint8_t buf[sizeof(expected)]; int rc; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index e7552aaf177b..f895ec32655a 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -12,6 +12,8 @@ #if defined(CONFIG_NORDIC_QSPI_NOR) #define TEST_AREA_DEV_NODE DT_INST(0, nordic_qspi_nor) +#elif defined(CONFIG_FLASH_OSPI_B_RENESAS_RA) +#define TEST_AREA_DEV_NODE DT_INST(0, renesas_ra_ospi_b_nor) #elif defined(CONFIG_SPI_NOR) #define TEST_AREA_DEV_NODE DT_INST(0, jedec_spi_nor) #else @@ -30,12 +32,18 @@ #elif defined(TEST_AREA_DEV_NODE) #define TEST_AREA_DEVICE DEVICE_DT_GET(TEST_AREA_DEV_NODE) +#if defined CONFIG_FLASH_OSPI_B_RENESAS_RA +#define TEST_AREA_OFFSET 0x40000 +#else #define TEST_AREA_OFFSET 0xff000 +#endif #if DT_NODE_HAS_PROP(TEST_AREA_DEV_NODE, size_in_bytes) #define TEST_AREA_MAX DT_PROP(TEST_AREA_DEV_NODE, size_in_bytes) -#else +#elif DT_NODE_HAS_PROP(TEST_AREA_DEV_NODE, size) #define TEST_AREA_MAX (DT_PROP(TEST_AREA_DEV_NODE, size) / 8) +#else +#define TEST_AREA_MAX DT_REG_SIZE(TEST_AREA_DEV_NODE) #endif #else