drivers: flash: Introduce SiWx91x Flash driver
Add flash driver for Silicon Labs SiWx91x family. Co-authored-by: Martin Hoff <martin.hoff@silabs.com> Signed-off-by: Martin Hoff <martin.hoff@silabs.com> Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
This commit is contained in:
parent
4391e4c960
commit
d97479fdc3
@ -60,6 +60,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM flash_sam.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM0 flash_sam0.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SI32 flash_si32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SILABS_SIWX91X soc_flash_silabs_siwx91x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SMARTBOND flash_smartbond.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_TELINK_B91 soc_flash_b91.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_XMC4XXX soc_flash_xmc4xxx.c)
|
||||
|
||||
@ -198,6 +198,7 @@ source "drivers/flash/Kconfig.sam"
|
||||
source "drivers/flash/Kconfig.sam0"
|
||||
source "drivers/flash/Kconfig.si32"
|
||||
source "drivers/flash/Kconfig.simulator"
|
||||
source "drivers/flash/Kconfig.siwx91x"
|
||||
source "drivers/flash/Kconfig.smartbond"
|
||||
source "drivers/flash/Kconfig.stm32"
|
||||
source "drivers/flash/Kconfig.stm32_ospi"
|
||||
|
||||
15
drivers/flash/Kconfig.siwx91x
Normal file
15
drivers/flash/Kconfig.siwx91x
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2024 Silicon Laboratories Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SOC_FLASH_SILABS_SIWX91X
|
||||
bool "Silicon Labs SiWx91x flash driver"
|
||||
default y
|
||||
depends on DT_HAS_SILABS_SIWX91X_FLASH_CONTROLLER_ENABLED
|
||||
select FLASH_HAS_DRIVER_ENABLED
|
||||
select FLASH_HAS_EXPLICIT_ERASE
|
||||
select FLASH_HAS_PAGE_LAYOUT
|
||||
# Flash controller is handled by the network coprocessor
|
||||
select WISECONNECT_NETWORK_STACK
|
||||
help
|
||||
Enable flash controller for flash embedded on Silicon Labs SiWx91x
|
||||
chips.
|
||||
176
drivers/flash/soc_flash_silabs_siwx91x.c
Normal file
176
drivers/flash/soc_flash_silabs_siwx91x.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Silicon Laboratories Inc.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#define DT_DRV_COMPAT silabs_siwx91x_flash_controller
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/flash.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "sl_si91x_driver.h"
|
||||
|
||||
LOG_MODULE_REGISTER(siwx91x_soc_flash);
|
||||
|
||||
struct siwx91x_config {
|
||||
uintptr_t base_address;
|
||||
uint32_t size;
|
||||
uint32_t write_block_size;
|
||||
uint32_t erase_block_size;
|
||||
struct flash_parameters flash_parameters;
|
||||
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||
struct flash_pages_layout flash_pages_layout;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct siwx91x_data {
|
||||
struct k_sem lock;
|
||||
};
|
||||
|
||||
static bool flash_siwx91x_range_is_in_bounds(const struct device *dev, off_t offset, size_t len)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
|
||||
/* Note: If offset < __rom_region_end, the user to overwriting the current firmware. User
|
||||
* is probably doing a mistake, but not an error from this driver point of view.
|
||||
*/
|
||||
if (offset < 0) {
|
||||
return false;
|
||||
}
|
||||
if (offset + len > cfg->size) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct flash_parameters *flash_siwx91x_get_parameters(const struct device *dev)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
|
||||
return &cfg->flash_parameters;
|
||||
}
|
||||
|
||||
static int flash_siwx91x_read(const struct device *dev, off_t offset, void *buf, size_t len)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
struct siwx91x_data *data = dev->data;
|
||||
void *location = (void *)(cfg->base_address + offset);
|
||||
|
||||
if (!flash_siwx91x_range_is_in_bounds(dev, offset, len)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
k_sem_take(&data->lock, K_FOREVER);
|
||||
memcpy(buf, location, len);
|
||||
k_sem_give(&data->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flash_siwx91x_write(const struct device *dev, off_t offset, const void *buf, size_t len)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
struct siwx91x_data *data = dev->data;
|
||||
uint32_t ret;
|
||||
|
||||
if (!flash_siwx91x_range_is_in_bounds(dev, offset, len)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (offset % cfg->write_block_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len % cfg->write_block_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
k_sem_take(&data->lock, K_FOREVER);
|
||||
ret = sl_si91x_command_to_write_common_flash(cfg->base_address + offset, (void *)buf, len,
|
||||
false);
|
||||
k_sem_give(&data->lock);
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flash_siwx91x_erase(const struct device *dev, off_t offset, size_t len)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
struct siwx91x_data *data = dev->data;
|
||||
uint32_t ret;
|
||||
|
||||
if (!flash_siwx91x_range_is_in_bounds(dev, offset, len)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (offset % cfg->erase_block_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len % cfg->erase_block_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
k_sem_take(&data->lock, K_FOREVER);
|
||||
ret = sl_si91x_command_to_write_common_flash(cfg->base_address + offset, NULL, len, true);
|
||||
k_sem_give(&data->lock);
|
||||
if (ret) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||
static void flash_siwx91x_page_layout(const struct device *dev,
|
||||
const struct flash_pages_layout **layout, size_t *layout_size)
|
||||
{
|
||||
const struct siwx91x_config *cfg = dev->config;
|
||||
|
||||
*layout = &cfg->flash_pages_layout;
|
||||
*layout_size = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEVICE_API(flash, siwx91x_api) = {
|
||||
.read = flash_siwx91x_read,
|
||||
.write = flash_siwx91x_write,
|
||||
.erase = flash_siwx91x_erase,
|
||||
.get_parameters = flash_siwx91x_get_parameters,
|
||||
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||
.page_layout = flash_siwx91x_page_layout,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int flash_siwx91x_init(const struct device *dev)
|
||||
{
|
||||
struct siwx91x_data *data = dev->data;
|
||||
|
||||
k_sem_init(&data->lock, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||||
#define SIWX91X_PAGE_LAYOUT_FLASH_INIT(n) \
|
||||
.flash_pages_layout.pages_count = DT_REG_SIZE(n) / DT_PROP(n, erase_block_size), \
|
||||
.flash_pages_layout.pages_size = DT_PROP(n, erase_block_size),
|
||||
#else
|
||||
#define SIWX91X_PAGE_LAYOUT_FLASH_INIT(n)
|
||||
#endif
|
||||
|
||||
#define SIWX91X_FLASH_INIT_P(n, p) \
|
||||
static const struct siwx91x_config flash_siwx91x_config_##p = { \
|
||||
.base_address = DT_REG_ADDR(n), \
|
||||
.size = DT_REG_SIZE(n), \
|
||||
.write_block_size = DT_PROP(n, write_block_size), \
|
||||
.erase_block_size = DT_PROP(n, erase_block_size), \
|
||||
.flash_parameters.write_block_size = DT_PROP(n, write_block_size), \
|
||||
.flash_parameters.erase_value = 0xff, \
|
||||
SIWX91X_PAGE_LAYOUT_FLASH_INIT(n) \
|
||||
}; \
|
||||
static struct siwx91x_data flash_siwx91x_data_##p = { \
|
||||
.lock = Z_SEM_INITIALIZER(flash_siwx91x_data_##p.lock, 1, 1), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(p, flash_siwx91x_init, NULL, &flash_siwx91x_data_##p, \
|
||||
&flash_siwx91x_config_##p, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, \
|
||||
&siwx91x_api);
|
||||
|
||||
#define SIWX91X_FLASH_INIT(p) \
|
||||
BUILD_ASSERT(DT_INST_CHILD_NUM_STATUS_OKAY(p) == 1); \
|
||||
DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(p, SIWX91X_FLASH_INIT_P, p)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(SIWX91X_FLASH_INIT)
|
||||
@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2024 Silicon Laboratories Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Silicon Labs SiWx91x flash controller
|
||||
|
||||
compatible: "silabs,siwx91x-flash-controller"
|
||||
|
||||
include: flash-controller.yaml
|
||||
Loading…
Reference in New Issue
Block a user