driver: flash: add flash driver for the RV32M1 SOC

Add driver and device tree for the flash controller for the RV32M1 SOC

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
Lyle Zhu 2019-05-22 23:07:50 +08:00 committed by Maureen Helm
commit cc2e176bb6
9 changed files with 224 additions and 0 deletions

View file

@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM flash_sam.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_NATIVE_POSIX flash_native_posix.c) zephyr_library_sources_ifdef(CONFIG_FLASH_NATIVE_POSIX flash_native_posix.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c)
if(CONFIG_CLOCK_CONTROL_STM32_CUBE) if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
zephyr_sources(flash_stm32.c) zephyr_sources(flash_stm32.c)

View file

@ -69,4 +69,6 @@ source "drivers/flash/Kconfig.w25qxxdv"
source "drivers/flash/Kconfig.simulator" source "drivers/flash/Kconfig.simulator"
source "drivers/flash/Kconfig.rv32m1"
endif # FLASH endif # FLASH

View file

@ -0,0 +1,17 @@
#
# Copyright (c) 2019 NXP
#
# SPDX-License-Identifier: Apache-2.0
#
config SOC_FLASH_RV32M1
bool "RV32M1 flash shim driver"
depends on HAS_RV32M1_FTFX
select FLASH_HAS_PAGE_LAYOUT
select FLASH_HAS_DRIVER_ENABLED
help
Enables the RV32M1 flash shim driver.
WARNING: This driver will disable the system interrupts for
the duration of the flash erase/write operations. This will
have an impact on the overall system performance - whether
this is acceptable or not will depend on the use case.

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2016 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <device.h>
#include <string.h>
#include <flash.h>
#include <errno.h>
#include <init.h>
#include <soc.h>
#include "flash_priv.h"
#include "fsl_common.h"
#include "fsl_flash.h"
#define CONFIG_FLASH_SIZE DT_FLASH_SIZE
struct flash_priv {
flash_config_t config;
/*
* HACK: flash write protection is managed in software.
*/
struct k_sem write_lock;
u32_t pflash_block_base;
};
/*
* Interrupt vectors could be executed from flash hence the need for locking.
* The underlying MCUX driver takes care of copying the functions to SRAM.
*
* For more information, see the application note below on Read-While-Write
* http://cache.freescale.com/files/32bit/doc/app_note/AN4695.pdf
*
*/
static int flash_mcux_erase(struct device *dev, off_t offset, size_t len)
{
struct flash_priv *priv = dev->driver_data;
u32_t addr;
status_t rc;
unsigned int key;
if (k_sem_take(&priv->write_lock, K_NO_WAIT)) {
return -EACCES;
}
addr = offset + priv->pflash_block_base;
key = irq_lock();
rc = FLASH_Erase(&priv->config, addr, len, kFLASH_ApiEraseKey);
irq_unlock(key);
k_sem_give(&priv->write_lock);
return (rc == kStatus_Success) ? 0 : -EINVAL;
}
static int flash_mcux_read(struct device *dev, off_t offset,
void *data, size_t len)
{
struct flash_priv *priv = dev->driver_data;
u32_t addr;
/*
* The MCUX supports different flash chips whose valid ranges are
* hidden below the API: until the API export these ranges, we can not
* do any generic validation
*/
addr = offset + priv->pflash_block_base;
memcpy(data, (void *) addr, len);
return 0;
}
static int flash_mcux_write(struct device *dev, off_t offset,
const void *data, size_t len)
{
struct flash_priv *priv = dev->driver_data;
u32_t addr;
status_t rc;
unsigned int key;
if (k_sem_take(&priv->write_lock, K_NO_WAIT)) {
return -EACCES;
}
addr = offset + priv->pflash_block_base;
key = irq_lock();
rc = FLASH_Program(&priv->config, addr, (uint32_t *) data, len);
irq_unlock(key);
k_sem_give(&priv->write_lock);
return (rc == kStatus_Success) ? 0 : -EINVAL;
}
static int flash_mcux_write_protection(struct device *dev, bool enable)
{
struct flash_priv *priv = dev->driver_data;
int rc = 0;
if (enable) {
rc = k_sem_take(&priv->write_lock, K_FOREVER);
} else {
k_sem_give(&priv->write_lock);
}
return rc;
}
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
static const struct flash_pages_layout dev_layout = {
.pages_count = KB(CONFIG_FLASH_SIZE) /
DT_SOC_NV_FLASH_0_ERASE_BLOCK_SIZE,
.pages_size = DT_SOC_NV_FLASH_0_ERASE_BLOCK_SIZE,
};
static void flash_mcux_pages_layout(
struct device *dev,
const struct flash_pages_layout **layout,
size_t *layout_size)
{
*layout = &dev_layout;
*layout_size = 1;
}
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
static struct flash_priv flash_data;
static const struct flash_driver_api flash_mcux_api = {
.write_protection = flash_mcux_write_protection,
.erase = flash_mcux_erase,
.write = flash_mcux_write,
.read = flash_mcux_read,
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
.page_layout = flash_mcux_pages_layout,
#endif
.write_block_size = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE,
};
static int flash_mcux_init(struct device *dev)
{
struct flash_priv *priv = dev->driver_data;
u32_t pflash_block_base;
status_t rc;
CLOCK_EnableClock(kCLOCK_Mscm);
k_sem_init(&priv->write_lock, 0, 1);
rc = FLASH_Init(&priv->config);
FLASH_GetProperty(&priv->config, kFLASH_PropertyPflashBlockBaseAddr,
(uint32_t *)&pflash_block_base);
priv->pflash_block_base = (u32_t) pflash_block_base;
return (rc == kStatus_Success) ? 0 : -EIO;
}
DEVICE_AND_API_INIT(flash_mcux, DT_FLASH_DEV_NAME,
flash_mcux_init, &flash_data, NULL, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &flash_mcux_api);

View file

@ -15,3 +15,10 @@ config HAS_RV32M1_LPI2C
bool bool
help help
Set if the low power i2c (LPI2C) module is present in the SoC. Set if the low power i2c (LPI2C) module is present in the SoC.
config HAS_RV32M1_FTFX
bool
help
Set if the flash memory (FTFA, FTFE, or FTFL) module is present in
the SoC.

View file

@ -3,3 +3,4 @@ zephyr_include_directories(.)
zephyr_sources(fsl_clock.c) zephyr_sources(fsl_clock.c)
zephyr_sources_ifdef(CONFIG_UART_RV32M1_LPUART fsl_lpuart.c) zephyr_sources_ifdef(CONFIG_UART_RV32M1_LPUART fsl_lpuart.c)
zephyr_sources_ifdef(CONFIG_I2C_RV32M1_LPI2C fsl_lpi2c.c) zephyr_sources_ifdef(CONFIG_I2C_RV32M1_LPI2C fsl_lpi2c.c)
zephyr_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 fsl_flash.c)

View file

@ -173,4 +173,14 @@ config I2C_RV32M1_LPI2C
endif # I2C endif # I2C
if FLASH
config SOC_FLASH_RV32M1
default y
config FLASH_BASE_ADDRESS
default $(dt_hex_val,DT_FLASH_BASE_ADDRESS)
endif # FLASH
endif # SOC_OPENISA_RV32M1_RISCV32 endif # SOC_OPENISA_RV32M1_RISCV32

View file

@ -14,6 +14,8 @@ config SOC_OPENISA_RV32M1_RISCV32
select VEGA_SDK_HAL select VEGA_SDK_HAL
select RISCV_SOC_INTERRUPT_INIT select RISCV_SOC_INTERRUPT_INIT
select CLOCK_CONTROL select CLOCK_CONTROL
select HAS_RV32M1_FTFX
select HAS_FLASH_LOAD_OFFSET
help help
Enable support for OpenISA RV32M1 RISC-V processors. Choose Enable support for OpenISA RV32M1 RISC-V processors. Choose
this option to target the RI5CY or ZERO-RISCY core. This this option to target the RI5CY or ZERO-RISCY core. This

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2019 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/* SoC level DTS fixup file */
#if defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
#define DT_FLASH_DEV_BASE_ADDRESS DT_OPENISA_RV32M1_FTFE_40023000_BASE_ADDRESS
#define DT_FLASH_DEV_NAME DT_OPENISA_RV32M1_FTFE_40023000_LABEL
#endif /* CONFIG_SOC_OPENISA_RV32M1_RISCV32 */
/* End of SoC Level DTS fixup file */