m24lr.c 16 KB

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