b53_spi.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * B53 register access through SPI
  3. *
  4. * Copyright (C) 2011-2013 Jonas Gorski <jogo@openwrt.org>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <asm/unaligned.h>
  19. #include <linux/kernel.h>
  20. #include <linux/module.h>
  21. #include <linux/spi/spi.h>
  22. #include <linux/platform_data/b53.h>
  23. #include "b53_priv.h"
  24. #define B53_SPI_DATA 0xf0
  25. #define B53_SPI_STATUS 0xfe
  26. #define B53_SPI_CMD_SPIF BIT(7)
  27. #define B53_SPI_CMD_RACK BIT(5)
  28. #define B53_SPI_CMD_READ 0x00
  29. #define B53_SPI_CMD_WRITE 0x01
  30. #define B53_SPI_CMD_NORMAL 0x60
  31. #define B53_SPI_CMD_FAST 0x10
  32. #define B53_SPI_PAGE_SELECT 0xff
  33. static inline int b53_spi_read_reg(struct spi_device *spi, u8 reg, u8 *val,
  34. unsigned len)
  35. {
  36. u8 txbuf[2];
  37. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_READ;
  38. txbuf[1] = reg;
  39. return spi_write_then_read(spi, txbuf, 2, val, len);
  40. }
  41. static inline int b53_spi_clear_status(struct spi_device *spi)
  42. {
  43. unsigned int i;
  44. u8 rxbuf;
  45. int ret;
  46. for (i = 0; i < 10; i++) {
  47. ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1);
  48. if (ret)
  49. return ret;
  50. if (!(rxbuf & B53_SPI_CMD_SPIF))
  51. break;
  52. mdelay(1);
  53. }
  54. if (i == 10)
  55. return -EIO;
  56. return 0;
  57. }
  58. static inline int b53_spi_set_page(struct spi_device *spi, u8 page)
  59. {
  60. u8 txbuf[3];
  61. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  62. txbuf[1] = B53_SPI_PAGE_SELECT;
  63. txbuf[2] = page;
  64. return spi_write(spi, txbuf, sizeof(txbuf));
  65. }
  66. static inline int b53_prepare_reg_access(struct spi_device *spi, u8 page)
  67. {
  68. int ret = b53_spi_clear_status(spi);
  69. if (ret)
  70. return ret;
  71. return b53_spi_set_page(spi, page);
  72. }
  73. static int b53_spi_prepare_reg_read(struct spi_device *spi, u8 reg)
  74. {
  75. u8 rxbuf;
  76. int retry_count;
  77. int ret;
  78. ret = b53_spi_read_reg(spi, reg, &rxbuf, 1);
  79. if (ret)
  80. return ret;
  81. for (retry_count = 0; retry_count < 10; retry_count++) {
  82. ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1);
  83. if (ret)
  84. return ret;
  85. if (rxbuf & B53_SPI_CMD_RACK)
  86. break;
  87. mdelay(1);
  88. }
  89. if (retry_count == 10)
  90. return -EIO;
  91. return 0;
  92. }
  93. static int b53_spi_read(struct b53_device *dev, u8 page, u8 reg, u8 *data,
  94. unsigned len)
  95. {
  96. struct spi_device *spi = dev->priv;
  97. int ret;
  98. ret = b53_prepare_reg_access(spi, page);
  99. if (ret)
  100. return ret;
  101. ret = b53_spi_prepare_reg_read(spi, reg);
  102. if (ret)
  103. return ret;
  104. return b53_spi_read_reg(spi, B53_SPI_DATA, data, len);
  105. }
  106. static int b53_spi_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
  107. {
  108. return b53_spi_read(dev, page, reg, val, 1);
  109. }
  110. static int b53_spi_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val)
  111. {
  112. int ret = b53_spi_read(dev, page, reg, (u8 *)val, 2);
  113. if (!ret)
  114. *val = le16_to_cpu(*val);
  115. return ret;
  116. }
  117. static int b53_spi_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val)
  118. {
  119. int ret = b53_spi_read(dev, page, reg, (u8 *)val, 4);
  120. if (!ret)
  121. *val = le32_to_cpu(*val);
  122. return ret;
  123. }
  124. static int b53_spi_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val)
  125. {
  126. int ret;
  127. *val = 0;
  128. ret = b53_spi_read(dev, page, reg, (u8 *)val, 6);
  129. if (!ret)
  130. *val = le64_to_cpu(*val);
  131. return ret;
  132. }
  133. static int b53_spi_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val)
  134. {
  135. int ret = b53_spi_read(dev, page, reg, (u8 *)val, 8);
  136. if (!ret)
  137. *val = le64_to_cpu(*val);
  138. return ret;
  139. }
  140. static int b53_spi_write8(struct b53_device *dev, u8 page, u8 reg, u8 value)
  141. {
  142. struct spi_device *spi = dev->priv;
  143. int ret;
  144. u8 txbuf[3];
  145. ret = b53_prepare_reg_access(spi, page);
  146. if (ret)
  147. return ret;
  148. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  149. txbuf[1] = reg;
  150. txbuf[2] = value;
  151. return spi_write(spi, txbuf, sizeof(txbuf));
  152. }
  153. static int b53_spi_write16(struct b53_device *dev, u8 page, u8 reg, u16 value)
  154. {
  155. struct spi_device *spi = dev->priv;
  156. int ret;
  157. u8 txbuf[4];
  158. ret = b53_prepare_reg_access(spi, page);
  159. if (ret)
  160. return ret;
  161. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  162. txbuf[1] = reg;
  163. put_unaligned_le16(value, &txbuf[2]);
  164. return spi_write(spi, txbuf, sizeof(txbuf));
  165. }
  166. static int b53_spi_write32(struct b53_device *dev, u8 page, u8 reg, u32 value)
  167. {
  168. struct spi_device *spi = dev->priv;
  169. int ret;
  170. u8 txbuf[6];
  171. ret = b53_prepare_reg_access(spi, page);
  172. if (ret)
  173. return ret;
  174. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  175. txbuf[1] = reg;
  176. put_unaligned_le32(value, &txbuf[2]);
  177. return spi_write(spi, txbuf, sizeof(txbuf));
  178. }
  179. static int b53_spi_write48(struct b53_device *dev, u8 page, u8 reg, u64 value)
  180. {
  181. struct spi_device *spi = dev->priv;
  182. int ret;
  183. u8 txbuf[10];
  184. ret = b53_prepare_reg_access(spi, page);
  185. if (ret)
  186. return ret;
  187. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  188. txbuf[1] = reg;
  189. put_unaligned_le64(value, &txbuf[2]);
  190. return spi_write(spi, txbuf, sizeof(txbuf) - 2);
  191. }
  192. static int b53_spi_write64(struct b53_device *dev, u8 page, u8 reg, u64 value)
  193. {
  194. struct spi_device *spi = dev->priv;
  195. int ret;
  196. u8 txbuf[10];
  197. ret = b53_prepare_reg_access(spi, page);
  198. if (ret)
  199. return ret;
  200. txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE;
  201. txbuf[1] = reg;
  202. put_unaligned_le64(value, &txbuf[2]);
  203. return spi_write(spi, txbuf, sizeof(txbuf));
  204. }
  205. static struct b53_io_ops b53_spi_ops = {
  206. .read8 = b53_spi_read8,
  207. .read16 = b53_spi_read16,
  208. .read32 = b53_spi_read32,
  209. .read48 = b53_spi_read48,
  210. .read64 = b53_spi_read64,
  211. .write8 = b53_spi_write8,
  212. .write16 = b53_spi_write16,
  213. .write32 = b53_spi_write32,
  214. .write48 = b53_spi_write48,
  215. .write64 = b53_spi_write64,
  216. };
  217. static int b53_spi_probe(struct spi_device *spi)
  218. {
  219. struct b53_device *dev;
  220. int ret;
  221. dev = b53_switch_alloc(&spi->dev, &b53_spi_ops, spi);
  222. if (!dev)
  223. return -ENOMEM;
  224. if (spi->dev.platform_data)
  225. dev->pdata = spi->dev.platform_data;
  226. ret = b53_switch_register(dev);
  227. if (ret)
  228. return ret;
  229. spi_set_drvdata(spi, dev);
  230. return 0;
  231. }
  232. static int b53_spi_remove(struct spi_device *spi)
  233. {
  234. struct b53_device *dev = spi_get_drvdata(spi);
  235. if (dev)
  236. b53_switch_remove(dev);
  237. return 0;
  238. }
  239. static struct spi_driver b53_spi_driver = {
  240. .driver = {
  241. .name = "b53-switch",
  242. .bus = &spi_bus_type,
  243. .owner = THIS_MODULE,
  244. },
  245. .probe = b53_spi_probe,
  246. .remove = b53_spi_remove,
  247. };
  248. module_spi_driver(b53_spi_driver);
  249. MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
  250. MODULE_DESCRIPTION("B53 SPI access driver");
  251. MODULE_LICENSE("Dual BSD/GPL");