Coverage Report

Created: 2026-10-13 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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);