123 lines
2.4 KiB
C
123 lines
2.4 KiB
C
|
/*
|
||
|
* Copyright (c) 2022 BrainCo Inc.
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*/
|
||
|
|
||
|
#define DT_DRV_COMPAT gd_gd32_flash_controller
|
||
|
|
||
|
#include "flash_gd32.h"
|
||
|
|
||
|
#include <zephyr/kernel.h>
|
||
|
#include <zephyr/devicetree.h>
|
||
|
#include <zephyr/drivers/flash.h>
|
||
|
#include <zephyr/logging/log.h>
|
||
|
|
||
|
#include <gd32_fmc.h>
|
||
|
|
||
|
LOG_MODULE_REGISTER(flash_gd32, CONFIG_FLASH_LOG_LEVEL);
|
||
|
|
||
|
struct flash_gd32_data {
|
||
|
struct k_sem mutex;
|
||
|
};
|
||
|
|
||
|
static struct flash_gd32_data flash_data;
|
||
|
|
||
|
static const struct flash_parameters flash_gd32_parameters = {
|
||
|
.write_block_size = SOC_NV_FLASH_PRG_SIZE,
|
||
|
.erase_value = 0xff,
|
||
|
};
|
||
|
|
||
|
static int flash_gd32_read(const struct device *dev, off_t offset,
|
||
|
void *data, size_t len)
|
||
|
{
|
||
|
if ((offset > SOC_NV_FLASH_SIZE) ||
|
||
|
((offset + len) > SOC_NV_FLASH_SIZE)) {
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (len == 0U) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
memcpy(data, (uint8_t *)SOC_NV_FLASH_ADDR + offset, len);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int flash_gd32_write(const struct device *dev, off_t offset,
|
||
|
const void *data, size_t len)
|
||
|
{
|
||
|
struct flash_gd32_data *dev_data = dev->data;
|
||
|
int ret = 0;
|
||
|
|
||
|
if (!flash_gd32_valid_range(offset, len, true)) {
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (len == 0U) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
k_sem_take(&dev_data->mutex, K_FOREVER);
|
||
|
|
||
|
ret = flash_gd32_write_range(offset, data, len);
|
||
|
|
||
|
k_sem_give(&dev_data->mutex);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int flash_gd32_erase(const struct device *dev, off_t offset, size_t size)
|
||
|
{
|
||
|
struct flash_gd32_data *data = dev->data;
|
||
|
int ret = 0;
|
||
|
|
||
|
if (size == 0U) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!flash_gd32_valid_range(offset, size, false)) {
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
k_sem_take(&data->mutex, K_FOREVER);
|
||
|
|
||
|
ret = flash_gd32_erase_block(offset, size);
|
||
|
|
||
|
k_sem_give(&data->mutex);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static const struct flash_parameters*
|
||
|
flash_gd32_get_parameters(const struct device *dev)
|
||
|
{
|
||
|
ARG_UNUSED(dev);
|
||
|
|
||
|
return &flash_gd32_parameters;
|
||
|
}
|
||
|
|
||
|
static const struct flash_driver_api flash_gd32_driver_api = {
|
||
|
.read = flash_gd32_read,
|
||
|
.write = flash_gd32_write,
|
||
|
.erase = flash_gd32_erase,
|
||
|
.get_parameters = flash_gd32_get_parameters,
|
||
|
#ifdef CONFIG_FLASH_PAGE_LAYOUT
|
||
|
.page_layout = flash_gd32_pages_layout,
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
static int flash_gd32_init(const struct device *dev)
|
||
|
{
|
||
|
struct flash_gd32_data *data = dev->data;
|
||
|
|
||
|
k_sem_init(&data->mutex, 1, 1);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
DEVICE_DT_INST_DEFINE(0, flash_gd32_init, NULL,
|
||
|
&flash_data, NULL, POST_KERNEL,
|
||
|
CONFIG_FLASH_INIT_PRIORITY, &flash_gd32_driver_api);
|