| /* |
| * 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(const 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(const 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(const struct device *dev) |
| { |
| const struct eeprom_lpc11u6x_config *config = dev->config; |
| |
| return config->size; |
| } |
| |
| static int eeprom_lpc11u6x_init(const 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_DT_INST_DEFINE(0, &eeprom_lpc11u6x_init, NULL, NULL, |
| &eeprom_config, POST_KERNEL, |
| CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &eeprom_lpc11u6x_api); |