From 68a97756def6aa4272ecbd91ee21fb2b39dab9a0 Mon Sep 17 00:00:00 2001 From: Tri Nguyen Date: Wed, 14 Aug 2024 16:27:06 +0700 Subject: [PATCH 1/7] drivers: flash: Initial support OSPI flash driver on RA8 boards Support OSPI flash driver on EK-RA8M1 and EK-RA8D1 with ospi_b and S28HL512T flash. Signed-off-by: Tri Nguyen Signed-off-by: Thao Luong --- drivers/flash/CMakeLists.txt | 1 + drivers/flash/Kconfig | 1 + drivers/flash/Kconfig.renesas_ra_ospi | 18 + drivers/flash/flash_renesas_ra_ospi_b.c | 773 ++++++++++++++++++ drivers/flash/flash_renesas_ra_ospi_b.h | 296 +++++++ .../renesas,ra-ospi-b-nor.yaml | 70 ++ dts/bindings/ospi/renesas,ra-ospi-b.yaml | 23 + modules/Kconfig.renesas_fsp | 5 + 8 files changed, 1187 insertions(+) create mode 100644 drivers/flash/Kconfig.renesas_ra_ospi create mode 100644 drivers/flash/flash_renesas_ra_ospi_b.c create mode 100644 drivers/flash/flash_renesas_ra_ospi_b.h create mode 100644 dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml create mode 100644 dts/bindings/ospi/renesas,ra-ospi-b.yaml diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 089259a2572a..d7b1583bad2b 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_MSPI_EMUL_DEVICE flash_mspi_emul_devic zephyr_library_sources_ifdef(CONFIG_FLASH_MSPI_NOR flash_mspi_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_NOR flash_npcx_fiu_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_QSPI flash_npcx_fiu_qspi.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_RENESAS_RA_OSPI_B flash_renesas_ra_ospi_b.c) zephyr_library_sources_ifdef(CONFIG_FLASH_RPI_PICO flash_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_OSPI flash_stm32_ospi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index bdd84f25814b..5b653a96a578 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -192,6 +192,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_ospi" source "drivers/flash/Kconfig.rpi_pico" source "drivers/flash/Kconfig.rv32m1" source "drivers/flash/Kconfig.sam" diff --git a/drivers/flash/Kconfig.renesas_ra_ospi b/drivers/flash/Kconfig.renesas_ra_ospi new file mode 100644 index 000000000000..1624f0c8258c --- /dev/null +++ b/drivers/flash/Kconfig.renesas_ra_ospi @@ -0,0 +1,18 @@ +# Renesas RA Family + +# Copyright (c) 2024-2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_RENESAS_RA_OSPI_B + 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..649f066b5f18 --- /dev/null +++ b/drivers/flash/flash_renesas_ra_ospi_b.c @@ -0,0 +1,773 @@ +/* + * 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; + ospi_b_table_t const xspi_command_set; + 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_commands = &high_speed_erase_commands}, + .xspi_command_set = {.p_table = &ospi_b_data.ospi_b_high_speed_command_set, .length = 1U}, + .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 = &ospi_b_data.xspi_command_set, + .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..3fe41d326135 --- /dev/null +++ b/drivers/flash/flash_renesas_ra_ospi_b.h @@ -0,0 +1,296 @@ +/* + * 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 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 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])) + +static ospi_b_table_t const high_speed_erase_commands = { + .p_table = &high_speed_erase_command_list, + .length = ERASE_COMMAND_LENGTH(high_speed_erase_command_list), +}; + +/* 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/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..0a4c53b02cc5 --- /dev/null +++ b/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml @@ -0,0 +1,70 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA OSPI FLASH + +compatible: "renesas,ra-ospi-b-nor" + +include: [base.yaml] + +on-bus: ospi + +properties: + reg: + required: true + description: Flash Memory base address and size in bytes + + size: + type: int + required: true + description: Flash Memory size + + 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 01fd54cb0812..3ce821867550 100644 --- a/modules/Kconfig.renesas_fsp +++ b/modules/Kconfig.renesas_fsp @@ -181,6 +181,11 @@ config USE_RA_FSP_LPM help Enable RA FSP LPM 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 From a294326e13a071080098d8ab25d561fbe5a27e30 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Mon, 17 Mar 2025 16:09:32 +0700 Subject: [PATCH 2/7] drivers: flash: Add additional define macro and reformat spi_nor.h Add additional define macro and reformat spi_nor.h Signed-off-by: Khoa Nguyen --- drivers/flash/spi_nor.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/flash/spi_nor.h b/drivers/flash/spi_nor.h index a918e0a99d05..62f2e8b8b745 100644 --- a/drivers/flash/spi_nor.h +++ b/drivers/flash/spi_nor.h @@ -61,6 +61,12 @@ #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 */ @@ -76,6 +82,20 @@ #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 @@ -100,6 +120,16 @@ #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 @@ -108,6 +138,12 @@ #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) From 2acdf76e61d01c6996f4beb0290a9920501281ee Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Thu, 28 Nov 2024 17:44:23 +0700 Subject: [PATCH 3/7] dts: renesas: Add devicetree property for OSPI support on RA8 Add ospi node on Renesas RA8 devicetree to support QSPI flash driver Signed-off-by: Quy Tran --- dts/arm/renesas/ra/ra8/ra8x1.dtsi | 9 +++++++++ dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml | 7 +------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dts/arm/renesas/ra/ra8/ra8x1.dtsi b/dts/arm/renesas/ra/ra8/ra8x1.dtsi index 1155a02793fd..57bdcc611491 100644 --- a/dts/arm/renesas/ra/ra8/ra8x1.dtsi +++ b/dts/arm/renesas/ra/ra8/ra8x1.dtsi @@ -586,6 +586,15 @@ }; }; + 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 index 0a4c53b02cc5..07c83927259f 100644 --- a/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml +++ b/dts/bindings/flash_controller/renesas,ra-ospi-b-nor.yaml @@ -5,7 +5,7 @@ description: Renesas RA OSPI FLASH compatible: "renesas,ra-ospi-b-nor" -include: [base.yaml] +include: [flash-controller.yaml] on-bus: ospi @@ -14,11 +14,6 @@ properties: required: true description: Flash Memory base address and size in bytes - size: - type: int - required: true - description: Flash Memory size - protocol-mode: type: int required: true From e38c3fd648d3bdd0030fd937162be5a07d048699 Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Thu, 28 Nov 2024 17:49:30 +0700 Subject: [PATCH 4/7] boards: renesas: Add boards support for OSPI flash driver on RA8 Add support for OSPI flash driver on EK-RA8D1 and EK-RA8M1 Signed-off-by: Quy Tran --- boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi | 19 ++++++ boards/renesas/ek_ra8d1/ek_ra8d1.dts | 65 +++++++++++++++++++ boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi | 19 ++++++ boards/renesas/ek_ra8m1/ek_ra8m1.dts | 64 ++++++++++++++++++ 4 files changed, 167 insertions(+) diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi index ba342a635726..af7c788374be 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi @@ -270,4 +270,23 @@ psels = ; }; }; + + 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 9fb7fec4dd16..25fde67752f6 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 @@ -114,6 +115,19 @@ }; }; +&pll2 { + status = "okay"; + clocks = <&xtal>; + div = <2>; + mul = <80 0>; + + pll2p { + status = "okay"; + freq = ; + div = <2>; + }; +}; + &sciclk { clocks = <&pllp>; div = <4>; @@ -132,6 +146,12 @@ status = "okay"; }; +&octaspiclk { + clocks = <&pll2p>; + div = <2>; + status = "okay"; +}; + &uclk { clocks = <&pllq>; div = <5>; @@ -342,3 +362,48 @@ pmod_sd_shield: &sdhc1 {}; status = "okay"; }; }; + +&ospi0 { + pinctrl-0 = <&ospi0_default>; + pinctrl-names = "default"; + status = "okay"; + + s28hl512t: ospi-nor-flash@90000000 { + compatible = "renesas,ra-ospi-b-nor"; + protocol-mode = ; + data-rate = ; + ospi-max-frequency = ; + reg = <0x90000000 DT_SIZE_M(64)>; + write-block-size = <1>; + status = "okay"; + + 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 = ; + }; + }; + + 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/ek_ra8m1-pinctrl.dtsi b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi index e8a26e09905b..bc8e01f83b28 100644 --- a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi @@ -212,4 +212,23 @@ psels = ; }; }; + + 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 e1c084877186..423df5bf4d61 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" @@ -151,6 +152,18 @@ }; }; +&pll2 { + status = "okay"; + clocks = <&xtal>; + div = <2>; + mul = <80 0>; + + pll2p { + status = "okay"; + freq = ; + div = <2>; + }; +}; &sciclk { clocks = <&pllp>; @@ -170,6 +183,12 @@ status = "okay"; }; +&octaspiclk { + clocks = <&pll2p>; + div = <2>; + status = "okay"; +}; + &ioport0 { status = "okay"; }; @@ -401,3 +420,48 @@ pmod_sd_shield: &sdhc0 {}; status = "okay"; }; }; + +&ospi0 { + pinctrl-0 = <&ospi0_default>; + pinctrl-names = "default"; + status = "okay"; + + s28hl512t: ospi-nor-flash@90000000 { + compatible = "renesas,ra-ospi-b-nor"; + protocol-mode = ; + data-rate = ; + ospi-max-frequency = ; + reg = <0x90000000 DT_SIZE_M(64)>; + write-block-size = <1>; + status = "okay"; + + 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 = ; + }; + }; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "nor"; + reg = <0x00000000 DT_SIZE_M(64)>; + }; + }; + }; +}; From 8430eaff56ca624b5156ea1a7d0379e3da80ae58 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 22 Apr 2025 14:14:43 +0700 Subject: [PATCH 5/7] tests: drivers: flash: Add support "common" for Renesas OSPI_B Add support test app "flash/common" for testing Renesas RA OSPI_B on ek_ra8m1, ek_ra8d1 Signed-off-by: Khoa Nguyen --- drivers/flash/flash_renesas_ra_ospi_b.c | 261 +++++++++--------- .../flash/common/boards/ek_ra8d1.overlay | 4 + .../common/boards/ek_ra8d1_ospi_b_nor.conf | 4 + .../common/boards/ek_ra8d1_ospi_b_nor.overlay | 10 + .../flash/common/boards/ek_ra8m1.overlay | 4 + .../common/boards/ek_ra8m1_ospi_b_nor.conf | 4 + .../common/boards/ek_ra8m1_ospi_b_nor.overlay | 10 + tests/drivers/flash/common/src/main.c | 10 +- tests/drivers/flash/common/testcase.yaml | 7 + 9 files changed, 188 insertions(+), 126 deletions(-) create mode 100644 tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf create mode 100644 tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay create mode 100644 tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf create mode 100644 tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay diff --git a/drivers/flash/flash_renesas_ra_ospi_b.c b/drivers/flash/flash_renesas_ra_ospi_b.c index 649f066b5f18..bdb291f2e518 100644 --- a/drivers/flash/flash_renesas_ra_ospi_b.c +++ b/drivers/flash/flash_renesas_ra_ospi_b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Renesas Electronics Corporation + * Copyright (c) 2024-2025 Renesas Electronics Corporation * * SPDX-License-Identifier: Apache-2.0 */ @@ -56,10 +56,8 @@ static void release_device(const struct device *dev) 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) +static int 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; @@ -67,20 +65,20 @@ static fsp_err_t flash_renesas_ra_ospi_b_wait_operation(ospi_b_instance_ctrl_t * /* Get device status */ R_OSPI_B_StatusGet(p_ctrl, &status); if (timeout == RESET_VALUE) { - LOG_ERR("Time out for operation"); - return FSP_ERR_TIMEOUT; + LOG_DBG("Time out for operation"); + return -EIO; } k_sleep(K_USEC(50)); timeout--; } - return err; + return 0; } -static fsp_err_t flash_renesas_ra_ospi_b_write_enable(ospi_b_instance_ctrl_t *p_ctrl) +static int 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}; + fsp_err_t err; /* Transfer write enable command */ transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == p_ctrl->spi_protocol) @@ -88,45 +86,43 @@ static fsp_err_t flash_renesas_ra_ospi_b_write_enable(ospi_b_instance_ctrl_t *p_ : 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; + return -EIO; } /* 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; + if ((err != FSP_SUCCESS) || (SPI_NOR_WREN_MASK != (transfer.data & SPI_NOR_WREN_MASK))) { + return -EIO; } - return err; + return 0; } -static fsp_err_t flash_renesas_ra_ospi_b_setup_calibrate_data(ospi_b_instance_ctrl_t *p_ctrl) +static int 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) { + fsp_err_t err; + /* 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; + LOG_DBG("Erase the flash sector Failed"); + return -EIO; } /* Wait until erase operation completes */ err = flash_renesas_ra_ospi_b_wait_operation(p_ctrl, TIME_ERASE_4K); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Wait for erase operation completes Failed"); + return -EIO; } /* Write auto-calibration data to the flash */ @@ -134,30 +130,36 @@ static fsp_err_t flash_renesas_ra_ospi_b_setup_calibrate_data(ospi_b_instance_ct (uint8_t *)APP_ADDRESS(SECTOR_THREE), sizeof(autocalibration_data)); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Write auto-calibration data Failed"); + return -EIO; } /* Wait until write operation completes */ err = flash_renesas_ra_ospi_b_wait_operation(p_ctrl, TIME_WRITE); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Wait for write operation completes Failed"); + return -EIO; } } - return err; + return 0; } -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) +static int 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}; + fsp_err_t err; /* Open OSPI module */ err = R_OSPI_B_Open(p_ctrl, p_cfg); + if (err != FSP_SUCCESS) { + LOG_DBG("OSPI open Failed"); + return -EIO; + } /* DDR sampling window extend */ R_XSPI->LIOCFGCS_b[p_ctrl->channel].DDRSMPEX = 1; @@ -165,7 +167,8 @@ static fsp_err_t flash_renesas_ra_ospi_b_spi_mode_init(ospi_b_instance_ctrl_t *p /* 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; + LOG_DBG("Switch OSPI module to 1S-1S-1S mode Failed"); + return -EIO; } /* Reset flash device by driving OM_RESET pin */ @@ -177,7 +180,8 @@ static fsp_err_t flash_renesas_ra_ospi_b_spi_mode_init(ospi_b_instance_ctrl_t *p /* Transfer write enable command */ err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Enable write Failed"); + return -EIO; } /* Write to CFR2V to configure Address Byte Length and Memory Array Read Latency */ @@ -185,65 +189,72 @@ static fsp_err_t flash_renesas_ra_ospi_b_spi_mode_init(ospi_b_instance_ctrl_t *p 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; + LOG_DBG("Configure Address Byte Length and Memory Array Read Latency Failed"); + return -EIO; } /* Transfer write enable command */ err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Enable write Failed"); + return -EIO; } /* 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; + LOG_DBG("Configure Volatile Register Read Latency Failed"); + return -EIO; } /* 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; + LOG_DBG("Read back CFR2V register Failed"); + return -EIO; } if (DATA_CFR2V_REGISTER != (uint8_t)transfer.data) { - LOG_ERR("Verify CFR2V register data Failed"); - return FSP_ERR_ABORTED; + LOG_DBG("Verify CFR2V register data Failed"); + return -EIO; } /* 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; + LOG_DBG("Read back CFR3V register Failed"); + return -EIO; } if (DATA_CFR3V_REGISTER != (uint8_t)transfer.data) { - LOG_ERR("Verify CFR3V register data Failed"); - return FSP_ERR_ABORTED; + LOG_DBG("Verify CFR3V register data Failed"); + return -EIO; } /* Setup calibrate data */ err = flash_renesas_ra_ospi_b_setup_calibrate_data(p_ctrl); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Setup calibrate data Failed"); + return -EIO; } - return err; + return 0; } -static fsp_err_t flash_renesas_ra_ospi_b_set_protocol_to_opi(ospi_b_instance_ctrl_t *p_ctrl, - const struct device *dev) +static int 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}; + fsp_err_t err; /* Transfer write enable command */ err = flash_renesas_ra_ospi_b_write_enable(p_ctrl); if (err != FSP_SUCCESS) { - return err; + LOG_DBG("Enable write Failed"); + return -EIO; } /* Write to CFR5V Register to Configure flash device interface mode */ @@ -251,28 +262,31 @@ static fsp_err_t flash_renesas_ra_ospi_b_set_protocol_to_opi(ospi_b_instance_ctr 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; + LOG_DBG("Configure flash device interface mode Failed"); + return -EIO; } /* 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; + LOG_DBG("Switch to OPI mode Failed"); + return -EIO; } /* 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; + LOG_DBG("Read back CFR5V register Failed"); + return -EIO; } if (DATA_SET_OSPI_CFR5V_REGISTER != (uint8_t)transfer.data) { - LOG_ERR("Verify CFR5V register data Failed"); - return FSP_ERR_ABORTED; + LOG_DBG("CFR5V register data is Incorrect"); + return -EIO; } - return err; + return 0; } static inline bool flash_renesas_ra_ospi_b_is_valid_address(const struct device *dev, off_t offset, @@ -285,13 +299,12 @@ static inline bool flash_renesas_ra_ospi_b_is_valid_address(const struct device } #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; + int ret = -ENOTSUP; ARG_UNUSED(in); ARG_UNUSED(out); @@ -299,7 +312,8 @@ static int flash_renesas_ra_ospi_b_ex_op(const struct device *dev, uint16_t code acquire_device(dev); if (code == FLASH_EX_OP_RESET) { - err = flash_renesas_ra_ospi_b_write_enable(&ospi_b_data->ospi_b_ctrl); + fsp_err_t 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 == @@ -320,19 +334,20 @@ static int flash_renesas_ra_ospi_b_ex_op(const struct device *dev, uint16_t code SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE); } - if (err != FSP_SUCCESS) { - err = -EIO; + if (err == FSP_SUCCESS) { + ret = 0; + } else { + ret = -EIO; } } release_device(dev); - return err; + return ret; } -#endif - -#if CONFIG_FLASH_PAGE_LAYOUT +#endif /* CONFIG_FLASH_EX_OP_ENABLED */ +#if defined(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)}, @@ -350,12 +365,11 @@ void flash_renesas_ra_ospi_b_page_layout(const struct device *dev, #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) +static int 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}; + fsp_err_t err; /* Read and check flash device ID */ transfer = (SPI_FLASH_PROTOCOL_EXTENDED_SPI == p_ctrl->spi_protocol) @@ -363,19 +377,19 @@ static fsp_err_t flash_renesas_ra_ospi_b_read_device_id(ospi_b_instance_ctrl_t * : 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; + return -EIO; } /* Get flash device ID */ memcpy(p_id, &transfer.data, sizeof(transfer.data)); - return err; + return 0; } 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; + int ret; if (id == NULL) { return -EINVAL; @@ -383,11 +397,9 @@ static int flash_renesas_ra_ospi_b_read_jedec_id(const struct device *dev, uint8 acquire_device(dev); - err = flash_renesas_ra_ospi_b_read_device_id(&ospi_b_data->ospi_b_ctrl, id); - if (err) { + ret = flash_renesas_ra_ospi_b_read_device_id(&ospi_b_data->ospi_b_ctrl, id); + if (ret) { 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", @@ -396,7 +408,7 @@ static int flash_renesas_ra_ospi_b_read_jedec_id(const struct device *dev, uint8 release_device(dev); - return err; + return ret; } static int flash_renesas_ra_ospi_b_sfdp_read(const struct device *dev, off_t offset, void *data, @@ -405,19 +417,16 @@ static int flash_renesas_ra_ospi_b_sfdp_read(const struct device *dev, off_t off 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; + fsp_err_t err; if (len == 0) { return 0; } - if (data != NULL) { - p_src = data; - } else { + if (data == NULL) { + LOG_ERR("The data buffer is NULL"); return -EINVAL; } - acquire_device(dev); if (ospi_b_data->ospi_b_ctrl.spi_protocol == SPI_FLASH_PROTOCOL_EXTENDED_SPI) { @@ -434,33 +443,33 @@ static int flash_renesas_ra_ospi_b_sfdp_read(const struct device *dev, off_t off err = R_OSPI_B_DirectTransfer(&ospi_b_data->ospi_b_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ); - if (err) { + if (err != FSP_SUCCESS) { LOG_ERR("Failed to read SFDP id"); release_device(dev); return -EIO; } - memcpy(p_src, &transfer.data, size); + memcpy(data, &transfer.data, size); len -= size; offset += size; - p_src += size; + data += size; } release_device(dev); - return err; + return 0; } -#endif +#endif /* CONFIG_FLASH_JESD216_API */ 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; + fsp_err_t err; struct flash_pages_info page_info_start, page_info_end; - int rc; + int ret; if (!len) { return 0; @@ -471,21 +480,20 @@ static int flash_renesas_ra_ospi_b_erase(const struct device *dev, off_t offset, 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", + "Address 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)) { + ret = flash_get_page_info_by_offs(dev, offset, &page_info_start); + if ((ret != 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)) { + ret = flash_get_page_info_by_offs(dev, (offset + len), &page_info_end); + if ((ret != 0) || ((offset + len) != page_info_end.start_offset)) { LOG_ERR("The size %u is not aligned with the ending sector", len); return -EINVAL; } @@ -513,14 +521,16 @@ static int flash_renesas_ra_ospi_b_erase(const struct device *dev, off_t offset, (uint8_t *)(BSP_FEATURE_OSPI_B_DEVICE_1_START_ADDRESS + offset), erase_size); if (err != FSP_SUCCESS) { - err = -EIO; + LOG_ERR("Erase at address 0x%lx, size %zu Failed", offset, erase_size); + ret = -EIO; break; } err = flash_renesas_ra_ospi_b_wait_operation(&ospi_b_data->ospi_b_ctrl, erase_timeout); if (err != FSP_SUCCESS) { - err = -EIO; + LOG_ERR("Wait for erase to finish timeout"); + ret = -EIO; break; } @@ -530,20 +540,19 @@ static int flash_renesas_ra_ospi_b_erase(const struct device *dev, off_t offset, release_device(dev); - return err; + return ret; } 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", + LOG_ERR("Address or size exceeds expected values: " + "Address 0x%lx, size %zu", (long)offset, len); return -EINVAL; } @@ -557,7 +566,8 @@ static int flash_renesas_ra_ospi_b_write(const struct device *dev, off_t offset, size_t len) { struct flash_renesas_ra_ospi_b_data *ospi_b_data = dev->data; - int err = 0; + fsp_err_t err; + int ret = 0; uint32_t size; const uint8_t *p_src; @@ -568,12 +578,13 @@ static int flash_renesas_ra_ospi_b_write(const struct device *dev, off_t offset, if (data != NULL) { p_src = data; } else { + LOG_ERR("The data buffer is NULL"); 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", + LOG_ERR("Address or size exceeds expected values: " + "Address 0x%lx, size %zu", (long)offset, len); return -EINVAL; } @@ -589,13 +600,15 @@ static int flash_renesas_ra_ospi_b_write(const struct device *dev, off_t offset, &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; + LOG_ERR("Write at address 0x%lx, size %zu", offset, size); + ret = -EIO; break; } err = flash_renesas_ra_ospi_b_wait_operation(&ospi_b_data->ospi_b_ctrl, TIME_WRITE); if (err != FSP_SUCCESS) { - err = -EIO; + LOG_ERR("Wait for write to finish timeout"); + ret = -EIO; break; } @@ -606,7 +619,7 @@ static int flash_renesas_ra_ospi_b_write(const struct device *dev, off_t offset, release_device(dev); - return err; + return ret; } static const struct flash_parameters * @@ -648,7 +661,7 @@ 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; + int ret; /* protocol/data_rate of XSPI checking */ if (config->protocol == XSPI_DUAL_MODE || config->protocol == XSPI_QUAD_MODE) { @@ -667,18 +680,17 @@ static int flash_renesas_ra_ospi_b_init(const struct device *dev) 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; + ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_subsys); + if (ret < 0) { + LOG_ERR("Could not initialize clock (%d)", ret); + return ret; } - err = clock_control_get_rate(config->clock_dev, + ret = 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 (ret) { + LOG_ERR("Failed to get clock frequency (%d)", ret); + return ret; } if ((config->protocol == XSPI_SPI_MODE && (config->max_frequency / 2) < clock_freq) || @@ -687,32 +699,31 @@ static int flash_renesas_ra_ospi_b_init(const struct device *dev) return -EINVAL; } - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (err) { - LOG_ERR("Failed to configure pins (%d)", err); - return err; + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + LOG_ERR("Failed to configure pins (%d)", ret); + return ret; } 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) { + ret = flash_renesas_ra_ospi_b_spi_mode_init(&data->ospi_b_ctrl, &data->ospi_b_cfg); + if (ret) { LOG_ERR("Init SPI mode failed"); - return -EIO; + return ret; } if (config->protocol == XSPI_OCTO_MODE) { - err = flash_renesas_ra_ospi_b_set_protocol_to_opi(&data->ospi_b_ctrl, dev); - if (err) { + ret = flash_renesas_ra_ospi_b_set_protocol_to_opi(&data->ospi_b_ctrl, dev); + if (ret) { LOG_ERR("Init OPI mode failed"); - return -EIO; + return ret; } } LOG_INF("Mode: %d Freq: %u", config->protocol, clock_freq); - return err; + return ret; } PINCTRL_DT_DEFINE(DT_INST_PARENT(0)); diff --git a/tests/drivers/flash/common/boards/ek_ra8d1.overlay b/tests/drivers/flash/common/boards/ek_ra8d1.overlay index 8e42c66387c7..ee45617b0097 100644 --- a/tests/drivers/flash/common/boards/ek_ra8d1.overlay +++ b/tests/drivers/flash/common/boards/ek_ra8d1.overlay @@ -18,3 +18,7 @@ }; }; }; + +&s28hl512t { + status = "disabled"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf new file mode 100644 index 000000000000..349d703d783c --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST_DRIVER_FLASH_SIZE=67108864 diff --git a/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay new file mode 100644 index 000000000000..cb05c656afaa --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; + +&s28hl512t { + status = "okay"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8m1.overlay b/tests/drivers/flash/common/boards/ek_ra8m1.overlay index 8e42c66387c7..ee45617b0097 100644 --- a/tests/drivers/flash/common/boards/ek_ra8m1.overlay +++ b/tests/drivers/flash/common/boards/ek_ra8m1.overlay @@ -18,3 +18,7 @@ }; }; }; + +&s28hl512t { + status = "disabled"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf new file mode 100644 index 000000000000..349d703d783c --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST_DRIVER_FLASH_SIZE=67108864 diff --git a/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay new file mode 100644 index 000000000000..cb05c656afaa --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; + +&s28hl512t { + status = "okay"; +}; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index 54b868a92341..22c53b0493ff 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_RENESAS_RA_OSPI_B) +#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) #elif defined(CONFIG_FLASH_MSPI_NOR) @@ -32,12 +34,18 @@ #elif defined(TEST_AREA_DEV_NODE) #define TEST_AREA_DEVICE DEVICE_DT_GET(TEST_AREA_DEV_NODE) +#if defined CONFIG_FLASH_RENESAS_RA_OSPI_B +#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 diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index 973fb95b223d..f016af4adb29 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -125,3 +125,10 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp + drivers.flash.common.ra_ospi_b_nor: + platform_allow: + - ek_ra8m1 + - ek_ra8d1 + extra_args: + - DTC_OVERLAY_FILE="./boards/${BOARD}_ospi_b_nor.overlay" + - CONF_FILE="./prj.conf ./boards/${BOARD}_ospi_b_nor.conf" From b2659d320283fc5778324c50adda03e7ab33ae7b Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Mon, 17 Mar 2025 11:59:08 +0700 Subject: [PATCH 6/7] samples: drivers: jesd216: Add support OSPI for Renesas RA8 Add support OSPI for Renesas ek_ra8m1, ek_ra8d1 to run sample jesd216 Signed-off-by: Khoa Nguyen Signed-off-by: Tri Nguyen Signed-off-by: Thao Luong --- samples/drivers/jesd216/src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/drivers/jesd216/src/main.c b/samples/drivers/jesd216/src/main.c index b8dad485997a..54fb766a533a 100644 --- a/samples/drivers/jesd216/src/main.c +++ b/samples/drivers/jesd216/src/main.c @@ -28,6 +28,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 From cfe422d465db200bf1f008f6b6391b9c40fad8c3 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Mon, 17 Mar 2025 13:06:58 +0700 Subject: [PATCH 7/7] samples: drivers: spi_flash: Add support OSPI for Renesas RA8 Add support OSPI for Renesas ek_ra8m1, ek_ra8d1 to run sample spi_flash Signed-off-by: Khoa Nguyen Signed-off-by: Tri Nguyen Signed-off-by: Thao Luong --- samples/drivers/spi_flash/src/main.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 52e8b6062b53..5c900f1f348a 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_RENESAS_RA_OSPI_B) -#if defined(CONFIG_FLASH_STM32_OSPI) || \ - defined(CONFIG_FLASH_STM32_QSPI) || \ - defined(CONFIG_FLASH_STM32_XSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif @@ -44,15 +50,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_RENESAS_RA_OSPI_B) +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_RENESAS_RA_OSPI_B) + 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; @@ -124,7 +140,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_RENESAS_RA_OSPI_B) + 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;