w1_ds250x.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/moduleparam.h>
  8. #include <linux/device.h>
  9. #include <linux/types.h>
  10. #include <linux/delay.h>
  11. #include <linux/slab.h>
  12. #include <linux/crc16.h>
  13. #include <linux/w1.h>
  14. #include <linux/nvmem-provider.h>
  15. #define W1_DS2501_UNW_FAMILY 0x91
  16. #define W1_DS2501_SIZE 64
  17. #define W1_DS2502_FAMILY 0x09
  18. #define W1_DS2502_UNW_FAMILY 0x89
  19. #define W1_DS2502_SIZE 128
  20. #define W1_DS2505_FAMILY 0x0b
  21. #define W1_DS2505_SIZE 2048
  22. #define W1_PAGE_SIZE 32
  23. #define W1_EXT_READ_MEMORY 0xA5
  24. #define W1_READ_DATA_CRC 0xC3
  25. #define OFF2PG(off) ((off) / W1_PAGE_SIZE)
  26. #define CRC16_INIT 0
  27. #define CRC16_VALID 0xb001
  28. struct w1_eprom_data {
  29. size_t size;
  30. int (*read)(struct w1_slave *sl, int pageno);
  31. u8 eprom[W1_DS2505_SIZE];
  32. DECLARE_BITMAP(page_present, W1_DS2505_SIZE / W1_PAGE_SIZE);
  33. char nvmem_name[64];
  34. };
  35. static int w1_ds2502_read_page(struct w1_slave *sl, int pageno)
  36. {
  37. struct w1_eprom_data *data = sl->family_data;
  38. int pgoff = pageno * W1_PAGE_SIZE;
  39. int ret = -EIO;
  40. u8 buf[3];
  41. u8 crc8;
  42. if (test_bit(pageno, data->page_present))
  43. return 0; /* page already present */
  44. mutex_lock(&sl->master->bus_mutex);
  45. if (w1_reset_select_slave(sl))
  46. goto err;
  47. buf[0] = W1_READ_DATA_CRC;
  48. buf[1] = pgoff & 0xff;
  49. buf[2] = pgoff >> 8;
  50. w1_write_block(sl->master, buf, 3);
  51. crc8 = w1_read_8(sl->master);
  52. if (w1_calc_crc8(buf, 3) != crc8)
  53. goto err;
  54. w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE);
  55. crc8 = w1_read_8(sl->master);
  56. if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8)
  57. goto err;
  58. set_bit(pageno, data->page_present); /* mark page present */
  59. ret = 0;
  60. err:
  61. mutex_unlock(&sl->master->bus_mutex);
  62. return ret;
  63. }
  64. static int w1_ds2505_read_page(struct w1_slave *sl, int pageno)
  65. {
  66. struct w1_eprom_data *data = sl->family_data;
  67. int redir_retries = 16;
  68. int pgoff, epoff;
  69. int ret = -EIO;
  70. u8 buf[6];
  71. u8 redir;
  72. u16 crc;
  73. if (test_bit(pageno, data->page_present))
  74. return 0; /* page already present */
  75. epoff = pgoff = pageno * W1_PAGE_SIZE;
  76. mutex_lock(&sl->master->bus_mutex);
  77. retry:
  78. if (w1_reset_select_slave(sl))
  79. goto err;
  80. buf[0] = W1_EXT_READ_MEMORY;
  81. buf[1] = pgoff & 0xff;
  82. buf[2] = pgoff >> 8;
  83. w1_write_block(sl->master, buf, 3);
  84. w1_read_block(sl->master, buf + 3, 3); /* redir, crc16 */
  85. redir = buf[3];
  86. crc = crc16(CRC16_INIT, buf, 6);
  87. if (crc != CRC16_VALID)
  88. goto err;
  89. if (redir != 0xff) {
  90. redir_retries--;
  91. if (redir_retries < 0)
  92. goto err;
  93. pgoff = (redir ^ 0xff) * W1_PAGE_SIZE;
  94. goto retry;
  95. }
  96. w1_read_block(sl->master, &data->eprom[epoff], W1_PAGE_SIZE);
  97. w1_read_block(sl->master, buf, 2); /* crc16 */
  98. crc = crc16(CRC16_INIT, &data->eprom[epoff], W1_PAGE_SIZE);
  99. crc = crc16(crc, buf, 2);
  100. if (crc != CRC16_VALID)
  101. goto err;
  102. set_bit(pageno, data->page_present);
  103. ret = 0;
  104. err:
  105. mutex_unlock(&sl->master->bus_mutex);
  106. return ret;
  107. }
  108. static int w1_nvmem_read(void *priv, unsigned int off, void *buf, size_t count)
  109. {
  110. struct w1_slave *sl = priv;
  111. struct w1_eprom_data *data = sl->family_data;
  112. size_t eprom_size = data->size;
  113. int ret;
  114. int i;
  115. if (off > eprom_size)
  116. return -EINVAL;
  117. if ((off + count) > eprom_size)
  118. count = eprom_size - off;
  119. i = OFF2PG(off);
  120. do {
  121. ret = data->read(sl, i++);
  122. if (ret < 0)
  123. return ret;
  124. } while (i < OFF2PG(off + count));
  125. memcpy(buf, &data->eprom[off], count);
  126. return 0;
  127. }
  128. static int w1_eprom_add_slave(struct w1_slave *sl)
  129. {
  130. struct w1_eprom_data *data;
  131. struct nvmem_device *nvmem;
  132. struct nvmem_config nvmem_cfg = {
  133. .dev = &sl->dev,
  134. .reg_read = w1_nvmem_read,
  135. .type = NVMEM_TYPE_OTP,
  136. .read_only = true,
  137. .word_size = 1,
  138. .priv = sl,
  139. .id = -1
  140. };
  141. data = devm_kzalloc(&sl->dev, sizeof(struct w1_eprom_data), GFP_KERNEL);
  142. if (!data)
  143. return -ENOMEM;
  144. sl->family_data = data;
  145. switch (sl->family->fid) {
  146. case W1_DS2501_UNW_FAMILY:
  147. data->size = W1_DS2501_SIZE;
  148. data->read = w1_ds2502_read_page;
  149. break;
  150. case W1_DS2502_FAMILY:
  151. case W1_DS2502_UNW_FAMILY:
  152. data->size = W1_DS2502_SIZE;
  153. data->read = w1_ds2502_read_page;
  154. break;
  155. case W1_DS2505_FAMILY:
  156. data->size = W1_DS2505_SIZE;
  157. data->read = w1_ds2505_read_page;
  158. break;
  159. }
  160. if (sl->master->bus_master->dev_id)
  161. snprintf(data->nvmem_name, sizeof(data->nvmem_name),
  162. "%s-%02x-%012llx",
  163. sl->master->bus_master->dev_id, sl->reg_num.family,
  164. (unsigned long long)sl->reg_num.id);
  165. else
  166. snprintf(data->nvmem_name, sizeof(data->nvmem_name),
  167. "%02x-%012llx",
  168. sl->reg_num.family,
  169. (unsigned long long)sl->reg_num.id);
  170. nvmem_cfg.name = data->nvmem_name;
  171. nvmem_cfg.size = data->size;
  172. nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg);
  173. return PTR_ERR_OR_ZERO(nvmem);
  174. }
  175. static const struct w1_family_ops w1_eprom_fops = {
  176. .add_slave = w1_eprom_add_slave,
  177. };
  178. static struct w1_family w1_family_09 = {
  179. .fid = W1_DS2502_FAMILY,
  180. .fops = &w1_eprom_fops,
  181. };
  182. static struct w1_family w1_family_0b = {
  183. .fid = W1_DS2505_FAMILY,
  184. .fops = &w1_eprom_fops,
  185. };
  186. static struct w1_family w1_family_89 = {
  187. .fid = W1_DS2502_UNW_FAMILY,
  188. .fops = &w1_eprom_fops,
  189. };
  190. static struct w1_family w1_family_91 = {
  191. .fid = W1_DS2501_UNW_FAMILY,
  192. .fops = &w1_eprom_fops,
  193. };
  194. static int __init w1_ds250x_init(void)
  195. {
  196. int err;
  197. err = w1_register_family(&w1_family_09);
  198. if (err)
  199. return err;
  200. err = w1_register_family(&w1_family_0b);
  201. if (err)
  202. goto err_0b;
  203. err = w1_register_family(&w1_family_89);
  204. if (err)
  205. goto err_89;
  206. err = w1_register_family(&w1_family_91);
  207. if (err)
  208. goto err_91;
  209. return 0;
  210. err_91:
  211. w1_unregister_family(&w1_family_89);
  212. err_89:
  213. w1_unregister_family(&w1_family_0b);
  214. err_0b:
  215. w1_unregister_family(&w1_family_09);
  216. return err;
  217. }
  218. static void __exit w1_ds250x_exit(void)
  219. {
  220. w1_unregister_family(&w1_family_09);
  221. w1_unregister_family(&w1_family_0b);
  222. w1_unregister_family(&w1_family_89);
  223. w1_unregister_family(&w1_family_91);
  224. }
  225. module_init(w1_ds250x_init);
  226. module_exit(w1_ds250x_exit);
  227. MODULE_AUTHOR("Thomas Bogendoerfer <[email protected]>");
  228. MODULE_DESCRIPTION("w1 family driver for DS250x Add Only Memory");
  229. MODULE_LICENSE("GPL");
  230. MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_FAMILY));
  231. MODULE_ALIAS("w1-family-" __stringify(W1_DS2505_FAMILY));
  232. MODULE_ALIAS("w1-family-" __stringify(W1_DS2501_UNW_FAMILY));
  233. MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_UNW_FAMILY));