aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvmem/lpc18xx_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvmem/lpc18xx_eeprom.c')
-rw-r--r--drivers/nvmem/lpc18xx_eeprom.c94
1 files changed, 26 insertions, 68 deletions
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c
index 878fce789341..c81ae4c6da74 100644
--- a/drivers/nvmem/lpc18xx_eeprom.c
+++ b/drivers/nvmem/lpc18xx_eeprom.c
@@ -16,7 +16,6 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/nvmem-provider.h> 17#include <linux/nvmem-provider.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/regmap.h>
20#include <linux/reset.h> 19#include <linux/reset.h>
21 20
22/* Registers */ 21/* Registers */
@@ -51,12 +50,7 @@ struct lpc18xx_eeprom_dev {
51 struct nvmem_device *nvmem; 50 struct nvmem_device *nvmem;
52 unsigned reg_bytes; 51 unsigned reg_bytes;
53 unsigned val_bytes; 52 unsigned val_bytes;
54}; 53 int size;
55
56static struct regmap_config lpc18xx_regmap_config = {
57 .reg_bits = 32,
58 .reg_stride = 4,
59 .val_bits = 32,
60}; 54};
61 55
62static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom, 56static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom,
@@ -95,30 +89,35 @@ static int lpc18xx_eeprom_busywait_until_prog(struct lpc18xx_eeprom_dev *eeprom)
95 return -ETIMEDOUT; 89 return -ETIMEDOUT;
96} 90}
97 91
98static int lpc18xx_eeprom_gather_write(void *context, const void *reg, 92static int lpc18xx_eeprom_gather_write(void *context, unsigned int reg,
99 size_t reg_size, const void *val, 93 void *val, size_t bytes)
100 size_t val_size)
101{ 94{
102 struct lpc18xx_eeprom_dev *eeprom = context; 95 struct lpc18xx_eeprom_dev *eeprom = context;
103 unsigned int offset = *(u32 *)reg; 96 unsigned int offset = reg;
104 int ret; 97 int ret;
105 98
106 if (offset % lpc18xx_regmap_config.reg_stride) 99 /*
100 * The last page contains the EEPROM initialization data and is not
101 * writable.
102 */
103 if ((reg > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE) ||
104 (reg + bytes > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE))
107 return -EINVAL; 105 return -EINVAL;
108 106
107
109 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, 108 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
110 LPC18XX_EEPROM_PWRDWN_NO); 109 LPC18XX_EEPROM_PWRDWN_NO);
111 110
112 /* Wait 100 us while the EEPROM wakes up */ 111 /* Wait 100 us while the EEPROM wakes up */
113 usleep_range(100, 200); 112 usleep_range(100, 200);
114 113
115 while (val_size) { 114 while (bytes) {
116 writel(*(u32 *)val, eeprom->mem_base + offset); 115 writel(*(u32 *)val, eeprom->mem_base + offset);
117 ret = lpc18xx_eeprom_busywait_until_prog(eeprom); 116 ret = lpc18xx_eeprom_busywait_until_prog(eeprom);
118 if (ret < 0) 117 if (ret < 0)
119 return ret; 118 return ret;
120 119
121 val_size -= eeprom->val_bytes; 120 bytes -= eeprom->val_bytes;
122 val += eeprom->val_bytes; 121 val += eeprom->val_bytes;
123 offset += eeprom->val_bytes; 122 offset += eeprom->val_bytes;
124 } 123 }
@@ -129,23 +128,10 @@ static int lpc18xx_eeprom_gather_write(void *context, const void *reg,
129 return 0; 128 return 0;
130} 129}
131 130
132static int lpc18xx_eeprom_write(void *context, const void *data, size_t count) 131static int lpc18xx_eeprom_read(void *context, unsigned int offset,
132 void *val, size_t bytes)
133{ 133{
134 struct lpc18xx_eeprom_dev *eeprom = context; 134 struct lpc18xx_eeprom_dev *eeprom = context;
135 unsigned int offset = eeprom->reg_bytes;
136
137 if (count <= offset)
138 return -EINVAL;
139
140 return lpc18xx_eeprom_gather_write(context, data, eeprom->reg_bytes,
141 data + offset, count - offset);
142}
143
144static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
145 void *val, size_t val_size)
146{
147 struct lpc18xx_eeprom_dev *eeprom = context;
148 unsigned int offset = *(u32 *)reg;
149 135
150 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, 136 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
151 LPC18XX_EEPROM_PWRDWN_NO); 137 LPC18XX_EEPROM_PWRDWN_NO);
@@ -153,9 +139,9 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
153 /* Wait 100 us while the EEPROM wakes up */ 139 /* Wait 100 us while the EEPROM wakes up */
154 usleep_range(100, 200); 140 usleep_range(100, 200);
155 141
156 while (val_size) { 142 while (bytes) {
157 *(u32 *)val = readl(eeprom->mem_base + offset); 143 *(u32 *)val = readl(eeprom->mem_base + offset);
158 val_size -= eeprom->val_bytes; 144 bytes -= eeprom->val_bytes;
159 val += eeprom->val_bytes; 145 val += eeprom->val_bytes;
160 offset += eeprom->val_bytes; 146 offset += eeprom->val_bytes;
161 } 147 }
@@ -166,31 +152,13 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
166 return 0; 152 return 0;
167} 153}
168 154
169static struct regmap_bus lpc18xx_eeprom_bus = {
170 .write = lpc18xx_eeprom_write,
171 .gather_write = lpc18xx_eeprom_gather_write,
172 .read = lpc18xx_eeprom_read,
173 .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
174 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
175};
176
177static bool lpc18xx_eeprom_writeable_reg(struct device *dev, unsigned int reg)
178{
179 /*
180 * The last page contains the EEPROM initialization data and is not
181 * writable.
182 */
183 return reg <= lpc18xx_regmap_config.max_register -
184 LPC18XX_EEPROM_PAGE_SIZE;
185}
186
187static bool lpc18xx_eeprom_readable_reg(struct device *dev, unsigned int reg)
188{
189 return reg <= lpc18xx_regmap_config.max_register;
190}
191 155
192static struct nvmem_config lpc18xx_nvmem_config = { 156static struct nvmem_config lpc18xx_nvmem_config = {
193 .name = "lpc18xx-eeprom", 157 .name = "lpc18xx-eeprom",
158 .stride = 4,
159 .word_size = 4,
160 .reg_read = lpc18xx_eeprom_read,
161 .reg_write = lpc18xx_eeprom_gather_write,
194 .owner = THIS_MODULE, 162 .owner = THIS_MODULE,
195}; 163};
196 164
@@ -200,7 +168,6 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
200 struct device *dev = &pdev->dev; 168 struct device *dev = &pdev->dev;
201 struct reset_control *rst; 169 struct reset_control *rst;
202 unsigned long clk_rate; 170 unsigned long clk_rate;
203 struct regmap *regmap;
204 struct resource *res; 171 struct resource *res;
205 int ret; 172 int ret;
206 173
@@ -243,8 +210,8 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
243 goto err_clk; 210 goto err_clk;
244 } 211 }
245 212
246 eeprom->val_bytes = lpc18xx_regmap_config.val_bits / BITS_PER_BYTE; 213 eeprom->val_bytes = 4;
247 eeprom->reg_bytes = lpc18xx_regmap_config.reg_bits / BITS_PER_BYTE; 214 eeprom->reg_bytes = 4;
248 215
249 /* 216 /*
250 * Clock rate is generated by dividing the system bus clock by the 217 * Clock rate is generated by dividing the system bus clock by the
@@ -264,19 +231,10 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
264 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, 231 lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
265 LPC18XX_EEPROM_PWRDWN_YES); 232 LPC18XX_EEPROM_PWRDWN_YES);
266 233
267 lpc18xx_regmap_config.max_register = resource_size(res) - 1; 234 eeprom->size = resource_size(res);
268 lpc18xx_regmap_config.writeable_reg = lpc18xx_eeprom_writeable_reg; 235 lpc18xx_nvmem_config.size = resource_size(res);
269 lpc18xx_regmap_config.readable_reg = lpc18xx_eeprom_readable_reg;
270
271 regmap = devm_regmap_init(dev, &lpc18xx_eeprom_bus, eeprom,
272 &lpc18xx_regmap_config);
273 if (IS_ERR(regmap)) {
274 dev_err(dev, "regmap init failed: %ld\n", PTR_ERR(regmap));
275 ret = PTR_ERR(regmap);
276 goto err_clk;
277 }
278
279 lpc18xx_nvmem_config.dev = dev; 236 lpc18xx_nvmem_config.dev = dev;
237 lpc18xx_nvmem_config.priv = eeprom;
280 238
281 eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config); 239 eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config);
282 if (IS_ERR(eeprom->nvmem)) { 240 if (IS_ERR(eeprom->nvmem)) {