1 /*
2 * Copyright (c) 2020 Seagate Technology LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_lpc11u6x_eeprom
8
9 /**
10 * @file
11 * @brief EEPROM driver for NXP LPC11U6X MCUs
12 *
13 * This driver supports the on-chip EEPROM found on NXP LPC11U6x MCUs.
14 *
15 * @note This driver is only a wrapper for the IAP (In-Application Programming)
16 * EEPROM functions.
17 */
18
19 #include <zephyr/kernel.h>
20 #include <zephyr/drivers/eeprom.h>
21 #include <iap.h>
22
23 #define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
24 #include <zephyr/logging/log.h>
25 LOG_MODULE_REGISTER(eeprom_lpc11u6x);
26
27 struct eeprom_lpc11u6x_config {
28 size_t size;
29 };
30
eeprom_lpc11u6x_read(const struct device * dev,off_t offset,void * data,size_t len)31 static int eeprom_lpc11u6x_read(const struct device *dev,
32 off_t offset, void *data, size_t len)
33 {
34 const struct eeprom_lpc11u6x_config *config = dev->config;
35 uint32_t cmd[5];
36 int ret;
37
38 if (!len) {
39 return 0;
40 }
41
42 if ((offset + len) > config->size) {
43 LOG_WRN("attempt to read past device boundary");
44 return -EINVAL;
45 }
46
47 cmd[0] = IAP_CMD_EEPROM_READ;
48 cmd[1] = offset;
49 cmd[2] = (uint32_t) data;
50 cmd[3] = len;
51 cmd[4] = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000;
52
53 ret = iap_cmd(cmd);
54
55 if (ret != IAP_STATUS_CMD_SUCCESS) {
56 LOG_ERR("failed to read EEPROM (offset=%08x len=%d err=%d)",
57 (unsigned int) offset, len, ret);
58 return -EINVAL;
59 }
60
61 return 0;
62 }
63
eeprom_lpc11u6x_write(const struct device * dev,off_t offset,const void * data,size_t len)64 static int eeprom_lpc11u6x_write(const struct device *dev,
65 off_t offset, const void *data, size_t len)
66 {
67 const struct eeprom_lpc11u6x_config *config = dev->config;
68 uint32_t cmd[5];
69 int ret;
70
71 if (!len) {
72 return 0;
73 }
74
75 if ((offset + len) > config->size) {
76 LOG_WRN("attempt to write past device boundary");
77 return -EINVAL;
78 }
79
80 cmd[0] = IAP_CMD_EEPROM_WRITE;
81 cmd[1] = offset;
82 cmd[2] = (uint32_t) data;
83 cmd[3] = len;
84 cmd[4] = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000;
85
86 ret = iap_cmd(cmd);
87
88 if (ret != IAP_STATUS_CMD_SUCCESS) {
89 LOG_ERR("failed to write EEPROM (offset=%08x len=%d err=%d)",
90 (unsigned int) offset, len, ret);
91 return -EINVAL;
92 }
93
94 return 0;
95 }
96
eeprom_lpc11u6x_size(const struct device * dev)97 static size_t eeprom_lpc11u6x_size(const struct device *dev)
98 {
99 const struct eeprom_lpc11u6x_config *config = dev->config;
100
101 return config->size;
102 }
103
104 static const struct eeprom_driver_api eeprom_lpc11u6x_api = {
105 .read = eeprom_lpc11u6x_read,
106 .write = eeprom_lpc11u6x_write,
107 .size = eeprom_lpc11u6x_size,
108 };
109
110 static const struct eeprom_lpc11u6x_config eeprom_config = {
111 .size = DT_INST_PROP(0, size),
112 };
113
114 DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &eeprom_config, POST_KERNEL,
115 CONFIG_EEPROM_INIT_PRIORITY, &eeprom_lpc11u6x_api);
116