/src/barebox/drivers/eeprom/at24.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * at24.c - handle most I2C EEPROMs |
4 | | * |
5 | | * Copyright (C) 2005-2007 David Brownell |
6 | | * Copyright (C) 2008 Wolfram Sang, Pengutronix |
7 | | */ |
8 | | |
9 | | #include <common.h> |
10 | | #include <malloc.h> |
11 | | #include <clock.h> |
12 | | #include <driver.h> |
13 | | #include <xfuncs.h> |
14 | | #include <errno.h> |
15 | | #include <linux/math64.h> |
16 | | #include <linux/log2.h> |
17 | | #include <i2c/i2c.h> |
18 | | #include <i2c/at24.h> |
19 | | #include <gpio.h> |
20 | | #include <of_gpio.h> |
21 | | |
22 | | #include <linux/nvmem-provider.h> |
23 | | |
24 | | /* |
25 | | * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. |
26 | | * Differences between different vendor product lines (like Atmel AT24C or |
27 | | * MicroChip 24LC, etc) won't much matter for typical read/write access. |
28 | | * There are also I2C RAM chips, likewise interchangeable. One example |
29 | | * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). |
30 | | * |
31 | | * However, misconfiguration can lose data. "Set 16-bit memory address" |
32 | | * to a part with 8-bit addressing will overwrite data. Writing with too |
33 | | * big a page size also loses data. And it's not safe to assume that the |
34 | | * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC |
35 | | * uses 0x51, for just one example. |
36 | | * |
37 | | * So this driver uses "new style" I2C driver binding, expecting to be |
38 | | * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or |
39 | | * similar kernel-resident tables; or, configuration data coming from |
40 | | * a bootloader. |
41 | | * |
42 | | * Other than binding model, current differences from "eeprom" driver are |
43 | | * that this one handles write access and isn't restricted to 24c02 devices. |
44 | | * It also handles larger devices (32 kbit and up) with two-byte addresses, |
45 | | * which won't work on pure SMBus systems. |
46 | | */ |
47 | | |
48 | | struct at24_data { |
49 | | struct at24_platform_data chip; |
50 | | |
51 | | struct nvmem_config nvmem_config; |
52 | | struct nvmem_device *nvmem; |
53 | | |
54 | | u8 *writebuf; |
55 | | unsigned write_max; |
56 | | unsigned num_addresses; |
57 | | int wp_gpio; |
58 | | int wp_active_low; |
59 | | |
60 | | /* |
61 | | * Some chips tie up multiple I2C addresses; dummy devices reserve |
62 | | * them for us. |
63 | | */ |
64 | | struct i2c_client *client[]; |
65 | | }; |
66 | | |
67 | | /* |
68 | | * This parameter is to help this driver avoid blocking other drivers out |
69 | | * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C |
70 | | * clock, one 256 byte read takes about 1/43 second which is excessive; |
71 | | * but the 1/170 second it takes at 400 kHz may be quite reasonable; and |
72 | | * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. |
73 | | * |
74 | | * This value is forced to be a power of two so that writes align on pages. |
75 | | */ |
76 | | static unsigned io_limit = 128; |
77 | | |
78 | | /* |
79 | | * Specs often allow 5 msec for a page write, sometimes 20 msec; |
80 | | * it's important to recover from write timeouts. |
81 | | */ |
82 | | static unsigned write_timeout = 25; |
83 | | |
84 | | /* number of bits in driver_data reserved for eeprom byte length */ |
85 | 0 | #define AT24_SIZE_BYTELEN 5 |
86 | | /* number of bits in driver_data reserved for flags */ |
87 | | #define AT24_SIZE_FLAGS 8 |
88 | | |
89 | 0 | #define AT24_BITMASK(x) (BIT(x) - 1) |
90 | | |
91 | | /* create non-zero magic value for given eeprom parameters */ |
92 | | #define AT24_DEVICE_MAGIC(_len, _flags) \ |
93 | | ((1 << AT24_SIZE_FLAGS | (_flags)) \ |
94 | | << AT24_SIZE_BYTELEN | ilog2(_len)) |
95 | | |
96 | | static struct platform_device_id at24_ids[] = { |
97 | | /* needs 8 addresses as A0-A2 are ignored */ |
98 | | { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, |
99 | | /* old variants can't be handled with this generic entry! */ |
100 | | { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, |
101 | | { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, |
102 | | { "24mac402", AT24_DEVICE_MAGIC(2048 / 8, AT24_FLAG_READONLY) }, |
103 | | { "24mac602", AT24_DEVICE_MAGIC(2048 / 8, AT24_FLAG_READONLY) }, |
104 | | /* spd is a 24c02 in memory DIMMs */ |
105 | | { "spd", AT24_DEVICE_MAGIC(2048 / 8, |
106 | | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, |
107 | | { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, |
108 | | /* 24rf08 quirk is handled at i2c-core */ |
109 | | { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, |
110 | | { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, |
111 | | { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, |
112 | | { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, |
113 | | { "24cs64", AT24_DEVICE_MAGIC(16, AT24_FLAG_ADDR16) }, |
114 | | { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, |
115 | | { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, |
116 | | { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, |
117 | | { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, |
118 | | { "24c1025", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_BANK_BIT_2) }, |
119 | | { "at24", 0 }, |
120 | | { /* END OF LIST */ } |
121 | | }; |
122 | | |
123 | | /*-------------------------------------------------------------------------*/ |
124 | | |
125 | | /* |
126 | | * This routine supports chips which consume multiple I2C addresses. It |
127 | | * computes the addressing information to be used for a given r/w request. |
128 | | * Assumes that sanity checks for offset happened at sysfs-layer. |
129 | | */ |
130 | | static struct i2c_client *at24_translate_offset(struct at24_data *at24, |
131 | | unsigned *offset) |
132 | 0 | { |
133 | 0 | unsigned i; |
134 | |
|
135 | 0 | if (at24->chip.flags & AT24_FLAG_ADDR16) { |
136 | 0 | i = *offset >> 16; |
137 | 0 | *offset &= 0xffff; |
138 | 0 | } else { |
139 | 0 | i = *offset >> 8; |
140 | 0 | *offset &= 0xff; |
141 | 0 | } |
142 | |
|
143 | 0 | return at24->client[i]; |
144 | 0 | } |
145 | | |
146 | | static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, |
147 | | unsigned offset, size_t count) |
148 | 0 | { |
149 | 0 | struct i2c_msg msg[2]; |
150 | 0 | u8 msgbuf[2]; |
151 | 0 | struct i2c_client *client; |
152 | 0 | int status, i; |
153 | 0 | uint64_t start, read_time; |
154 | |
|
155 | 0 | memset(msg, 0, sizeof(msg)); |
156 | | |
157 | | /* |
158 | | * REVISIT some multi-address chips don't rollover page reads to |
159 | | * the next slave address, so we may need to truncate the count. |
160 | | * Those chips might need another quirk flag. |
161 | | * |
162 | | * If the real hardware used four adjacent 24c02 chips and that |
163 | | * were misconfigured as one 24c08, that would be a similar effect: |
164 | | * one "eeprom" file not four, but larger reads would fail when |
165 | | * they crossed certain pages. |
166 | | */ |
167 | | |
168 | | /* |
169 | | * Slave address and byte offset derive from the offset. Always |
170 | | * set the byte address; on a multi-master board, another master |
171 | | * may have changed the chip's "current" address pointer. |
172 | | */ |
173 | 0 | client = at24_translate_offset(at24, &offset); |
174 | |
|
175 | 0 | if (count > io_limit) |
176 | 0 | count = io_limit; |
177 | |
|
178 | 0 | i = 0; |
179 | 0 | if (at24->chip.flags & AT24_FLAG_ADDR16) |
180 | 0 | msgbuf[i++] = offset >> 8; |
181 | 0 | msgbuf[i++] = offset; |
182 | |
|
183 | 0 | msg[0].addr = client->addr; |
184 | 0 | msg[0].buf = msgbuf; |
185 | 0 | msg[0].len = i; |
186 | |
|
187 | 0 | msg[1].addr = client->addr; |
188 | 0 | msg[1].flags = I2C_M_RD; |
189 | 0 | msg[1].buf = buf; |
190 | 0 | msg[1].len = count; |
191 | | |
192 | | /* |
193 | | * Reads fail if the previous write didn't complete yet. We may |
194 | | * loop a few times until this one succeeds, waiting at least |
195 | | * long enough for one entire page write to work. |
196 | | */ |
197 | 0 | start = get_time_ns(); |
198 | 0 | do { |
199 | 0 | read_time = get_time_ns(); |
200 | 0 | status = i2c_transfer(client->adapter, msg, 2); |
201 | 0 | if (status == 2) |
202 | 0 | status = count; |
203 | 0 | dev_dbg(&client->dev, "read %zu@%d --> %d (%llu)\n", |
204 | 0 | count, offset, status, read_time); |
205 | |
|
206 | 0 | if (status == count) |
207 | 0 | return count; |
208 | | |
209 | | /* REVISIT: at HZ=100, this is sloooow */ |
210 | 0 | mdelay(1); |
211 | 0 | } while (!is_timeout(start, write_timeout * MSECOND)); |
212 | | |
213 | 0 | return -ETIMEDOUT; |
214 | 0 | } |
215 | | |
216 | | static ssize_t at24_read(struct at24_data *at24, |
217 | | char *buf, loff_t off, size_t count) |
218 | 0 | { |
219 | 0 | ssize_t retval = 0; |
220 | |
|
221 | 0 | if (unlikely(!count)) |
222 | 0 | return count; |
223 | | |
224 | | /* |
225 | | * Read data from chip, protecting against concurrent updates |
226 | | * from this host, but not from other I2C masters. |
227 | | */ |
228 | 0 | while (count) { |
229 | 0 | ssize_t status; |
230 | |
|
231 | 0 | status = at24_eeprom_read(at24, buf, off, count); |
232 | 0 | if (status <= 0) { |
233 | 0 | if (retval == 0) |
234 | 0 | retval = status; |
235 | 0 | break; |
236 | 0 | } |
237 | 0 | buf += status; |
238 | 0 | off += status; |
239 | 0 | count -= status; |
240 | 0 | retval += status; |
241 | 0 | } |
242 | |
|
243 | 0 | return retval; |
244 | 0 | } |
245 | | |
246 | | static int at24_nvmem_read(void *ctx, unsigned off, void *buf, size_t count) |
247 | 0 | { |
248 | 0 | return at24_read(ctx, buf, off, count); |
249 | 0 | } |
250 | | |
251 | | /* |
252 | | * Note that if the hardware write-protect pin is pulled high, the whole |
253 | | * chip is normally write protected. But there are plenty of product |
254 | | * variants here, including OTP fuses and partial chip protect. |
255 | | * |
256 | | * We only use page mode writes; the alternative is sloooow. This routine |
257 | | * writes at most one page. |
258 | | */ |
259 | | static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, |
260 | | unsigned offset, size_t count) |
261 | 0 | { |
262 | 0 | struct i2c_client *client; |
263 | 0 | struct i2c_msg msg; |
264 | 0 | ssize_t status; |
265 | 0 | uint64_t start, write_time; |
266 | 0 | unsigned next_page; |
267 | 0 | int i = 0; |
268 | | |
269 | | /* Get corresponding I2C address and adjust offset */ |
270 | 0 | client = at24_translate_offset(at24, &offset); |
271 | | |
272 | | /* write_max is at most a page */ |
273 | 0 | if (count > at24->write_max) |
274 | 0 | count = at24->write_max; |
275 | | |
276 | | /* Never roll over backwards, to the start of this page */ |
277 | 0 | next_page = roundup(offset + 1, at24->chip.page_size); |
278 | 0 | if (offset + count > next_page) |
279 | 0 | count = next_page - offset; |
280 | | |
281 | |
|
282 | 0 | msg.addr = client->addr; |
283 | 0 | msg.flags = 0; |
284 | | |
285 | | /* msg.buf is u8 and casts will mask the values */ |
286 | 0 | msg.buf = at24->writebuf; |
287 | 0 | if (at24->chip.flags & AT24_FLAG_ADDR16) |
288 | 0 | msg.buf[i++] = offset >> 8; |
289 | |
|
290 | 0 | msg.buf[i++] = offset; |
291 | 0 | memcpy(&msg.buf[i], buf, count); |
292 | 0 | msg.len = i + count; |
293 | | |
294 | | /* |
295 | | * Writes fail if the previous one didn't complete yet. We may |
296 | | * loop a few times until this one succeeds, waiting at least |
297 | | * long enough for one entire page write to work. |
298 | | */ |
299 | 0 | start = get_time_ns(); |
300 | 0 | do { |
301 | 0 | write_time = get_time_ns(); |
302 | 0 | status = i2c_transfer(client->adapter, &msg, 1); |
303 | 0 | if (status == 1) |
304 | 0 | status = count; |
305 | 0 | dev_dbg(&client->dev, "write %zu@%d --> %zd (%llu)\n", |
306 | 0 | count, offset, status, write_time); |
307 | |
|
308 | 0 | if (status == count) |
309 | 0 | return count; |
310 | | |
311 | | /* REVISIT: at HZ=100, this is sloooow */ |
312 | 0 | mdelay(1); |
313 | 0 | } while (!is_timeout(start, write_timeout * MSECOND)); |
314 | | |
315 | 0 | return -ETIMEDOUT; |
316 | 0 | } |
317 | | |
318 | | static void at24_protect(struct at24_data *at24, bool prot) |
319 | 0 | { |
320 | 0 | if (gpio_is_valid(at24->wp_gpio)) { |
321 | |
|
322 | 0 | if (at24->wp_active_low) |
323 | 0 | prot = !prot; |
324 | |
|
325 | 0 | gpio_set_value(at24->wp_gpio, prot); |
326 | |
|
327 | 0 | udelay(50); |
328 | 0 | } |
329 | 0 | } |
330 | | |
331 | | static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, |
332 | | size_t count) |
333 | 0 | { |
334 | 0 | ssize_t retval = 0; |
335 | |
|
336 | 0 | if (unlikely(!count)) |
337 | 0 | return count; |
338 | | |
339 | 0 | at24_protect(at24, false); |
340 | |
|
341 | 0 | while (count) { |
342 | 0 | ssize_t status; |
343 | |
|
344 | 0 | status = at24_eeprom_write(at24, buf, off, count); |
345 | 0 | if (status <= 0) { |
346 | 0 | if (retval == 0) |
347 | 0 | retval = status; |
348 | 0 | break; |
349 | 0 | } |
350 | 0 | buf += status; |
351 | 0 | off += status; |
352 | 0 | count -= status; |
353 | 0 | retval += status; |
354 | 0 | } |
355 | |
|
356 | 0 | at24_protect(at24, true); |
357 | |
|
358 | 0 | return retval; |
359 | 0 | } |
360 | | |
361 | | static int at24_nvmem_write(void *ctx, unsigned off, const void *buf, size_t count) |
362 | 0 | { |
363 | 0 | return at24_write(ctx, buf, off, count); |
364 | 0 | } |
365 | | |
366 | | static int at24_probe(struct device *dev) |
367 | 0 | { |
368 | 0 | struct i2c_client *client = to_i2c_client(dev); |
369 | 0 | struct at24_platform_data chip; |
370 | 0 | bool writable; |
371 | 0 | struct at24_data *at24; |
372 | 0 | int devid, err; |
373 | 0 | unsigned i, num_addresses; |
374 | 0 | const char *devname; |
375 | 0 | const char *alias; |
376 | |
|
377 | 0 | if (dev->platform_data) { |
378 | 0 | chip = *(struct at24_platform_data *)dev->platform_data; |
379 | 0 | } else { |
380 | 0 | unsigned long magic; |
381 | 0 | u32 page_size; |
382 | |
|
383 | 0 | magic = (uintptr_t)device_get_match_data(dev); |
384 | |
|
385 | 0 | chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); |
386 | 0 | magic >>= AT24_SIZE_BYTELEN; |
387 | 0 | chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); |
388 | 0 | if (dev->of_node && |
389 | 0 | !of_property_read_u32(dev->of_node, "pagesize", &page_size)) |
390 | 0 | chip.page_size = page_size; |
391 | 0 | else { |
392 | | /* |
393 | | * This is slow, but we can't know all eeproms, so we better |
394 | | * play safe. Specifying custom eeprom-types via platform_data |
395 | | * is recommended anyhow. |
396 | | */ |
397 | 0 | chip.page_size = 1; |
398 | 0 | } |
399 | 0 | } |
400 | |
|
401 | 0 | if (!is_power_of_2(chip.byte_len)) |
402 | 0 | dev_warn(&client->dev, |
403 | 0 | "byte_len looks suspicious (no power of 2)!\n"); |
404 | 0 | if (!chip.page_size) { |
405 | 0 | dev_err(&client->dev, "page_size must not be 0!\n"); |
406 | 0 | err = -EINVAL; |
407 | 0 | goto err_out; |
408 | 0 | } |
409 | 0 | if (!is_power_of_2(chip.page_size)) |
410 | 0 | dev_warn(&client->dev, |
411 | 0 | "page_size looks suspicious (no power of 2)!\n"); |
412 | |
|
413 | 0 | if (chip.flags & AT24_FLAG_TAKE8ADDR) |
414 | 0 | num_addresses = 8; |
415 | 0 | else |
416 | 0 | num_addresses = DIV_ROUND_UP(chip.byte_len, |
417 | 0 | (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); |
418 | |
|
419 | 0 | at24 = xzalloc(sizeof(struct at24_data) + |
420 | 0 | num_addresses * sizeof(struct i2c_client *)); |
421 | |
|
422 | 0 | at24->chip = chip; |
423 | 0 | at24->num_addresses = num_addresses; |
424 | |
|
425 | 0 | alias = of_alias_get(dev->of_node); |
426 | 0 | if (alias) { |
427 | 0 | devname = alias; |
428 | 0 | devid = NVMEM_DEVID_NONE; |
429 | 0 | } else { |
430 | 0 | devname = "eeprom"; |
431 | 0 | devid = get_free_deviceid_from(devname, |
432 | 0 | of_alias_get_free_id(devname)); |
433 | 0 | } |
434 | |
|
435 | 0 | writable = !(chip.flags & AT24_FLAG_READONLY); |
436 | |
|
437 | 0 | if (of_get_property(dev->of_node, "read-only", NULL)) |
438 | 0 | writable = 0; |
439 | |
|
440 | 0 | if (writable) { |
441 | 0 | unsigned write_max = chip.page_size; |
442 | |
|
443 | 0 | if (write_max > io_limit) |
444 | 0 | write_max = io_limit; |
445 | 0 | at24->write_max = write_max; |
446 | | |
447 | | /* buffer (data + address at the beginning) */ |
448 | 0 | at24->writebuf = xmalloc(write_max + 2); |
449 | 0 | } |
450 | |
|
451 | 0 | at24->wp_gpio = -1; |
452 | 0 | if (dev->of_node) { |
453 | 0 | enum of_gpio_flags flags; |
454 | 0 | at24->wp_gpio = of_get_named_gpio_flags(dev->of_node, |
455 | 0 | "wp-gpios", 0, &flags); |
456 | 0 | if (gpio_is_valid(at24->wp_gpio)) { |
457 | 0 | at24->wp_active_low = flags & OF_GPIO_ACTIVE_LOW; |
458 | 0 | gpio_request(at24->wp_gpio, "eeprom-wp"); |
459 | 0 | gpio_direction_output(at24->wp_gpio, |
460 | 0 | !at24->wp_active_low); |
461 | 0 | } |
462 | 0 | } |
463 | |
|
464 | 0 | at24->client[0] = client; |
465 | | |
466 | | /* use dummy devices for multiple-address chips */ |
467 | 0 | for (i = 1; i < num_addresses; i++) { |
468 | 0 | const int shift = (chip.flags & AT24_FLAG_BANK_BIT_2) ? 2 : 0; |
469 | 0 | at24->client[i] = i2c_new_dummy(client->adapter, |
470 | 0 | client->addr + (i << shift)); |
471 | 0 | if (!at24->client[i]) { |
472 | 0 | dev_err(&client->dev, "address 0x%02x unavailable\n", |
473 | 0 | client->addr + (i << shift)); |
474 | 0 | err = -EADDRINUSE; |
475 | 0 | goto err_clients; |
476 | 0 | } |
477 | 0 | } |
478 | | |
479 | 0 | at24->nvmem_config.name = devname; |
480 | 0 | at24->nvmem_config.dev = dev; |
481 | 0 | at24->nvmem_config.priv = at24; |
482 | 0 | at24->nvmem_config.read_only = !writable; |
483 | 0 | at24->nvmem_config.reg_write = at24_nvmem_write; |
484 | 0 | at24->nvmem_config.reg_read = at24_nvmem_read; |
485 | 0 | at24->nvmem_config.stride = 1; |
486 | 0 | at24->nvmem_config.word_size = 1; |
487 | 0 | at24->nvmem_config.size = chip.byte_len; |
488 | 0 | at24->nvmem_config.id = devid; |
489 | |
|
490 | 0 | at24->nvmem = nvmem_register(&at24->nvmem_config); |
491 | 0 | err = PTR_ERR_OR_ZERO(at24->nvmem); |
492 | 0 | if (err) |
493 | 0 | goto err_devfs_create; |
494 | | |
495 | 0 | return 0; |
496 | | |
497 | 0 | err_devfs_create: |
498 | 0 | err_clients: |
499 | 0 | for (i = 1; i < num_addresses; i++) { |
500 | 0 | if (at24->client[i]) |
501 | 0 | i2c_unregister_device(at24->client[i]); |
502 | 0 | kfree(at24->client[i]); |
503 | 0 | } |
504 | |
|
505 | 0 | if (gpio_is_valid(at24->wp_gpio)) |
506 | 0 | gpio_free(at24->wp_gpio); |
507 | 0 | kfree(at24->writebuf); |
508 | 0 | kfree(at24); |
509 | 0 | err_out: |
510 | 0 | dev_dbg(&client->dev, "probe error %d\n", err); |
511 | 0 | return err; |
512 | |
|
513 | 0 | } |
514 | | |
515 | | static struct driver at24_driver = { |
516 | | .name = "at24", |
517 | | .probe = at24_probe, |
518 | | .id_table = at24_ids, |
519 | | }; |
520 | | device_i2c_driver(at24_driver); |