i2c_eeprom.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2014 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <eeprom.h>
  7. #include <linux/err.h>
  8. #include <linux/kernel.h>
  9. #include <dm.h>
  10. #include <dm/device-internal.h>
  11. #include <i2c.h>
  12. #include <i2c_eeprom.h>
  13. struct i2c_eeprom_drv_data {
  14. u32 size; /* size in bytes */
  15. u32 pagewidth; /* pagesize = 2^pagewidth */
  16. u32 addr_offset_mask; /* bits in addr used for offset overflow */
  17. u32 offset_len; /* size in bytes of offset */
  18. };
  19. int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size)
  20. {
  21. const struct i2c_eeprom_ops *ops = device_get_ops(dev);
  22. if (!ops->read)
  23. return -ENOSYS;
  24. return ops->read(dev, offset, buf, size);
  25. }
  26. int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size)
  27. {
  28. const struct i2c_eeprom_ops *ops = device_get_ops(dev);
  29. if (!ops->write)
  30. return -ENOSYS;
  31. return ops->write(dev, offset, buf, size);
  32. }
  33. int i2c_eeprom_size(struct udevice *dev)
  34. {
  35. const struct i2c_eeprom_ops *ops = device_get_ops(dev);
  36. if (!ops->size)
  37. return -ENOSYS;
  38. return ops->size(dev);
  39. }
  40. static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf,
  41. int size)
  42. {
  43. return dm_i2c_read(dev, offset, buf, size);
  44. }
  45. static int i2c_eeprom_std_write(struct udevice *dev, int offset,
  46. const uint8_t *buf, int size)
  47. {
  48. struct i2c_eeprom *priv = dev_get_priv(dev);
  49. int ret;
  50. while (size > 0) {
  51. int write_size = min_t(int, size, priv->pagesize);
  52. ret = dm_i2c_write(dev, offset, buf, write_size);
  53. if (ret)
  54. return ret;
  55. offset += write_size;
  56. buf += write_size;
  57. size -= write_size;
  58. udelay(10000);
  59. }
  60. return 0;
  61. }
  62. static int i2c_eeprom_std_size(struct udevice *dev)
  63. {
  64. struct i2c_eeprom *priv = dev_get_priv(dev);
  65. return priv->size;
  66. }
  67. static const struct i2c_eeprom_ops i2c_eeprom_std_ops = {
  68. .read = i2c_eeprom_std_read,
  69. .write = i2c_eeprom_std_write,
  70. .size = i2c_eeprom_std_size,
  71. };
  72. static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
  73. {
  74. struct i2c_eeprom *priv = dev_get_priv(dev);
  75. struct i2c_eeprom_drv_data *data =
  76. (struct i2c_eeprom_drv_data *)dev_get_driver_data(dev);
  77. u32 pagesize;
  78. u32 size;
  79. if (dev_read_u32(dev, "pagesize", &pagesize) == 0)
  80. priv->pagesize = pagesize;
  81. else
  82. /* 6 bit -> page size of up to 2^63 (should be sufficient) */
  83. priv->pagesize = 1 << data->pagewidth;
  84. if (dev_read_u32(dev, "size", &size) == 0)
  85. priv->size = size;
  86. else
  87. priv->size = data->size;
  88. return 0;
  89. }
  90. static int i2c_eeprom_std_bind(struct udevice *dev)
  91. {
  92. ofnode partitions = ofnode_find_subnode(dev_ofnode(dev), "partitions");
  93. ofnode partition;
  94. const char *name;
  95. if (!ofnode_valid(partitions))
  96. return 0;
  97. if (!ofnode_device_is_compatible(partitions, "fixed-partitions"))
  98. return -ENOTSUPP;
  99. ofnode_for_each_subnode(partition, partitions) {
  100. name = ofnode_get_name(partition);
  101. if (!name)
  102. continue;
  103. device_bind_ofnode(dev, DM_GET_DRIVER(i2c_eeprom_partition),
  104. name, NULL, partition, NULL);
  105. }
  106. return 0;
  107. }
  108. static int i2c_eeprom_std_probe(struct udevice *dev)
  109. {
  110. u8 test_byte;
  111. int ret;
  112. struct i2c_eeprom_drv_data *data =
  113. (struct i2c_eeprom_drv_data *)dev_get_driver_data(dev);
  114. i2c_set_chip_offset_len(dev, data->offset_len);
  115. i2c_set_chip_addr_offset_mask(dev, data->addr_offset_mask);
  116. /* Verify that the chip is functional */
  117. ret = i2c_eeprom_read(dev, 0, &test_byte, 1);
  118. if (ret)
  119. return -ENODEV;
  120. return 0;
  121. }
  122. static const struct i2c_eeprom_drv_data eeprom_data = {
  123. .size = 0,
  124. .pagewidth = 0,
  125. .addr_offset_mask = 0,
  126. .offset_len = 1,
  127. };
  128. static const struct i2c_eeprom_drv_data mc24aa02e48_data = {
  129. .size = 256,
  130. .pagewidth = 3,
  131. .addr_offset_mask = 0,
  132. .offset_len = 1,
  133. };
  134. static const struct i2c_eeprom_drv_data atmel24c01a_data = {
  135. .size = 128,
  136. .pagewidth = 3,
  137. .addr_offset_mask = 0,
  138. .offset_len = 1,
  139. };
  140. static const struct i2c_eeprom_drv_data atmel24c02_data = {
  141. .size = 256,
  142. .pagewidth = 3,
  143. .addr_offset_mask = 0,
  144. .offset_len = 1,
  145. };
  146. static const struct i2c_eeprom_drv_data atmel24c04_data = {
  147. .size = 512,
  148. .pagewidth = 4,
  149. .addr_offset_mask = 0x1,
  150. .offset_len = 1,
  151. };
  152. static const struct i2c_eeprom_drv_data atmel24c08_data = {
  153. .size = 1024,
  154. .pagewidth = 4,
  155. .addr_offset_mask = 0x3,
  156. .offset_len = 1,
  157. };
  158. static const struct i2c_eeprom_drv_data atmel24c08a_data = {
  159. .size = 1024,
  160. .pagewidth = 4,
  161. .addr_offset_mask = 0x3,
  162. .offset_len = 1,
  163. };
  164. static const struct i2c_eeprom_drv_data atmel24c16a_data = {
  165. .size = 2048,
  166. .pagewidth = 4,
  167. .addr_offset_mask = 0x7,
  168. .offset_len = 1,
  169. };
  170. static const struct i2c_eeprom_drv_data atmel24mac402_data = {
  171. .size = 256,
  172. .pagewidth = 4,
  173. .addr_offset_mask = 0,
  174. .offset_len = 1,
  175. };
  176. static const struct i2c_eeprom_drv_data atmel24c32_data = {
  177. .size = 4096,
  178. .pagewidth = 5,
  179. .addr_offset_mask = 0,
  180. .offset_len = 2,
  181. };
  182. static const struct i2c_eeprom_drv_data atmel24c64_data = {
  183. .size = 8192,
  184. .pagewidth = 5,
  185. .addr_offset_mask = 0,
  186. .offset_len = 2,
  187. };
  188. static const struct i2c_eeprom_drv_data atmel24c128_data = {
  189. .size = 16384,
  190. .pagewidth = 6,
  191. .addr_offset_mask = 0,
  192. .offset_len = 2,
  193. };
  194. static const struct i2c_eeprom_drv_data atmel24c256_data = {
  195. .size = 32768,
  196. .pagewidth = 6,
  197. .addr_offset_mask = 0,
  198. .offset_len = 2,
  199. };
  200. static const struct i2c_eeprom_drv_data atmel24c512_data = {
  201. .size = 65536,
  202. .pagewidth = 6,
  203. .addr_offset_mask = 0,
  204. .offset_len = 2,
  205. };
  206. static const struct udevice_id i2c_eeprom_std_ids[] = {
  207. { .compatible = "i2c-eeprom", (ulong)&eeprom_data },
  208. { .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data },
  209. { .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data },
  210. { .compatible = "atmel,24c02", (ulong)&atmel24c02_data },
  211. { .compatible = "atmel,24c04", (ulong)&atmel24c04_data },
  212. { .compatible = "atmel,24c08", (ulong)&atmel24c08_data },
  213. { .compatible = "atmel,24c08a", (ulong)&atmel24c08a_data },
  214. { .compatible = "atmel,24c16a", (ulong)&atmel24c16a_data },
  215. { .compatible = "atmel,24mac402", (ulong)&atmel24mac402_data },
  216. { .compatible = "atmel,24c32", (ulong)&atmel24c32_data },
  217. { .compatible = "atmel,24c64", (ulong)&atmel24c64_data },
  218. { .compatible = "atmel,24c128", (ulong)&atmel24c128_data },
  219. { .compatible = "atmel,24c256", (ulong)&atmel24c256_data },
  220. { .compatible = "atmel,24c512", (ulong)&atmel24c512_data },
  221. { }
  222. };
  223. U_BOOT_DRIVER(i2c_eeprom_std) = {
  224. .name = "i2c_eeprom",
  225. .id = UCLASS_I2C_EEPROM,
  226. .of_match = i2c_eeprom_std_ids,
  227. .bind = i2c_eeprom_std_bind,
  228. .probe = i2c_eeprom_std_probe,
  229. .ofdata_to_platdata = i2c_eeprom_std_ofdata_to_platdata,
  230. .priv_auto_alloc_size = sizeof(struct i2c_eeprom),
  231. .ops = &i2c_eeprom_std_ops,
  232. };
  233. struct i2c_eeprom_partition {
  234. u32 offset;
  235. u32 size;
  236. };
  237. static int i2c_eeprom_partition_probe(struct udevice *dev)
  238. {
  239. return 0;
  240. }
  241. static int i2c_eeprom_partition_ofdata_to_platdata(struct udevice *dev)
  242. {
  243. struct i2c_eeprom_partition *priv = dev_get_priv(dev);
  244. u32 offset, size;
  245. int ret;
  246. ret = dev_read_u32(dev, "offset", &offset);
  247. if (ret)
  248. return ret;
  249. ret = dev_read_u32(dev, "size", &size);
  250. if (ret)
  251. return ret;
  252. priv->offset = offset;
  253. priv->size = size;
  254. return 0;
  255. }
  256. static int i2c_eeprom_partition_read(struct udevice *dev, int offset,
  257. u8 *buf, int size)
  258. {
  259. struct i2c_eeprom_partition *priv = dev_get_priv(dev);
  260. struct udevice *parent = dev_get_parent(dev);
  261. if (!parent)
  262. return -ENODEV;
  263. if (offset + size > priv->size)
  264. return -EINVAL;
  265. return i2c_eeprom_read(parent, offset + priv->offset, buf, size);
  266. }
  267. static int i2c_eeprom_partition_write(struct udevice *dev, int offset,
  268. const u8 *buf, int size)
  269. {
  270. struct i2c_eeprom_partition *priv = dev_get_priv(dev);
  271. struct udevice *parent = dev_get_parent(dev);
  272. if (!parent)
  273. return -ENODEV;
  274. if (offset + size > priv->size)
  275. return -EINVAL;
  276. return i2c_eeprom_write(parent, offset + priv->offset, (uint8_t *)buf,
  277. size);
  278. }
  279. static int i2c_eeprom_partition_size(struct udevice *dev)
  280. {
  281. struct i2c_eeprom_partition *priv = dev_get_priv(dev);
  282. return priv->size;
  283. }
  284. static const struct i2c_eeprom_ops i2c_eeprom_partition_ops = {
  285. .read = i2c_eeprom_partition_read,
  286. .write = i2c_eeprom_partition_write,
  287. .size = i2c_eeprom_partition_size,
  288. };
  289. U_BOOT_DRIVER(i2c_eeprom_partition) = {
  290. .name = "i2c_eeprom_partition",
  291. .id = UCLASS_I2C_EEPROM,
  292. .probe = i2c_eeprom_partition_probe,
  293. .ofdata_to_platdata = i2c_eeprom_partition_ofdata_to_platdata,
  294. .priv_auto_alloc_size = sizeof(struct i2c_eeprom_partition),
  295. .ops = &i2c_eeprom_partition_ops,
  296. };
  297. UCLASS_DRIVER(i2c_eeprom) = {
  298. .id = UCLASS_I2C_EEPROM,
  299. .name = "i2c_eeprom",
  300. };