zephyr/drivers/eeprom/eeprom_lpc11u6x.c

122 lines
2.5 KiB
C

/*
* Copyright (c) 2020 Seagate Technology LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nxp_lpc11u6x_eeprom
/**
* @file
* @brief EEPROM driver for NXP LPC11U6X MCUs
*
* This driver supports the on-chip EEPROM found on NXP LPC11U6x MCUs.
*
* @note This driver is only a wrapper for the IAP (In-Application Programming)
* EEPROM funcions.
*/
#include <drivers/eeprom.h>
#include <iap.h>
#define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(eeprom_lpc11u6x);
struct eeprom_lpc11u6x_config {
size_t size;
};
static int eeprom_lpc11u6x_read(struct device *dev,
off_t offset, void *data, size_t len)
{
const struct eeprom_lpc11u6x_config *config = dev->config;
uint32_t cmd[5];
int ret;
if (!len) {
return 0;
}
if ((offset + len) > config->size) {
LOG_WRN("attempt to read past device boundary");
return -EINVAL;
}
cmd[0] = IAP_CMD_EEPROM_READ;
cmd[1] = offset;
cmd[2] = (uint32_t) data;
cmd[3] = len;
cmd[4] = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000;
ret = iap_cmd(cmd);
if (ret != IAP_STATUS_CMD_SUCCESS) {
LOG_ERR("failed to read EEPROM (offset=%08x len=%d err=%d)",
(unsigned int) offset, len, ret);
return -EINVAL;
}
return 0;
}
static int eeprom_lpc11u6x_write(struct device *dev,
off_t offset, const void *data, size_t len)
{
const struct eeprom_lpc11u6x_config *config = dev->config;
uint32_t cmd[5];
int ret;
if (!len) {
return 0;
}
if ((offset + len) > config->size) {
LOG_WRN("attempt to write past device boundary");
return -EINVAL;
}
cmd[0] = IAP_CMD_EEPROM_WRITE;
cmd[1] = offset;
cmd[2] = (uint32_t) data;
cmd[3] = len;
cmd[4] = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000;
ret = iap_cmd(cmd);
if (ret != IAP_STATUS_CMD_SUCCESS) {
LOG_ERR("failed to write EEPROM (offset=%08x len=%d err=%d)",
(unsigned int) offset, len, ret);
return -EINVAL;
}
return 0;
}
static size_t eeprom_lpc11u6x_size(struct device *dev)
{
const struct eeprom_lpc11u6x_config *config = dev->config;
return config->size;
}
static int eeprom_lpc11u6x_init(struct device *dev)
{
return 0;
}
static const struct eeprom_driver_api eeprom_lpc11u6x_api = {
.read = eeprom_lpc11u6x_read,
.write = eeprom_lpc11u6x_write,
.size = eeprom_lpc11u6x_size,
};
static const struct eeprom_lpc11u6x_config eeprom_config = {
.size = DT_INST_PROP(0, size),
};
DEVICE_AND_API_INIT(eeprom_lpc11u6x, DT_INST_LABEL(0),
&eeprom_lpc11u6x_init, NULL,
&eeprom_config, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &eeprom_lpc11u6x_api);