32b4950c61
Refactors all of the EEPROM drivers to use a shared driver class initialization priority configuration, CONFIG_EEPROM_INIT_PRIORITY, to allow configuring EEPROM drivers separately from other devices. This is similar to other driver classes like I2C and SPI. The default is set to CONFIG_KERNEL_INIT_PRIORITY_DEVICE to preserve the existing default initialization priority for most drivers. The exceptions are at2x and emul drivers which have dependencies on SPI, I2C, or flash drivers and must therefore initialize later than the default device priority. Signed-off-by: Maureen Helm <maureen.helm@intel.com>
128 lines
2.4 KiB
C
128 lines
2.4 KiB
C
/*
|
|
* Copyright (c) 2019 Kwon Tae-young <tykwon@m2i.co.kr>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT st_stm32_eeprom
|
|
|
|
#include <drivers/eeprom.h>
|
|
#include <soc.h>
|
|
|
|
#define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
|
|
#include <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 int eeprom_stm32_init(const struct device *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
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, &eeprom_stm32_init, NULL, NULL,
|
|
&eeprom_config, POST_KERNEL,
|
|
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_stm32_api);
|