1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * m24lr.c - Sysfs control interface for ST M24LR series RFID/NFC chips
4 *
5 * Copyright (c) 2025 Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
6 *
7 * This driver implements both the sysfs-based control interface and EEPROM
8 * access for STMicroelectronics M24LR series chips (e.g., M24LR04E-R).
9 * It provides access to control registers for features such as password
10 * authentication, memory protection, and device configuration. In addition,
11 * it manages read and write operations to the EEPROM region of the chip.
12 */
13
14 #include <linux/device.h>
15 #include <linux/i2c.h>
16 #include <linux/module.h>
17 #include <linux/nvmem-provider.h>
18 #include <linux/of.h>
19 #include <linux/of_device.h>
20 #include <linux/regmap.h>
21
22 #define M24LR_WRITE_TIMEOUT 25u
23 #define M24LR_READ_TIMEOUT (M24LR_WRITE_TIMEOUT)
24
25 /**
26 * struct m24lr_chip - describes chip-specific sysfs layout
27 * @sss_len: the length of the sss region
28 * @page_size: chip-specific limit on the maximum number of bytes allowed
29 * in a single write operation.
30 * @eeprom_size: size of the EEPROM in byte
31 *
32 * Supports multiple M24LR chip variants (e.g., M24LRxx) by allowing each
33 * to define its own set of sysfs attributes, depending on its available
34 * registers and features.
35 */
36 struct m24lr_chip {
37 unsigned int sss_len;
38 unsigned int page_size;
39 unsigned int eeprom_size;
40 };
41
42 /**
43 * struct m24lr - core driver data for M24LR chip control
44 * @uid: 64 bits unique identifier stored in the device
45 * @sss_len: the length of the sss region
46 * @page_size: chip-specific limit on the maximum number of bytes allowed
47 * in a single write operation.
48 * @eeprom_size: size of the EEPROM in byte
49 * @ctl_regmap: regmap interface for accessing the system parameter sector
50 * @eeprom_regmap: regmap interface for accessing the EEPROM
51 * @lock: mutex to synchronize operations to the device
52 *
53 * Central data structure holding the state and resources used by the
54 * M24LR device driver.
55 */
56 struct m24lr {
57 u64 uid;
58 unsigned int sss_len;
59 unsigned int page_size;
60 unsigned int eeprom_size;
61 struct regmap *ctl_regmap;
62 struct regmap *eeprom_regmap;
63 struct mutex lock; /* synchronize operations to the device */
64 };
65
66 static const struct regmap_range m24lr_ctl_vo_ranges[] = {
67 regmap_reg_range(0, 63),
68 };
69
70 static const struct regmap_access_table m24lr_ctl_vo_table = {
71 .yes_ranges = m24lr_ctl_vo_ranges,
72 .n_yes_ranges = ARRAY_SIZE(m24lr_ctl_vo_ranges),
73 };
74
75 static const struct regmap_config m24lr_ctl_regmap_conf = {
76 .name = "m24lr_ctl",
77 .reg_stride = 1,
78 .reg_bits = 16,
79 .val_bits = 8,
80 .disable_locking = false,
81 .cache_type = REGCACHE_RBTREE,/* Flat can't be used, there's huge gap */
82 .volatile_table = &m24lr_ctl_vo_table,
83 };
84
85 /* Chip descriptor for M24LR04E-R variant */
86 static const struct m24lr_chip m24lr04e_r_chip = {
87 .page_size = 4,
88 .eeprom_size = 512,
89 .sss_len = 4,
90 };
91
92 /* Chip descriptor for M24LR16E-R variant */
93 static const struct m24lr_chip m24lr16e_r_chip = {
94 .page_size = 4,
95 .eeprom_size = 2048,
96 .sss_len = 16,
97 };
98
99 /* Chip descriptor for M24LR64E-R variant */
100 static const struct m24lr_chip m24lr64e_r_chip = {
101 .page_size = 4,
102 .eeprom_size = 8192,
103 .sss_len = 64,
104 };
105
106 static const struct i2c_device_id m24lr_ids[] = {
107 { "m24lr04e-r", (kernel_ulong_t)&m24lr04e_r_chip},
108 { "m24lr16e-r", (kernel_ulong_t)&m24lr16e_r_chip},
109 { "m24lr64e-r", (kernel_ulong_t)&m24lr64e_r_chip},
110 { }
111 };
112 MODULE_DEVICE_TABLE(i2c, m24lr_ids);
113
114 static const struct of_device_id m24lr_of_match[] = {
115 { .compatible = "st,m24lr04e-r", .data = &m24lr04e_r_chip},
116 { .compatible = "st,m24lr16e-r", .data = &m24lr16e_r_chip},
117 { .compatible = "st,m24lr64e-r", .data = &m24lr64e_r_chip},
118 { }
119 };
120 MODULE_DEVICE_TABLE(of, m24lr_of_match);
121
122 /**
123 * m24lr_regmap_read - read data using regmap with retry on failure
124 * @regmap: regmap instance for the device
125 * @buf: buffer to store the read data
126 * @size: number of bytes to read
127 * @offset: starting register address
128 *
129 * Attempts to read a block of data from the device with retries and timeout.
130 * Some M24LR chips may transiently NACK reads (e.g., during internal write
131 * cycles), so this function retries with a short sleep until the timeout
132 * expires.
133 *
134 * Returns:
135 * Number of bytes read on success,
136 * -ETIMEDOUT if the read fails within the timeout window.
137 */
m24lr_regmap_read(struct regmap * regmap,u8 * buf,size_t size,unsigned int offset)138 static ssize_t m24lr_regmap_read(struct regmap *regmap, u8 *buf,
139 size_t size, unsigned int offset)
140 {
141 int err;
142 unsigned long timeout, read_time;
143 ssize_t ret = -ETIMEDOUT;
144
145 timeout = jiffies + msecs_to_jiffies(M24LR_READ_TIMEOUT);
146 do {
147 read_time = jiffies;
148
149 err = regmap_bulk_read(regmap, offset, buf, size);
150 if (!err) {
151 ret = size;
152 break;
153 }
154
155 usleep_range(1000, 2000);
156 } while (time_before(read_time, timeout));
157
158 return ret;
159 }
160
161 /**
162 * m24lr_regmap_write - write data using regmap with retry on failure
163 * @regmap: regmap instance for the device
164 * @buf: buffer containing the data to write
165 * @size: number of bytes to write
166 * @offset: starting register address
167 *
168 * Attempts to write a block of data to the device with retries and a timeout.
169 * Some M24LR devices may NACK I2C writes while an internal write operation
170 * is in progress. This function retries the write operation with a short delay
171 * until it succeeds or the timeout is reached.
172 *
173 * Returns:
174 * Number of bytes written on success,
175 * -ETIMEDOUT if the write fails within the timeout window.
176 */
m24lr_regmap_write(struct regmap * regmap,const u8 * buf,size_t size,unsigned int offset)177 static ssize_t m24lr_regmap_write(struct regmap *regmap, const u8 *buf,
178 size_t size, unsigned int offset)
179 {
180 int err;
181 unsigned long timeout, write_time;
182 ssize_t ret = -ETIMEDOUT;
183
184 timeout = jiffies + msecs_to_jiffies(M24LR_WRITE_TIMEOUT);
185
186 do {
187 write_time = jiffies;
188
189 err = regmap_bulk_write(regmap, offset, buf, size);
190 if (!err) {
191 ret = size;
192 break;
193 }
194
195 usleep_range(1000, 2000);
196 } while (time_before(write_time, timeout));
197
198 return ret;
199 }
200
m24lr_read(struct m24lr * m24lr,u8 * buf,size_t size,unsigned int offset,bool is_eeprom)201 static ssize_t m24lr_read(struct m24lr *m24lr, u8 *buf, size_t size,
202 unsigned int offset, bool is_eeprom)
203 {
204 struct regmap *regmap;
205 ssize_t ret;
206
207 if (is_eeprom)
208 regmap = m24lr->eeprom_regmap;
209 else
210 regmap = m24lr->ctl_regmap;
211
212 mutex_lock(&m24lr->lock);
213 ret = m24lr_regmap_read(regmap, buf, size, offset);
214 mutex_unlock(&m24lr->lock);
215
216 return ret;
217 }
218
219 /**
220 * m24lr_write - write buffer to M24LR device with page alignment handling
221 * @m24lr: pointer to driver context
222 * @buf: data buffer to write
223 * @size: number of bytes to write
224 * @offset: target register address in the device
225 * @is_eeprom: true if the write should target the EEPROM,
226 * false if it should target the system parameters sector.
227 *
228 * Writes data to the M24LR device using regmap, split into chunks no larger
229 * than page_size to respect device-specific write limitations (e.g., page
230 * size or I2C hold-time concerns). Each chunk is aligned to the page boundary
231 * defined by page_size.
232 *
233 * Returns:
234 * Total number of bytes written on success,
235 * A negative error code if any write fails.
236 */
m24lr_write(struct m24lr * m24lr,const u8 * buf,size_t size,unsigned int offset,bool is_eeprom)237 static ssize_t m24lr_write(struct m24lr *m24lr, const u8 *buf, size_t size,
238 unsigned int offset, bool is_eeprom)
239 {
240 unsigned int n, next_sector;
241 struct regmap *regmap;
242 ssize_t ret = 0;
243 ssize_t err;
244
245 if (is_eeprom)
246 regmap = m24lr->eeprom_regmap;
247 else
248 regmap = m24lr->ctl_regmap;
249
250 n = min_t(unsigned int, size, m24lr->page_size);
251 next_sector = roundup(offset + 1, m24lr->page_size);
252 if (offset + n > next_sector)
253 n = next_sector - offset;
254
255 mutex_lock(&m24lr->lock);
256 while (n) {
257 err = m24lr_regmap_write(regmap, buf + offset, n, offset);
258 if (IS_ERR_VALUE(err)) {
259 if (!ret)
260 ret = err;
261
262 break;
263 }
264
265 offset += n;
266 size -= n;
267 ret += n;
268 n = min_t(unsigned int, size, m24lr->page_size);
269 }
270 mutex_unlock(&m24lr->lock);
271
272 return ret;
273 }
274
275 /**
276 * m24lr_write_pass - Write password to M24LR043-R using secure format
277 * @m24lr: Pointer to device control structure
278 * @buf: Input buffer containing hex-encoded password
279 * @count: Number of bytes in @buf
280 * @code: Operation code to embed between password copies
281 *
282 * This function parses a 4-byte password, encodes it in big-endian format,
283 * and constructs a 9-byte sequence of the form:
284 *
285 * [BE(password), code, BE(password)]
286 *
287 * The result is written to register 0x0900 (2304), which is the password
288 * register in M24LR04E-R chip.
289 *
290 * Return: Number of bytes written on success, or negative error code on failure
291 */
m24lr_write_pass(struct m24lr * m24lr,const char * buf,size_t count,u8 code)292 static ssize_t m24lr_write_pass(struct m24lr *m24lr, const char *buf,
293 size_t count, u8 code)
294 {
295 __be32 be_pass;
296 u8 output[9];
297 ssize_t ret;
298 u32 pass;
299 int err;
300
301 if (!count)
302 return -EINVAL;
303
304 if (count > 8)
305 return -EINVAL;
306
307 err = kstrtou32(buf, 16, &pass);
308 if (err)
309 return err;
310
311 be_pass = cpu_to_be32(pass);
312
313 memcpy(output, &be_pass, sizeof(be_pass));
314 output[4] = code;
315 memcpy(output + 5, &be_pass, sizeof(be_pass));
316
317 mutex_lock(&m24lr->lock);
318 ret = m24lr_regmap_write(m24lr->ctl_regmap, output, 9, 2304);
319 mutex_unlock(&m24lr->lock);
320
321 return ret;
322 }
323
m24lr_read_reg_le(struct m24lr * m24lr,u64 * val,unsigned int reg_addr,unsigned int reg_size)324 static ssize_t m24lr_read_reg_le(struct m24lr *m24lr, u64 *val,
325 unsigned int reg_addr,
326 unsigned int reg_size)
327 {
328 ssize_t ret;
329 __le64 input = 0;
330
331 ret = m24lr_read(m24lr, (u8 *)&input, reg_size, reg_addr, false);
332 if (IS_ERR_VALUE(ret))
333 return ret;
334
335 if (ret != reg_size)
336 return -EINVAL;
337
338 switch (reg_size) {
339 case 1:
340 *val = *(u8 *)&input;
341 break;
342 case 2:
343 *val = le16_to_cpu((__le16)input);
344 break;
345 case 4:
346 *val = le32_to_cpu((__le32)input);
347 break;
348 case 8:
349 *val = le64_to_cpu((__le64)input);
350 break;
351 default:
352 return -EINVAL;
353 }
354
355 return 0;
356 }
357
m24lr_nvmem_read(void * priv,unsigned int offset,void * val,size_t bytes)358 static int m24lr_nvmem_read(void *priv, unsigned int offset, void *val,
359 size_t bytes)
360 {
361 ssize_t err;
362 struct m24lr *m24lr = priv;
363
364 if (!bytes)
365 return bytes;
366
367 if (offset + bytes > m24lr->eeprom_size)
368 return -EINVAL;
369
370 err = m24lr_read(m24lr, val, bytes, offset, true);
371 if (IS_ERR_VALUE(err))
372 return err;
373
374 return 0;
375 }
376
m24lr_nvmem_write(void * priv,unsigned int offset,void * val,size_t bytes)377 static int m24lr_nvmem_write(void *priv, unsigned int offset, void *val,
378 size_t bytes)
379 {
380 ssize_t err;
381 struct m24lr *m24lr = priv;
382
383 if (!bytes)
384 return -EINVAL;
385
386 if (offset + bytes > m24lr->eeprom_size)
387 return -EINVAL;
388
389 err = m24lr_write(m24lr, val, bytes, offset, true);
390 if (IS_ERR_VALUE(err))
391 return err;
392
393 return 0;
394 }
395
m24lr_ctl_sss_read(struct file * filep,struct kobject * kobj,const struct bin_attribute * attr,char * buf,loff_t offset,size_t count)396 static ssize_t m24lr_ctl_sss_read(struct file *filep, struct kobject *kobj,
397 const struct bin_attribute *attr, char *buf,
398 loff_t offset, size_t count)
399 {
400 struct m24lr *m24lr = attr->private;
401
402 if (!count)
403 return count;
404
405 if (size_add(offset, count) > m24lr->sss_len)
406 return -EINVAL;
407
408 return m24lr_read(m24lr, buf, count, offset, false);
409 }
410
m24lr_ctl_sss_write(struct file * filep,struct kobject * kobj,const struct bin_attribute * attr,char * buf,loff_t offset,size_t count)411 static ssize_t m24lr_ctl_sss_write(struct file *filep, struct kobject *kobj,
412 const struct bin_attribute *attr, char *buf,
413 loff_t offset, size_t count)
414 {
415 struct m24lr *m24lr = attr->private;
416
417 if (!count)
418 return -EINVAL;
419
420 if (size_add(offset, count) > m24lr->sss_len)
421 return -EINVAL;
422
423 return m24lr_write(m24lr, buf, count, offset, false);
424 }
425 static BIN_ATTR(sss, 0600, m24lr_ctl_sss_read, m24lr_ctl_sss_write, 0);
426
new_pass_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)427 static ssize_t new_pass_store(struct device *dev, struct device_attribute *attr,
428 const char *buf, size_t count)
429 {
430 struct m24lr *m24lr = i2c_get_clientdata(to_i2c_client(dev));
431
432 return m24lr_write_pass(m24lr, buf, count, 7);
433 }
434 static DEVICE_ATTR_WO(new_pass);
435
unlock_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)436 static ssize_t unlock_store(struct device *dev, struct device_attribute *attr,
437 const char *buf, size_t count)
438 {
439 struct m24lr *m24lr = i2c_get_clientdata(to_i2c_client(dev));
440
441 return m24lr_write_pass(m24lr, buf, count, 9);
442 }
443 static DEVICE_ATTR_WO(unlock);
444
uid_show(struct device * dev,struct device_attribute * attr,char * buf)445 static ssize_t uid_show(struct device *dev, struct device_attribute *attr,
446 char *buf)
447 {
448 struct m24lr *m24lr = i2c_get_clientdata(to_i2c_client(dev));
449
450 return sysfs_emit(buf, "%llx\n", m24lr->uid);
451 }
452 static DEVICE_ATTR_RO(uid);
453
total_sectors_show(struct device * dev,struct device_attribute * attr,char * buf)454 static ssize_t total_sectors_show(struct device *dev,
455 struct device_attribute *attr, char *buf)
456 {
457 struct m24lr *m24lr = i2c_get_clientdata(to_i2c_client(dev));
458
459 return sysfs_emit(buf, "%x\n", m24lr->sss_len);
460 }
461 static DEVICE_ATTR_RO(total_sectors);
462
463 static struct attribute *m24lr_ctl_dev_attrs[] = {
464 &dev_attr_unlock.attr,
465 &dev_attr_new_pass.attr,
466 &dev_attr_uid.attr,
467 &dev_attr_total_sectors.attr,
468 NULL,
469 };
470
m24lr_get_chip(struct device * dev)471 static const struct m24lr_chip *m24lr_get_chip(struct device *dev)
472 {
473 const struct m24lr_chip *ret;
474 const struct i2c_device_id *id;
475
476 id = i2c_match_id(m24lr_ids, to_i2c_client(dev));
477
478 if (dev->of_node && of_match_device(m24lr_of_match, dev))
479 ret = of_device_get_match_data(dev);
480 else if (id)
481 ret = (void *)id->driver_data;
482 else
483 ret = acpi_device_get_match_data(dev);
484
485 return ret;
486 }
487
m24lr_probe(struct i2c_client * client)488 static int m24lr_probe(struct i2c_client *client)
489 {
490 struct regmap_config eeprom_regmap_conf = {0};
491 struct nvmem_config nvmem_conf = {0};
492 struct device *dev = &client->dev;
493 struct i2c_client *eeprom_client;
494 const struct m24lr_chip *chip;
495 struct regmap *eeprom_regmap;
496 struct nvmem_device *nvmem;
497 struct regmap *ctl_regmap;
498 struct m24lr *m24lr;
499 u32 regs[2];
500 long err;
501
502 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
503 return -EOPNOTSUPP;
504
505 chip = m24lr_get_chip(dev);
506 if (!chip)
507 return -ENODEV;
508
509 m24lr = devm_kzalloc(dev, sizeof(struct m24lr), GFP_KERNEL);
510 if (!m24lr)
511 return -ENOMEM;
512
513 err = device_property_read_u32_array(dev, "reg", regs, ARRAY_SIZE(regs));
514 if (err)
515 return dev_err_probe(dev, err, "Failed to read 'reg' property\n");
516
517 /* Create a second I2C client for the eeprom interface */
518 eeprom_client = devm_i2c_new_dummy_device(dev, client->adapter, regs[1]);
519 if (IS_ERR(eeprom_client))
520 return dev_err_probe(dev, PTR_ERR(eeprom_client),
521 "Failed to create dummy I2C client for the EEPROM\n");
522
523 ctl_regmap = devm_regmap_init_i2c(client, &m24lr_ctl_regmap_conf);
524 if (IS_ERR(ctl_regmap))
525 return dev_err_probe(dev, PTR_ERR(ctl_regmap),
526 "Failed to init regmap\n");
527
528 eeprom_regmap_conf.name = "m24lr_eeprom";
529 eeprom_regmap_conf.reg_bits = 16;
530 eeprom_regmap_conf.val_bits = 8;
531 eeprom_regmap_conf.disable_locking = true;
532 eeprom_regmap_conf.max_register = chip->eeprom_size - 1;
533
534 eeprom_regmap = devm_regmap_init_i2c(eeprom_client,
535 &eeprom_regmap_conf);
536 if (IS_ERR(eeprom_regmap))
537 return dev_err_probe(dev, PTR_ERR(eeprom_regmap),
538 "Failed to init regmap\n");
539
540 mutex_init(&m24lr->lock);
541 m24lr->sss_len = chip->sss_len;
542 m24lr->page_size = chip->page_size;
543 m24lr->eeprom_size = chip->eeprom_size;
544 m24lr->eeprom_regmap = eeprom_regmap;
545 m24lr->ctl_regmap = ctl_regmap;
546
547 nvmem_conf.dev = &eeprom_client->dev;
548 nvmem_conf.owner = THIS_MODULE;
549 nvmem_conf.type = NVMEM_TYPE_EEPROM;
550 nvmem_conf.reg_read = m24lr_nvmem_read;
551 nvmem_conf.reg_write = m24lr_nvmem_write;
552 nvmem_conf.size = chip->eeprom_size;
553 nvmem_conf.word_size = 1;
554 nvmem_conf.stride = 1;
555 nvmem_conf.priv = m24lr;
556
557 nvmem = devm_nvmem_register(dev, &nvmem_conf);
558 if (IS_ERR(nvmem))
559 return dev_err_probe(dev, PTR_ERR(nvmem),
560 "Failed to register nvmem\n");
561
562 i2c_set_clientdata(client, m24lr);
563 i2c_set_clientdata(eeprom_client, m24lr);
564
565 bin_attr_sss.size = chip->sss_len;
566 bin_attr_sss.private = m24lr;
567 err = sysfs_create_bin_file(&dev->kobj, &bin_attr_sss);
568 if (err)
569 return dev_err_probe(dev, err,
570 "Failed to create sss bin file\n");
571
572 /* test by reading the uid, if success store it */
573 err = m24lr_read_reg_le(m24lr, &m24lr->uid, 2324, sizeof(m24lr->uid));
574 if (IS_ERR_VALUE(err))
575 goto remove_bin_file;
576
577 return 0;
578
579 remove_bin_file:
580 sysfs_remove_bin_file(&dev->kobj, &bin_attr_sss);
581
582 return err;
583 }
584
m24lr_remove(struct i2c_client * client)585 static void m24lr_remove(struct i2c_client *client)
586 {
587 sysfs_remove_bin_file(&client->dev.kobj, &bin_attr_sss);
588 }
589
590 ATTRIBUTE_GROUPS(m24lr_ctl_dev);
591
592 static struct i2c_driver m24lr_driver = {
593 .driver = {
594 .name = "m24lr",
595 .of_match_table = m24lr_of_match,
596 .dev_groups = m24lr_ctl_dev_groups,
597 },
598 .probe = m24lr_probe,
599 .remove = m24lr_remove,
600 .id_table = m24lr_ids,
601 };
602 module_i2c_driver(m24lr_driver);
603
604 MODULE_AUTHOR("Abd-Alrhman Masalkhi");
605 MODULE_DESCRIPTION("st m24lr control driver");
606 MODULE_LICENSE("GPL");
607