blob: 9cab215a3dd28ffe6a25817d4c8e99ef98af8a07 [file] [log] [blame] [edit]
/*
* Copyright (c) 2019 Kwon Tae-young <tykwon@m2i.co.kr>
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT st_stm32_eeprom
#include <zephyr/drivers/eeprom.h>
#include <soc.h>
#include <zephyr/kernel.h>
#define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(eeprom_stm32);
K_MUTEX_DEFINE(lock);
struct eeprom_stm32_config {
uint32_t addr;
size_t size;
};
static int eeprom_stm32_read(const struct device *dev, off_t offset,
void *buf,
size_t len)
{
const struct eeprom_stm32_config *config = dev->config;
uint8_t *pbuf = buf;
if (!len) {
return 0;
}
if ((offset + len) > config->size) {
LOG_WRN("attempt to read past device boundary");
return -EINVAL;
}
k_mutex_lock(&lock, K_FOREVER);
while (len) {
*pbuf = *(__IO uint8_t*)(config->addr + offset);
pbuf++;
offset++;
len--;
}
k_mutex_unlock(&lock);
return 0;
}
static int eeprom_stm32_write(const struct device *dev, off_t offset,
const void *buf, size_t len)
{
const struct eeprom_stm32_config *config = dev->config;
const uint8_t *pbuf = buf;
HAL_StatusTypeDef ret = HAL_OK;
if (!len) {
return 0;
}
if ((offset + len) > config->size) {
LOG_WRN("attempt to write past device boundary");
return -EINVAL;
}
k_mutex_lock(&lock, K_FOREVER);
HAL_FLASHEx_DATAEEPROM_Unlock();
while (len) {
ret = HAL_FLASHEx_DATAEEPROM_Program(
FLASH_TYPEPROGRAMDATA_BYTE,
config->addr + offset, *pbuf);
if (ret) {
LOG_ERR("failed to write to EEPROM (err %d)", ret);
HAL_FLASHEx_DATAEEPROM_Lock();
k_mutex_unlock(&lock);
return ret;
}
pbuf++;
offset++;
len--;
}
ret = HAL_FLASHEx_DATAEEPROM_Lock();
if (ret) {
LOG_ERR("failed to lock EEPROM (err %d)", ret);
k_mutex_unlock(&lock);
return ret;
}
k_mutex_unlock(&lock);
return ret;
}
static size_t eeprom_stm32_size(const struct device *dev)
{
const struct eeprom_stm32_config *config = dev->config;
return config->size;
}
static const struct eeprom_driver_api eeprom_stm32_api = {
.read = eeprom_stm32_read,
.write = eeprom_stm32_write,
.size = eeprom_stm32_size,
};
static const struct eeprom_stm32_config eeprom_config = {
.addr = DT_INST_REG_ADDR(0),
.size = DT_INST_REG_SIZE(0),
};
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &eeprom_config, POST_KERNEL,
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_stm32_api);