drivers: flash: Initial support flash driver on EK-RA8M1
Initial commit for flash driver support on board using RA8 MCUs * drivers: flash: implementation for flash driver on EK-RA8M1 * dts: arm: add device node for flash of EK-RA8M1 * boards: arm: enable support flash driver for ek_ra8m1, update board documentation Signed-off-by: Quy Tran <quy.tran.pz@renesas.com> Signed-off-by: Duy Phuong Hoang. Nguyen <duy.nguyen.xa@renesas.com>
This commit is contained in:
parent
3af8001e0a
commit
e1f990c176
18 changed files with 1143 additions and 5 deletions
|
@ -104,6 +104,8 @@ The below features are currently supported on Zephyr OS for EK-RA8M1 board:
|
||||||
+-----------+------------+----------------------+
|
+-----------+------------+----------------------+
|
||||||
| SPI | on-chip | spi |
|
| SPI | on-chip | spi |
|
||||||
+-----------+------------+----------------------+
|
+-----------+------------+----------------------+
|
||||||
|
| FLASH | on-chip | flash |
|
||||||
|
+-----------+------------+----------------------+
|
||||||
|
|
||||||
Other hardware features are currently not supported by the port.
|
Other hardware features are currently not supported by the port.
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,sram = &sram0;
|
zephyr,sram = &sram0;
|
||||||
|
zephyr,flash-controller = &flash1;
|
||||||
zephyr,flash = &flash0;
|
zephyr,flash = &flash0;
|
||||||
zephyr,console = &uart9;
|
zephyr,console = &uart9;
|
||||||
zephyr,shell-uart = &uart9;
|
zephyr,shell-uart = &uart9;
|
||||||
|
@ -169,3 +170,16 @@ mikrobus_serial: &uart3 {};
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&flash1 {
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
storage_partition: partition@0 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0X0 DT_SIZE_K(12)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -16,3 +16,5 @@ CONFIG_CONSOLE=y
|
||||||
CONFIG_BUILD_OUTPUT_HEX=y
|
CONFIG_BUILD_OUTPUT_HEX=y
|
||||||
CONFIG_BUILD_NO_GAP_FILL=y
|
CONFIG_BUILD_NO_GAP_FILL=y
|
||||||
CONFIG_CLOCK_CONTROL=y
|
CONFIG_CLOCK_CONTROL=y
|
||||||
|
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
|
|
@ -140,3 +140,8 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_RRAM soc_flash_nrf_rram.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_MRAM soc_flash_nrf_mram.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_MRAM soc_flash_nrf_mram.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NUMAKER_RMC soc_flash_numaker_rmc.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NUMAKER_RMC soc_flash_numaker_rmc.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SI32 flash_si32.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SI32 flash_si32.c)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
|
@ -237,6 +237,8 @@ source "drivers/flash/Kconfig.nrf_mram"
|
||||||
|
|
||||||
source "drivers/flash/Kconfig.numaker_rmc"
|
source "drivers/flash/Kconfig.numaker_rmc"
|
||||||
|
|
||||||
|
source "drivers/flash/Kconfig.renesas_ra"
|
||||||
|
|
||||||
module = FLASH
|
module = FLASH
|
||||||
module-str = flash
|
module-str = flash
|
||||||
source "subsys/logging/Kconfig.template.log_config"
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
28
drivers/flash/Kconfig.renesas_ra
Normal file
28
drivers/flash/Kconfig.renesas_ra
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Renesas RA Family
|
||||||
|
|
||||||
|
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config RA_FLASH_HP
|
||||||
|
bool "RA flash driver"
|
||||||
|
depends on DT_HAS_RENESAS_RA_FLASH_HP_CONTROLLER_ENABLED
|
||||||
|
default y
|
||||||
|
select FLASH_HAS_DRIVER_ENABLED
|
||||||
|
select FLASH_PAGE_LAYOUT
|
||||||
|
select FLASH_HAS_PAGE_LAYOUT
|
||||||
|
select FLASH_HAS_EXPLICIT_ERASE
|
||||||
|
select FLASH_HAS_EX_OP if(SOC_SERIES_RA8M1)
|
||||||
|
select USE_RA_FSP_FLASH_HP
|
||||||
|
help
|
||||||
|
Enable flash driver for RA series
|
||||||
|
|
||||||
|
if RA_FLASH_HP
|
||||||
|
|
||||||
|
config FLASH_RA_WRITE_PROTECT
|
||||||
|
bool "Extended operation for flash write protection control"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enables flash extended operation to enable/disable flash write
|
||||||
|
protection from external devices
|
||||||
|
|
||||||
|
endif # RA_FLASH_HP
|
397
drivers/flash/flash_hp_ra.c
Normal file
397
drivers/flash/flash_hp_ra.c
Normal file
|
@ -0,0 +1,397 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <soc.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/devicetree.h>
|
||||||
|
#include <zephyr/init.h>
|
||||||
|
#include <zephyr/irq.h>
|
||||||
|
#include "flash_hp_ra.h"
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT renesas_ra_flash_hp_controller
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(flash_hp_ra, CONFIG_FLASH_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define ERASE_BLOCK_SIZE_0 DT_PROP(DT_INST(0, renesas_ra_nv_flash), erase_block_size)
|
||||||
|
#define ERASE_BLOCK_SIZE_1 DT_PROP(DT_INST(1, renesas_ra_nv_flash), erase_block_size)
|
||||||
|
|
||||||
|
BUILD_ASSERT((ERASE_BLOCK_SIZE_0 % FLASH_HP_CF_BLOCK_8KB_SIZE) == 0,
|
||||||
|
"erase-block-size expected to be a multiple of a block size");
|
||||||
|
BUILD_ASSERT((ERASE_BLOCK_SIZE_1 % FLASH_HP_DF_BLOCK_SIZE) == 0,
|
||||||
|
"erase-block-size expected to be a multiple of a block size");
|
||||||
|
|
||||||
|
/* Flags, set from Callback function */
|
||||||
|
static volatile struct event_flash g_event_flash = {
|
||||||
|
.erase_complete = false,
|
||||||
|
.write_complete = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
void fcu_frdyi_isr(void);
|
||||||
|
void fcu_fiferr_isr(void);
|
||||||
|
|
||||||
|
static int flash_controller_ra_init(const struct device *dev);
|
||||||
|
static int flash_ra_init(const struct device *dev);
|
||||||
|
static int flash_ra_erase(const struct device *dev, off_t offset, size_t len);
|
||||||
|
static int flash_ra_read(const struct device *dev, off_t offset, void *data, size_t len);
|
||||||
|
static int flash_ra_write(const struct device *dev, off_t offset, const void *data, size_t len);
|
||||||
|
static const struct flash_parameters *flash_ra_get_parameters(const struct device *dev);
|
||||||
|
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||||
|
void flash_ra_page_layout(const struct device *dev, const struct flash_pages_layout **layout,
|
||||||
|
size_t *layout_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_FLASH_EX_OP_ENABLED
|
||||||
|
static int flash_ra_ex_op(const struct device *dev, uint16_t code, const uintptr_t in, void *out);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const struct flash_driver_api flash_ra_api = {
|
||||||
|
.erase = flash_ra_erase,
|
||||||
|
.write = flash_ra_write,
|
||||||
|
.read = flash_ra_read,
|
||||||
|
.get_parameters = flash_ra_get_parameters,
|
||||||
|
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||||
|
.page_layout = flash_ra_page_layout,
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_FLASH_EX_OP_ENABLED
|
||||||
|
.ex_op = flash_ra_ex_op,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct flash_pages_layout flash_ra_layout[5];
|
||||||
|
|
||||||
|
void bgo_callback(flash_callback_args_t *p_args)
|
||||||
|
{
|
||||||
|
if (FLASH_EVENT_ERASE_COMPLETE == p_args->event) {
|
||||||
|
g_event_flash.erase_complete = true;
|
||||||
|
} else {
|
||||||
|
g_event_flash.write_complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool flash_ra_valid_range(off_t area_size, off_t offset, size_t len)
|
||||||
|
{
|
||||||
|
if ((offset < 0) || (offset >= area_size) || ((area_size - offset) < len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flash_ra_read(const struct device *dev, off_t offset, void *data, size_t len)
|
||||||
|
{
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
|
||||||
|
if (!flash_ra_valid_range(flash_data->area_size, offset, len)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("flash: read 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
|
||||||
|
|
||||||
|
memcpy(data, (uint8_t *)(offset + flash_data->area_address), len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flash_ra_erase(const struct device *dev, off_t offset, size_t len)
|
||||||
|
{
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
|
||||||
|
static struct flash_pages_info page_info_off, page_info_len;
|
||||||
|
fsp_err_t err = FSP_ERR_ASSERTION;
|
||||||
|
uint32_t block_num;
|
||||||
|
int rc, rc2;
|
||||||
|
|
||||||
|
if (!flash_ra_valid_range(flash_data->area_size, offset, len)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("flash: erase 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
|
||||||
|
|
||||||
|
rc = flash_get_page_info_by_offs(dev, offset, &page_info_off);
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != page_info_off.start_offset) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc2 = flash_get_page_info_by_offs(dev, (offset + len), &page_info_len);
|
||||||
|
if (rc2 != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_DUAL_BANK_MODE)
|
||||||
|
/* Invalid offset in dual bank mode, this is reversed area. */
|
||||||
|
if ((page_info_off.index > FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_END &&
|
||||||
|
page_info_off.index < FLASH_HP_CF_BLOCK_8KB_HIGH_START) ||
|
||||||
|
(page_info_len.index > FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_END &&
|
||||||
|
page_info_len.index < FLASH_HP_CF_BLOCK_8KB_HIGH_START)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((offset + len) != (page_info_len.start_offset)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_num = (uint32_t)((page_info_len.index) - page_info_off.index);
|
||||||
|
|
||||||
|
if (block_num > 0) {
|
||||||
|
k_sem_take(&dev_ctrl->ctrl_sem, K_FOREVER);
|
||||||
|
|
||||||
|
err = R_FLASH_HP_Erase(&dev_ctrl->flash_ctrl,
|
||||||
|
(long)(flash_data->area_address + offset), block_num);
|
||||||
|
|
||||||
|
if (err != FSP_SUCCESS) {
|
||||||
|
k_sem_give(&dev_ctrl->ctrl_sem);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_data->FlashRegion == DATA_FLASH) {
|
||||||
|
/* Wait for the erase complete event flag, if BGO is SET */
|
||||||
|
if (true == dev_ctrl->fsp_config.data_flash_bgo) {
|
||||||
|
while (!g_event_flash.erase_complete) {
|
||||||
|
k_sleep(K_USEC(10));
|
||||||
|
}
|
||||||
|
g_event_flash.erase_complete = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_give(&dev_ctrl->ctrl_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flash_ra_write(const struct device *dev, off_t offset, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
fsp_err_t err = FSP_ERR_ASSERTION;
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
|
||||||
|
|
||||||
|
if (!flash_ra_valid_range(flash_data->area_size, offset, len)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("flash: write 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
|
||||||
|
|
||||||
|
k_sem_take(&dev_ctrl->ctrl_sem, K_FOREVER);
|
||||||
|
|
||||||
|
err = R_FLASH_HP_Write(&dev_ctrl->flash_ctrl, (uint32_t)data,
|
||||||
|
(long)(offset + flash_data->area_address), len);
|
||||||
|
|
||||||
|
if (err != FSP_SUCCESS) {
|
||||||
|
k_sem_give(&dev_ctrl->ctrl_sem);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_data->FlashRegion == DATA_FLASH) {
|
||||||
|
/* Wait for the write complete event flag, if BGO is SET */
|
||||||
|
if (true == dev_ctrl->fsp_config.data_flash_bgo) {
|
||||||
|
while (!g_event_flash.write_complete) {
|
||||||
|
k_sleep(K_USEC(10));
|
||||||
|
}
|
||||||
|
g_event_flash.write_complete = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_give(&dev_ctrl->ctrl_sem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_ra_page_layout(const struct device *dev, const struct flash_pages_layout **layout,
|
||||||
|
size_t *layout_size)
|
||||||
|
{
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
|
||||||
|
if (flash_data->FlashRegion == DATA_FLASH) {
|
||||||
|
flash_ra_layout[0].pages_count = flash_data->area_size / FLASH_HP_DF_BLOCK_SIZE;
|
||||||
|
flash_ra_layout[0].pages_size = FLASH_HP_DF_BLOCK_SIZE;
|
||||||
|
|
||||||
|
*layout_size = 1;
|
||||||
|
} else {
|
||||||
|
#if defined(CONFIG_DUAL_BANK_MODE)
|
||||||
|
flash_ra_layout[0].pages_count =
|
||||||
|
(FLASH_HP_CF_BLOCK_8KB_LOW_END - FLASH_HP_CF_BLOCK_8KB_LOW_START) + 1;
|
||||||
|
flash_ra_layout[0].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
|
||||||
|
|
||||||
|
flash_ra_layout[1].pages_count = (FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_END -
|
||||||
|
FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_START) +
|
||||||
|
1;
|
||||||
|
flash_ra_layout[1].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
|
||||||
|
|
||||||
|
flash_ra_layout[2].pages_count = FLASH_RESERVED_AREA_NUM;
|
||||||
|
flash_ra_layout[2].pages_size =
|
||||||
|
(FLASH_HP_BANK2_OFFSET -
|
||||||
|
(flash_ra_layout[0].pages_count * flash_ra_layout[0].pages_size) -
|
||||||
|
(flash_ra_layout[1].pages_count * flash_ra_layout[1].pages_size)) /
|
||||||
|
FLASH_RESERVED_AREA_NUM;
|
||||||
|
|
||||||
|
flash_ra_layout[3].pages_count =
|
||||||
|
(FLASH_HP_CF_BLOCK_8KB_HIGH_END - FLASH_HP_CF_BLOCK_8KB_HIGH_START) + 1;
|
||||||
|
flash_ra_layout[3].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
|
||||||
|
|
||||||
|
/* The final block is the dummy block */
|
||||||
|
flash_ra_layout[4].pages_count = (FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_END + 1 -
|
||||||
|
FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_START) +
|
||||||
|
1;
|
||||||
|
flash_ra_layout[4].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
|
||||||
|
|
||||||
|
*layout_size = 5;
|
||||||
|
#else
|
||||||
|
flash_ra_layout[0].pages_count =
|
||||||
|
(FLASH_HP_CF_BLOCK_8KB_LOW_END - FLASH_HP_CF_BLOCK_8KB_LOW_START) + 1;
|
||||||
|
flash_ra_layout[0].pages_size = FLASH_HP_CF_BLOCK_8KB_SIZE;
|
||||||
|
flash_ra_layout[1].pages_count =
|
||||||
|
(FLASH_HP_CF_BLOCK_32KB_LINEAR_END - FLASH_HP_CF_BLOCK_32KB_LINEAR_START) +
|
||||||
|
1;
|
||||||
|
flash_ra_layout[1].pages_size = FLASH_HP_CF_BLOCK_32KB_SIZE;
|
||||||
|
|
||||||
|
*layout_size = 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
*layout = flash_ra_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct flash_parameters *flash_ra_get_parameters(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct flash_hp_ra_config *config = dev->config;
|
||||||
|
|
||||||
|
return &config->flash_ra_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct flash_hp_ra_controller flash_hp_ra_controller = {
|
||||||
|
.fsp_config = {
|
||||||
|
.data_flash_bgo = true,
|
||||||
|
.p_callback = bgo_callback,
|
||||||
|
.p_context = NULL,
|
||||||
|
.irq = (IRQn_Type)DT_INST_IRQ_BY_NAME(0, frdyi, irq),
|
||||||
|
.err_irq = (IRQn_Type)DT_INST_IRQ_BY_NAME(0, fiferr, irq),
|
||||||
|
.err_ipl = DT_INST_IRQ_BY_NAME(0, fiferr, priority),
|
||||||
|
.ipl = DT_INST_IRQ_BY_NAME(0, frdyi, priority),
|
||||||
|
}};
|
||||||
|
|
||||||
|
#ifdef CONFIG_FLASH_EX_OP_ENABLED
|
||||||
|
static int flash_ra_ex_op(const struct device *dev, uint16_t code, const uintptr_t in, void *out)
|
||||||
|
{
|
||||||
|
int err = -ENOTSUP;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
#if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
|
||||||
|
case FLASH_RA_EX_OP_WRITE_PROTECT:
|
||||||
|
err = flash_ra_ex_op_write_protect(dev, in, out);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_FLASH_RA_WRITE_PROTECT */
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int flash_ra_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct device *dev_ctrl = DEVICE_DT_INST_GET(0);
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
|
||||||
|
if (!device_is_ready(dev_ctrl)) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_data->area_address == FLASH_HP_DF_START) {
|
||||||
|
flash_data->FlashRegion = DATA_FLASH;
|
||||||
|
} else {
|
||||||
|
flash_data->FlashRegion = CODE_FLASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_data->controller = dev_ctrl->data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flash_controller_ra_irq_config_func(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
R_ICU->IELSR[DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, irq)] = ELC_EVENT_FCU_FRDYI;
|
||||||
|
R_ICU->IELSR[DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, irq)] = ELC_EVENT_FCU_FIFERR;
|
||||||
|
|
||||||
|
IRQ_CONNECT(DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, irq),
|
||||||
|
DT_IRQ_BY_NAME(DT_DRV_INST(0), frdyi, priority), fcu_frdyi_isr,
|
||||||
|
DEVICE_DT_INST_GET(0), 0);
|
||||||
|
IRQ_CONNECT(DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, irq),
|
||||||
|
DT_IRQ_BY_NAME(DT_DRV_INST(0), fiferr, priority), fcu_fiferr_isr,
|
||||||
|
DEVICE_DT_INST_GET(0), 0);
|
||||||
|
|
||||||
|
irq_enable(DT_INST_IRQ_BY_NAME(0, frdyi, irq));
|
||||||
|
irq_enable(DT_INST_IRQ_BY_NAME(0, fiferr, irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flash_controller_ra_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
fsp_err_t err = FSP_SUCCESS;
|
||||||
|
const struct flash_hp_ra_controller_config *cfg = dev->config;
|
||||||
|
struct flash_hp_ra_controller *data = dev->data;
|
||||||
|
|
||||||
|
cfg->irq_config(dev);
|
||||||
|
|
||||||
|
err = R_FLASH_HP_Open(&data->flash_ctrl, &data->fsp_config);
|
||||||
|
|
||||||
|
if (err != FSP_SUCCESS) {
|
||||||
|
LOG_DBG("flash: open error=%d", (int)err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_init(&data->ctrl_sem, 1, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct flash_hp_ra_controller_config flash_hp_ra_controller_config = {
|
||||||
|
.irq_config = flash_controller_ra_irq_config_func,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RA_FLASH_INIT(index) \
|
||||||
|
struct flash_hp_ra_data flash_hp_ra_data_##index = {.area_address = DT_REG_ADDR(index), \
|
||||||
|
.area_size = DT_REG_SIZE(index)}; \
|
||||||
|
static struct flash_hp_ra_config flash_hp_ra_config_##index = { \
|
||||||
|
.flash_ra_parameters = { \
|
||||||
|
.write_block_size = GET_SIZE( \
|
||||||
|
(CHECK_EQ(DT_REG_ADDR(index), FLASH_HP_DF_START)), 4, 128), \
|
||||||
|
.erase_value = 0xff, \
|
||||||
|
}}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_DEFINE(index, flash_ra_init, NULL, &flash_hp_ra_data_##index, \
|
||||||
|
&flash_hp_ra_config_##index, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, \
|
||||||
|
&flash_ra_api);
|
||||||
|
|
||||||
|
DT_FOREACH_CHILD_STATUS_OKAY(DT_DRV_INST(0), RA_FLASH_INIT);
|
||||||
|
|
||||||
|
/* define the flash controller device just to run the init. */
|
||||||
|
DEVICE_DT_DEFINE(DT_DRV_INST(0), flash_controller_ra_init, NULL, &flash_hp_ra_controller,
|
||||||
|
&flash_hp_ra_controller_config, PRE_KERNEL_1, CONFIG_FLASH_INIT_PRIORITY, NULL);
|
92
drivers/flash/flash_hp_ra.h
Normal file
92
drivers/flash/flash_hp_ra.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_FLASH_RA_HP_H_
|
||||||
|
#define ZEPHYR_DRIVERS_FLASH_RA_HP_H_
|
||||||
|
|
||||||
|
#include <zephyr/drivers/flash.h>
|
||||||
|
#include <instances/r_flash_hp.h>
|
||||||
|
#include <api/r_flash_api.h>
|
||||||
|
#include <zephyr/drivers/flash/ra_flash_api_extensions.h>
|
||||||
|
|
||||||
|
#define CHECK_EQ(val1, val2) ((val1) == (val2) ? 1 : 0)
|
||||||
|
#define GET_SIZE(COND, value, default_value) ((COND) ? (value) : (default_value))
|
||||||
|
|
||||||
|
#define FLASH_HP_BANK2_OFFSET \
|
||||||
|
(BSP_FEATURE_FLASH_HP_CF_DUAL_BANK_START - BSP_FEATURE_FLASH_CODE_FLASH_START)
|
||||||
|
|
||||||
|
#define FLASH_HP_CF_BLOCK_8KB_SIZE BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_SIZE BSP_FEATURE_FLASH_HP_CF_REGION1_BLOCK_SIZE
|
||||||
|
#define FLASH_HP_DF_BLOCK_SIZE BSP_FEATURE_FLASH_HP_DF_BLOCK_SIZE
|
||||||
|
#define FLASH_HP_DF_START BSP_FEATURE_FLASH_DATA_FLASH_START
|
||||||
|
|
||||||
|
#define FLASH_HP_CF_BLOCK_8KB_LOW_START (0)
|
||||||
|
#define FLASH_HP_CF_BLOCK_8KB_LOW_END (7)
|
||||||
|
#define FLASH_HP_CF_BLOCK_8KB_HIGH_START (70)
|
||||||
|
#define FLASH_HP_CF_BLOCK_8KB_HIGH_END (77)
|
||||||
|
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_LINEAR_START (8)
|
||||||
|
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_START (8)
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_START (78)
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOC_R7FA8M1AHECBD)
|
||||||
|
#define FLASH_RESERVED_AREA_NUM (33)
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_LINEAR_END (68)
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_DUAL_LOW_END (36)
|
||||||
|
#define FLASH_HP_CF_BLOCK_32KB_DUAL_HIGH_END (106)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_FLASH_EX_OP_ENABLED)
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_BPS (0x1300A1C0U)
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_BPS_SEC (0x0300A240U)
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_BPS_SEL (0x0300A2C0U)
|
||||||
|
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_PBPS (0x1300A1E0U)
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_PBPS_SEC (0x0300A260U)
|
||||||
|
#endif /* CONFIG_FLASH_EX_OP_ENABLED */
|
||||||
|
|
||||||
|
/* Zero based offset into g_configuration_area_data[] for BPS */
|
||||||
|
#define FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET (0U)
|
||||||
|
|
||||||
|
enum flash_region {
|
||||||
|
CODE_FLASH,
|
||||||
|
DATA_FLASH,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*irq_config_func_t)(const struct device *dev);
|
||||||
|
|
||||||
|
struct flash_hp_ra_controller {
|
||||||
|
struct st_flash_hp_instance_ctrl flash_ctrl;
|
||||||
|
struct k_sem ctrl_sem;
|
||||||
|
struct st_flash_cfg fsp_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flash_hp_ra_controller_config {
|
||||||
|
irq_config_func_t irq_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flash_hp_ra_data {
|
||||||
|
struct flash_hp_ra_controller *controller;
|
||||||
|
enum flash_region FlashRegion;
|
||||||
|
uint32_t area_address;
|
||||||
|
uint32_t area_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flash_hp_ra_config {
|
||||||
|
struct flash_parameters flash_ra_parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct event_flash {
|
||||||
|
volatile bool erase_complete;
|
||||||
|
volatile bool write_complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
|
||||||
|
int flash_ra_ex_op_write_protect(const struct device *dev, const uintptr_t in, void *out);
|
||||||
|
#endif /*CONFIG_FLASH_RA_WRITE_PROTECT*/
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_FLASH_RA_HP_H_ */
|
379
drivers/flash/flash_hp_ra_ex_op.c
Normal file
379
drivers/flash/flash_hp_ra_ex_op.c
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/flash/ra_flash_api_extensions.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
#include <zephyr/syscall.h>
|
||||||
|
#include <zephyr/syscall_handler.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include "flash_hp_ra.h"
|
||||||
|
|
||||||
|
#define FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT (8U)
|
||||||
|
|
||||||
|
#if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
|
||||||
|
extern uint16_t g_configuration_area_data[FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT];
|
||||||
|
#endif
|
||||||
|
extern fsp_err_t
|
||||||
|
flash_hp_enter_pe_cf_mode(flash_hp_instance_ctrl_t *const p_ctrl) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
extern fsp_err_t flash_hp_stop(void) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
extern fsp_err_t flash_hp_configuration_area_write(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint32_t fsaddr) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
extern fsp_err_t flash_hp_check_errors(fsp_err_t previous_error, uint32_t error_bits,
|
||||||
|
fsp_err_t return_error) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
extern fsp_err_t flash_hp_pe_mode_exit(void) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_ns(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_val_ns, uint8_t *pbps_val_ns,
|
||||||
|
uint32_t size) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_sec(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_val_sec, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t size) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_sel(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_sel_val,
|
||||||
|
uint32_t size) PLACE_IN_RAM_SECTION;
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_ns(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_val_ns, uint8_t *pbps_val_ns,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
/* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
|
||||||
|
int key = irq_lock();
|
||||||
|
|
||||||
|
/* Update Flash state and enter Code Flash P/E mode */
|
||||||
|
fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
|
||||||
|
|
||||||
|
FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
|
||||||
|
|
||||||
|
memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
|
||||||
|
if (bps_val_ns != NULL) {
|
||||||
|
memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_val_ns,
|
||||||
|
size);
|
||||||
|
err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS);
|
||||||
|
err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
|
||||||
|
if (pbps_val_ns != NULL) {
|
||||||
|
memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], pbps_val_ns,
|
||||||
|
size);
|
||||||
|
err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_PBPS);
|
||||||
|
err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return to read mode*/
|
||||||
|
fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
|
||||||
|
|
||||||
|
if (err == FSP_SUCCESS) {
|
||||||
|
err = pe_exit_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable interrupts after code flash operations are complete. */
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_sec(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_val_sec, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
/* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
|
||||||
|
int key = irq_lock();
|
||||||
|
/* Update Flash state and enter Code Flash P/E mode */
|
||||||
|
fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
|
||||||
|
|
||||||
|
FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
|
||||||
|
|
||||||
|
memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
|
||||||
|
if (bps_val_sec != NULL) {
|
||||||
|
memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_val_sec,
|
||||||
|
size);
|
||||||
|
err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS_SEC);
|
||||||
|
err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
|
||||||
|
if (pbps_val_sec != NULL) {
|
||||||
|
memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], pbps_val_sec,
|
||||||
|
size);
|
||||||
|
err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_PBPS_SEC);
|
||||||
|
err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return to read mode*/
|
||||||
|
fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
|
||||||
|
|
||||||
|
if (err == FSP_SUCCESS) {
|
||||||
|
err = pe_exit_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable interrupts after code flash operations are complete. */
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fsp_err_t flash_hp_set_block_protect_sel(flash_hp_instance_ctrl_t *p_ctrl,
|
||||||
|
uint8_t *bps_sel_val, uint32_t size)
|
||||||
|
{
|
||||||
|
/* Disable interrupts to prevent vector table access while code flash is in P/E mode. */
|
||||||
|
int key = irq_lock();
|
||||||
|
|
||||||
|
/* Update Flash state and enter Code Flash P/E mode */
|
||||||
|
fsp_err_t err = flash_hp_enter_pe_cf_mode(p_ctrl);
|
||||||
|
|
||||||
|
FSP_ERROR_RETURN(err == FSP_SUCCESS, err);
|
||||||
|
|
||||||
|
memset(g_configuration_area_data, UINT8_MAX, sizeof(g_configuration_area_data));
|
||||||
|
memcpy(&g_configuration_area_data[FLASH_HP_FCU_CONFIG_SET_BPS_OFFSET], bps_sel_val, size);
|
||||||
|
err = flash_hp_configuration_area_write(p_ctrl, FLASH_HP_FCU_CONFIG_SET_BPS_SEL);
|
||||||
|
err = flash_hp_check_errors(err, 0, FSP_ERR_WRITE_FAILED);
|
||||||
|
|
||||||
|
/* Return to read mode*/
|
||||||
|
fsp_err_t pe_exit_err = flash_hp_pe_mode_exit();
|
||||||
|
|
||||||
|
if (err == FSP_SUCCESS) {
|
||||||
|
err = pe_exit_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable interrupts after code flash operations are complete. */
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fsp_err_t R_FLASH_HP_BlockProtectSet(flash_ctrl_t *const p_api_ctrl, uint8_t *bps_val_ns,
|
||||||
|
uint8_t *bps_val_sec, uint8_t *bps_val_sel,
|
||||||
|
uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
static fsp_err_t R_FLASH_HP_BlockProtectGet(flash_ctrl_t *const p_api_ctrl, uint32_t *bps_val_ns,
|
||||||
|
uint32_t *bps_val_sec, uint8_t *bps_val_sel,
|
||||||
|
uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t *size);
|
||||||
|
|
||||||
|
int flash_ra_block_protect_set(const struct device *dev,
|
||||||
|
const struct flash_ra_ex_write_protect_in *request);
|
||||||
|
|
||||||
|
int flash_ra_block_protect_get(const struct device *dev,
|
||||||
|
struct flash_ra_ex_write_protect_out *response);
|
||||||
|
|
||||||
|
static fsp_err_t R_FLASH_HP_BlockProtectSet(flash_ctrl_t *const p_api_ctrl, uint8_t *bps_val_ns,
|
||||||
|
uint8_t *bps_val_sec, uint8_t *bps_val_sel,
|
||||||
|
uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
flash_hp_instance_ctrl_t *p_ctrl = (flash_hp_instance_ctrl_t *)p_api_ctrl;
|
||||||
|
fsp_err_t err = FSP_SUCCESS;
|
||||||
|
|
||||||
|
#if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
|
||||||
|
|
||||||
|
/* if non-secure BPS (PBPS) buffers are not null and size is smaller than 16 bytes */
|
||||||
|
if (((bps_val_ns != NULL) || (pbps_val_ns != NULL)) &&
|
||||||
|
(size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
|
||||||
|
err = flash_hp_set_block_protect_ns(p_ctrl, bps_val_ns, pbps_val_ns, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if secure BPS (PBPS) buffers are not null and size is smaller than 16 bytes */
|
||||||
|
if (((bps_val_sec != NULL) || (pbps_val_sec != NULL)) &&
|
||||||
|
(size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
|
||||||
|
err = flash_hp_set_block_protect_sec(p_ctrl, bps_val_sec, pbps_val_sec, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if BPS SEL buffer is not null and size is smaller than 16 bytes */
|
||||||
|
if ((bps_val_sel != NULL) &&
|
||||||
|
(size <= (sizeof(uint16_t) * FLASH_HP_CONFIG_SET_ACCESS_WORD_CNT))) {
|
||||||
|
err = flash_hp_set_block_protect_sel(p_ctrl, bps_val_sel, size);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
err = FSP_ERR_UNSUPPORTED; /* For consistency with _LP API we return error if Code Flash */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fsp_err_t R_FLASH_HP_BlockProtectGet(flash_ctrl_t *const p_api_ctrl, uint32_t *bps_val_ns,
|
||||||
|
uint32_t *bps_val_sec, uint8_t *bps_val_sel,
|
||||||
|
uint8_t *pbps_val_ns, uint8_t *pbps_val_sec,
|
||||||
|
uint32_t *size)
|
||||||
|
{
|
||||||
|
fsp_err_t err = FSP_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
|
#if (DT_PROP(DT_NODELABEL(flash0), renesas_programming_enable))
|
||||||
|
|
||||||
|
err = FSP_SUCCESS;
|
||||||
|
|
||||||
|
if (bps_val_ns != NULL) {
|
||||||
|
bps_val_ns[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 0));
|
||||||
|
bps_val_ns[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 3));
|
||||||
|
bps_val_ns[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 7));
|
||||||
|
bps_val_ns[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS + 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bps_val_sec != NULL) {
|
||||||
|
bps_val_sec[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 0));
|
||||||
|
bps_val_sec[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 3));
|
||||||
|
bps_val_sec[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 7));
|
||||||
|
bps_val_sec[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEC + 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bps_val_sel != NULL) {
|
||||||
|
bps_val_sel[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 0));
|
||||||
|
bps_val_sel[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 3));
|
||||||
|
bps_val_sel[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 7));
|
||||||
|
bps_val_sel[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_BPS_SEL + 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbps_val_ns != NULL) {
|
||||||
|
pbps_val_ns[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 0));
|
||||||
|
pbps_val_ns[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 3));
|
||||||
|
pbps_val_ns[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 7));
|
||||||
|
pbps_val_ns[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS + 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbps_val_sec != NULL) {
|
||||||
|
pbps_val_sec[0] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 0));
|
||||||
|
pbps_val_sec[1] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 3));
|
||||||
|
pbps_val_sec[2] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 7));
|
||||||
|
pbps_val_sec[3] = *((uint32_t *)(FLASH_HP_FCU_CONFIG_SET_PBPS_SEC + 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != NULL) {
|
||||||
|
*size = 4;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FSP_PARAMETER_NOT_USED(p_api_ctrl);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
|
||||||
|
int flash_ra_block_protect_get(const struct device *dev,
|
||||||
|
struct flash_ra_ex_write_protect_out *response)
|
||||||
|
{
|
||||||
|
fsp_err_t err = FSP_ERR_ASSERTION;
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
|
||||||
|
flash_ra_cf_block_map bps_ns;
|
||||||
|
|
||||||
|
/* get the current non-secure BPS register values */
|
||||||
|
err = R_FLASH_HP_BlockProtectGet(&dev_ctrl->flash_ctrl, (uint32_t *)&bps_ns, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
memcpy(&response->protected_enabled, &bps_ns, sizeof(flash_ra_cf_block_map));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flash_ra_ex_op_write_protect(const struct device *dev, const uintptr_t in, void *out)
|
||||||
|
{
|
||||||
|
const struct flash_ra_ex_write_protect_in *request =
|
||||||
|
(const struct flash_ra_ex_write_protect_in *)in;
|
||||||
|
struct flash_ra_ex_write_protect_out *result = (struct flash_ra_ex_write_protect_out *)out;
|
||||||
|
|
||||||
|
int rc = 0, rc2 = 0;
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
bool syscall_trap = z_syscall_trap();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (request != NULL) {
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
struct flash_ra_ex_write_protect_in copy_in;
|
||||||
|
|
||||||
|
if (syscall_trap) {
|
||||||
|
Z_OOPS(z_user_from_copy(©_in, request, sizeof(copy_in)));
|
||||||
|
request = ©_in;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* if both enable and disable are set */
|
||||||
|
if ((request->protect_enable.BPS[0] & request->protect_disable.BPS[0]) ||
|
||||||
|
(request->protect_enable.BPS[1] & request->protect_disable.BPS[1]) ||
|
||||||
|
(request->protect_enable.BPS[2] & request->protect_disable.BPS[2]) ||
|
||||||
|
(request->protect_enable.BPS[3] & request->protect_disable.BPS[3])) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = flash_ra_block_protect_set(dev, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != NULL) {
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
struct flash_ra_ex_write_protect_out copy_out;
|
||||||
|
|
||||||
|
if (syscall_trap) {
|
||||||
|
result = ©_out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rc2 = flash_ra_block_protect_get(dev, result);
|
||||||
|
if (!rc) {
|
||||||
|
rc = rc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
if (syscall_trap) {
|
||||||
|
Z_OOPS(z_user_to_copy(out, result, sizeof(copy_out)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flash_ra_block_protect_set(const struct device *dev,
|
||||||
|
const struct flash_ra_ex_write_protect_in *request)
|
||||||
|
{
|
||||||
|
fsp_err_t err = FSP_ERR_ASSERTION;
|
||||||
|
struct flash_hp_ra_data *flash_data = dev->data;
|
||||||
|
struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
|
||||||
|
flash_ra_cf_block_map bps_ns;
|
||||||
|
|
||||||
|
/* get the current non-secure BPS register values */
|
||||||
|
err = R_FLASH_HP_BlockProtectGet(&dev_ctrl->flash_ctrl, (uint32_t *)&bps_ns, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (err != FSP_SUCCESS) {
|
||||||
|
__ASSERT(false, "flash: block get current value error =%d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable block protect */
|
||||||
|
bps_ns.BPS[0] &= ~(request->protect_enable.BPS[0]);
|
||||||
|
bps_ns.BPS[1] &= ~(request->protect_enable.BPS[1]);
|
||||||
|
bps_ns.BPS[2] &= ~(request->protect_enable.BPS[2]);
|
||||||
|
bps_ns.BPS[3] &= ~(request->protect_enable.BPS[3]);
|
||||||
|
|
||||||
|
/* disable block protect */
|
||||||
|
bps_ns.BPS[0] |= (request->protect_disable.BPS[0]);
|
||||||
|
bps_ns.BPS[1] |= (request->protect_disable.BPS[1]);
|
||||||
|
bps_ns.BPS[2] |= (request->protect_disable.BPS[2]);
|
||||||
|
bps_ns.BPS[3] |= (request->protect_disable.BPS[3]);
|
||||||
|
|
||||||
|
/* reset default all from non-secure */
|
||||||
|
err = R_FLASH_HP_BlockProtectSet(&dev_ctrl->flash_ctrl, (uint8_t *)&bps_ns, NULL, NULL,
|
||||||
|
NULL, NULL, sizeof(bps_ns));
|
||||||
|
|
||||||
|
if (err != FSP_SUCCESS) {
|
||||||
|
__ASSERT(false, "flash: block protect error=%d", err);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_FLASH_RA_WRITE_PROTECT */
|
|
@ -8,10 +8,21 @@
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
soc {
|
soc {
|
||||||
flash-controller@407fe000 {
|
flash-controller@40100000 {
|
||||||
flash0: flash@2000000 {
|
flash0: flash@2000000 {
|
||||||
compatible = "soc-nv-flash";
|
compatible = "renesas,ra-nv-flash";
|
||||||
reg = <0x02000000 DT_SIZE_M(2)>;
|
reg = <0x02000000 DT_SIZE_K(2016)>;
|
||||||
|
write-block-size = <128>;
|
||||||
|
erase-block-size = <8192>;
|
||||||
|
renesas,programming-enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
flash1: flash@27000000 {
|
||||||
|
compatible = "renesas,ra-nv-flash";
|
||||||
|
reg = <0x27000000 DT_SIZE_K(12)>;
|
||||||
|
write-block-size = <4>;
|
||||||
|
erase-block-size = <64>;
|
||||||
|
renesas,programming-enable;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -271,10 +271,13 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flash-controller@407fe000 {
|
flash: flash-controller@40100000 {
|
||||||
reg = <0x407fe000 0x1000>;
|
compatible = "renesas,ra-flash-hp-controller";
|
||||||
|
reg = <0x40100000 0x20000>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
interrupts = <38 2>, <39 2>;
|
||||||
|
interrupt-names = "frdyi", "fiferr";
|
||||||
};
|
};
|
||||||
|
|
||||||
adc0: adc@40332000 {
|
adc0: adc@40332000 {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: Renesas RA family flash high-performance controller
|
||||||
|
|
||||||
|
compatible: "renesas,ra-flash-hp-controller"
|
||||||
|
|
||||||
|
include: flash-controller.yaml
|
14
dts/bindings/mtd/renesas,ra-nv-flash.yaml
Normal file
14
dts/bindings/mtd/renesas,ra-nv-flash.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Flash memory binding of Renesas RA family
|
||||||
|
|
||||||
|
include: [base.yaml, soc-nv-flash.yaml]
|
||||||
|
|
||||||
|
compatible: "renesas,ra-nv-flash"
|
||||||
|
|
||||||
|
properties:
|
||||||
|
renesas,programming-enable:
|
||||||
|
type: boolean
|
||||||
|
description: Enable flash programming configuration
|
146
include/zephyr/drivers/flash/ra_flash_api_extensions.h
Normal file
146
include/zephyr/drivers/flash/ra_flash_api_extensions.h
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ZEPHYR_INCLUDE_DRIVERS_FLASH_RA_EXTENSIONS_H__
|
||||||
|
#define __ZEPHYR_INCLUDE_DRIVERS_FLASH_RA_EXTENSIONS_H__
|
||||||
|
|
||||||
|
#include <zephyr/drivers/flash.h>
|
||||||
|
|
||||||
|
enum ra_ex_ops {
|
||||||
|
FLASH_RA_EX_OP_WRITE_PROTECT = FLASH_EX_OP_VENDOR_BASE,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
uint32_t BPS[4];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t b000: 1;
|
||||||
|
uint32_t b001: 1;
|
||||||
|
uint32_t b002: 1;
|
||||||
|
uint32_t b003: 1;
|
||||||
|
uint32_t b004: 1;
|
||||||
|
uint32_t b005: 1;
|
||||||
|
uint32_t b006: 1;
|
||||||
|
uint32_t b007: 1;
|
||||||
|
uint32_t b008: 1;
|
||||||
|
uint32_t b009: 1;
|
||||||
|
uint32_t b010: 1;
|
||||||
|
uint32_t b011: 1;
|
||||||
|
uint32_t b012: 1;
|
||||||
|
uint32_t b013: 1;
|
||||||
|
uint32_t b014: 1;
|
||||||
|
uint32_t b015: 1;
|
||||||
|
uint32_t b016: 1;
|
||||||
|
uint32_t b017: 1;
|
||||||
|
uint32_t b018: 1;
|
||||||
|
uint32_t b019: 1;
|
||||||
|
uint32_t b020: 1;
|
||||||
|
uint32_t b021: 1;
|
||||||
|
uint32_t b022: 1;
|
||||||
|
uint32_t b023: 1;
|
||||||
|
uint32_t b024: 1;
|
||||||
|
uint32_t b025: 1;
|
||||||
|
uint32_t b026: 1;
|
||||||
|
uint32_t b027: 1;
|
||||||
|
uint32_t b028: 1;
|
||||||
|
uint32_t b029: 1;
|
||||||
|
uint32_t b030: 1;
|
||||||
|
uint32_t b031: 1;
|
||||||
|
uint32_t b032: 1;
|
||||||
|
uint32_t b033: 1;
|
||||||
|
uint32_t b034: 1;
|
||||||
|
uint32_t b035: 1;
|
||||||
|
uint32_t b036: 1;
|
||||||
|
uint32_t b037: 1;
|
||||||
|
uint32_t b038: 1;
|
||||||
|
uint32_t b039: 1;
|
||||||
|
uint32_t b040: 1;
|
||||||
|
uint32_t b041: 1;
|
||||||
|
uint32_t b042: 1;
|
||||||
|
uint32_t b043: 1;
|
||||||
|
uint32_t b044: 1;
|
||||||
|
uint32_t b045: 1;
|
||||||
|
uint32_t b046: 1;
|
||||||
|
uint32_t b047: 1;
|
||||||
|
uint32_t b048: 1;
|
||||||
|
uint32_t b049: 1;
|
||||||
|
uint32_t b050: 1;
|
||||||
|
uint32_t b051: 1;
|
||||||
|
uint32_t b052: 1;
|
||||||
|
uint32_t b053: 1;
|
||||||
|
uint32_t b054: 1;
|
||||||
|
uint32_t b055: 1;
|
||||||
|
uint32_t b056: 1;
|
||||||
|
uint32_t b057: 1;
|
||||||
|
uint32_t b058: 1;
|
||||||
|
uint32_t b059: 1;
|
||||||
|
uint32_t b060: 1;
|
||||||
|
uint32_t b061: 1;
|
||||||
|
uint32_t b062: 1;
|
||||||
|
uint32_t b063: 1;
|
||||||
|
uint32_t b064: 1;
|
||||||
|
uint32_t b065: 1;
|
||||||
|
uint32_t b066: 1;
|
||||||
|
uint32_t b067: 1;
|
||||||
|
uint32_t b068: 1;
|
||||||
|
uint32_t b069: 1;
|
||||||
|
uint32_t b070: 1;
|
||||||
|
uint32_t b071: 1;
|
||||||
|
uint32_t b072: 1;
|
||||||
|
uint32_t b073: 1;
|
||||||
|
uint32_t b074: 1;
|
||||||
|
uint32_t b075: 1;
|
||||||
|
uint32_t b076: 1;
|
||||||
|
uint32_t b077: 1;
|
||||||
|
uint32_t b078: 1;
|
||||||
|
uint32_t b079: 1;
|
||||||
|
uint32_t b080: 1;
|
||||||
|
uint32_t b081: 1;
|
||||||
|
uint32_t b082: 1;
|
||||||
|
uint32_t b083: 1;
|
||||||
|
uint32_t b084: 1;
|
||||||
|
uint32_t b085: 1;
|
||||||
|
uint32_t b086: 1;
|
||||||
|
uint32_t b087: 1;
|
||||||
|
uint32_t b088: 1;
|
||||||
|
uint32_t b089: 1;
|
||||||
|
uint32_t b090: 1;
|
||||||
|
uint32_t b091: 1;
|
||||||
|
uint32_t b092: 1;
|
||||||
|
uint32_t b093: 1;
|
||||||
|
uint32_t b094: 1;
|
||||||
|
uint32_t b095: 1;
|
||||||
|
uint32_t b096: 1;
|
||||||
|
uint32_t b097: 1;
|
||||||
|
uint32_t b098: 1;
|
||||||
|
uint32_t b099: 1;
|
||||||
|
uint32_t b100: 1;
|
||||||
|
uint32_t b101: 1;
|
||||||
|
uint32_t b102: 1;
|
||||||
|
uint32_t b103: 1;
|
||||||
|
uint32_t b104: 1;
|
||||||
|
uint32_t b105: 1;
|
||||||
|
uint32_t b106: 1;
|
||||||
|
uint32_t: 21;
|
||||||
|
} BPS_b;
|
||||||
|
};
|
||||||
|
} flash_ra_cf_block_map;
|
||||||
|
|
||||||
|
#if defined(CONFIG_FLASH_RA_WRITE_PROTECT)
|
||||||
|
typedef struct flash_ra_ex_write_protect_in {
|
||||||
|
flash_ra_cf_block_map protect_enable;
|
||||||
|
flash_ra_cf_block_map protect_disable;
|
||||||
|
flash_ra_cf_block_map protect_permanent;
|
||||||
|
} flash_ra_ex_write_protect_in_t;
|
||||||
|
|
||||||
|
typedef struct flash_ra_ex_write_protect_out {
|
||||||
|
flash_ra_cf_block_map protected_enabled;
|
||||||
|
flash_ra_cf_block_map protected_premanent;
|
||||||
|
} flash_ra_ex_write_protect_out_t;
|
||||||
|
#endif /* CONFIG_FLASH_RA_WRITE_PROTECT */
|
||||||
|
|
||||||
|
#endif
|
|
@ -53,3 +53,8 @@ config USE_RA_FSP_SPI_B
|
||||||
bool
|
bool
|
||||||
help
|
help
|
||||||
Enable RA FSP SPI-B driver
|
Enable RA FSP SPI-B driver
|
||||||
|
|
||||||
|
config USE_RA_FSP_FLASH_HP
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Enable RA FSP FLASH HP driver
|
||||||
|
|
|
@ -9,4 +9,8 @@ config NUM_IRQS
|
||||||
config PINCTRL
|
config PINCTRL
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
# Set to the minimal size of data which can be written.
|
||||||
|
config FLASH_FILL_BUFFER_SIZE
|
||||||
|
default 128
|
||||||
|
|
||||||
endif # SOC_SERIES_RA8M1
|
endif # SOC_SERIES_RA8M1
|
||||||
|
|
|
@ -19,3 +19,9 @@ config SOC_SERIES
|
||||||
|
|
||||||
config SOC
|
config SOC
|
||||||
default "r7fa8m1ahecbd" if SOC_R7FA8M1AHECBD
|
default "r7fa8m1ahecbd" if SOC_R7FA8M1AHECBD
|
||||||
|
|
||||||
|
config DUAL_BANK_MODE
|
||||||
|
bool "Dual bank mode"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable dual bank mode
|
||||||
|
|
20
tests/drivers/flash/common/boards/ek_ra8m1.overlay
Normal file
20
tests/drivers/flash/common/boards/ek_ra8m1.overlay
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/delete-node/ &storage_partition;
|
||||||
|
|
||||||
|
&flash0 {
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* Set the 2 last block of storage. */
|
||||||
|
storage_partition: partition@1E8000 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0x1E8000 DT_SIZE_K(64)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue