oc_tiny_spi.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Opencore tiny_spi driver
  3. *
  4. * http://opencores.org/project,tiny_spi
  5. *
  6. * based on bfin_spi.c
  7. * Copyright (c) 2005-2008 Analog Devices Inc.
  8. * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
  9. *
  10. * Licensed under the GPL-2 or later.
  11. */
  12. #include <common.h>
  13. #include <asm/io.h>
  14. #include <malloc.h>
  15. #include <spi.h>
  16. #include <asm/gpio.h>
  17. #define TINY_SPI_STATUS_TXE 0x1
  18. #define TINY_SPI_STATUS_TXR 0x2
  19. struct tiny_spi_regs {
  20. unsigned rxdata; /* Rx data reg */
  21. unsigned txdata; /* Tx data reg */
  22. unsigned status; /* Status reg */
  23. unsigned control; /* Control reg */
  24. unsigned baud; /* Baud reg */
  25. };
  26. struct tiny_spi_host {
  27. uint base;
  28. uint freq;
  29. uint baudwidth;
  30. };
  31. static const struct tiny_spi_host tiny_spi_host_list[] =
  32. CONFIG_SYS_TINY_SPI_LIST;
  33. struct tiny_spi_slave {
  34. struct spi_slave slave;
  35. const struct tiny_spi_host *host;
  36. uint mode;
  37. uint baud;
  38. uint flg;
  39. };
  40. #define to_tiny_spi_slave(s) container_of(s, struct tiny_spi_slave, slave)
  41. int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  42. {
  43. return bus < ARRAY_SIZE(tiny_spi_host_list) && gpio_is_valid(cs);
  44. }
  45. void spi_cs_activate(struct spi_slave *slave)
  46. {
  47. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  48. unsigned int cs = slave->cs;
  49. gpio_set_value(cs, tiny_spi->flg);
  50. debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
  51. }
  52. void spi_cs_deactivate(struct spi_slave *slave)
  53. {
  54. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  55. unsigned int cs = slave->cs;
  56. gpio_set_value(cs, !tiny_spi->flg);
  57. debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
  58. }
  59. void spi_set_speed(struct spi_slave *slave, uint hz)
  60. {
  61. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  62. const struct tiny_spi_host *host = tiny_spi->host;
  63. tiny_spi->baud = min(DIV_ROUND_UP(host->freq, hz * 2),
  64. (1 << host->baudwidth)) - 1;
  65. debug("%s: speed %u actual %u\n", __func__, hz,
  66. host->freq / ((tiny_spi->baud + 1) * 2));
  67. }
  68. void spi_init(void)
  69. {
  70. }
  71. struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  72. unsigned int hz, unsigned int mode)
  73. {
  74. struct tiny_spi_slave *tiny_spi;
  75. if (!spi_cs_is_valid(bus, cs) || gpio_request(cs, "tiny_spi"))
  76. return NULL;
  77. tiny_spi = malloc(sizeof(*tiny_spi));
  78. if (!tiny_spi)
  79. return NULL;
  80. memset(tiny_spi, 0, sizeof(*tiny_spi));
  81. tiny_spi->slave.bus = bus;
  82. tiny_spi->slave.cs = cs;
  83. tiny_spi->host = &tiny_spi_host_list[bus];
  84. tiny_spi->mode = mode & (SPI_CPOL | SPI_CPHA);
  85. tiny_spi->flg = mode & SPI_CS_HIGH ? 1 : 0;
  86. spi_set_speed(&tiny_spi->slave, hz);
  87. debug("%s: bus:%i cs:%i base:%lx\n", __func__,
  88. bus, cs, tiny_spi->host->base);
  89. return &tiny_spi->slave;
  90. }
  91. void spi_free_slave(struct spi_slave *slave)
  92. {
  93. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  94. gpio_free(slave->cs);
  95. free(tiny_spi);
  96. }
  97. int spi_claim_bus(struct spi_slave *slave)
  98. {
  99. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  100. struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
  101. debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
  102. gpio_direction_output(slave->cs, !tiny_spi->flg);
  103. writel(tiny_spi->mode, &regs->control);
  104. writel(tiny_spi->baud, &regs->baud);
  105. return 0;
  106. }
  107. void spi_release_bus(struct spi_slave *slave)
  108. {
  109. debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
  110. }
  111. #ifndef CONFIG_TINY_SPI_IDLE_VAL
  112. # define CONFIG_TINY_SPI_IDLE_VAL 0xff
  113. #endif
  114. int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
  115. void *din, unsigned long flags)
  116. {
  117. struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
  118. struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
  119. const u8 *txp = dout;
  120. u8 *rxp = din;
  121. uint bytes = bitlen / 8;
  122. uint i;
  123. debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
  124. slave->bus, slave->cs, bitlen, bytes, flags);
  125. if (bitlen == 0)
  126. goto done;
  127. /* assume to do 8 bits transfers */
  128. if (bitlen % 8) {
  129. flags |= SPI_XFER_END;
  130. goto done;
  131. }
  132. if (flags & SPI_XFER_BEGIN)
  133. spi_cs_activate(slave);
  134. /* we need to tighten the transfer loop */
  135. if (txp && rxp) {
  136. writeb(*txp++, &regs->txdata);
  137. if (bytes > 1) {
  138. writeb(*txp++, &regs->txdata);
  139. for (i = 2; i < bytes; i++) {
  140. u8 rx, tx = *txp++;
  141. while (!(readb(&regs->status) &
  142. TINY_SPI_STATUS_TXR))
  143. ;
  144. rx = readb(&regs->txdata);
  145. writeb(tx, &regs->txdata);
  146. *rxp++ = rx;
  147. }
  148. while (!(readb(&regs->status) &
  149. TINY_SPI_STATUS_TXR))
  150. ;
  151. *rxp++ = readb(&regs->txdata);
  152. }
  153. while (!(readb(&regs->status) &
  154. TINY_SPI_STATUS_TXE))
  155. ;
  156. *rxp++ = readb(&regs->rxdata);
  157. } else if (rxp) {
  158. writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
  159. if (bytes > 1) {
  160. writeb(CONFIG_TINY_SPI_IDLE_VAL,
  161. &regs->txdata);
  162. for (i = 2; i < bytes; i++) {
  163. u8 rx;
  164. while (!(readb(&regs->status) &
  165. TINY_SPI_STATUS_TXR))
  166. ;
  167. rx = readb(&regs->txdata);
  168. writeb(CONFIG_TINY_SPI_IDLE_VAL,
  169. &regs->txdata);
  170. *rxp++ = rx;
  171. }
  172. while (!(readb(&regs->status) &
  173. TINY_SPI_STATUS_TXR))
  174. ;
  175. *rxp++ = readb(&regs->txdata);
  176. }
  177. while (!(readb(&regs->status) &
  178. TINY_SPI_STATUS_TXE))
  179. ;
  180. *rxp++ = readb(&regs->rxdata);
  181. } else if (txp) {
  182. writeb(*txp++, &regs->txdata);
  183. if (bytes > 1) {
  184. writeb(*txp++, &regs->txdata);
  185. for (i = 2; i < bytes; i++) {
  186. u8 tx = *txp++;
  187. while (!(readb(&regs->status) &
  188. TINY_SPI_STATUS_TXR))
  189. ;
  190. writeb(tx, &regs->txdata);
  191. }
  192. }
  193. while (!(readb(&regs->status) &
  194. TINY_SPI_STATUS_TXE))
  195. ;
  196. } else {
  197. writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
  198. if (bytes > 1) {
  199. writeb(CONFIG_TINY_SPI_IDLE_VAL,
  200. &regs->txdata);
  201. for (i = 2; i < bytes; i++) {
  202. while (!(readb(&regs->status) &
  203. TINY_SPI_STATUS_TXR))
  204. ;
  205. writeb(CONFIG_TINY_SPI_IDLE_VAL,
  206. &regs->txdata);
  207. }
  208. }
  209. while (!(readb(&regs->status) &
  210. TINY_SPI_STATUS_TXE))
  211. ;
  212. }
  213. done:
  214. if (flags & SPI_XFER_END)
  215. spi_cs_deactivate(slave);
  216. return 0;
  217. }