atmel_spi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2007 Atmel Corporation
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <common.h>
  23. #include <spi.h>
  24. #include <malloc.h>
  25. #include <asm/io.h>
  26. #include <asm/arch/clk.h>
  27. #include <asm/arch/hardware.h>
  28. #include "atmel_spi.h"
  29. static int spi_has_wdrbt(struct atmel_spi_slave *slave)
  30. {
  31. unsigned int ver;
  32. ver = spi_readl(slave, VERSION);
  33. return (ATMEL_SPI_VERSION_REV(ver) >= 0x210);
  34. }
  35. void spi_init()
  36. {
  37. }
  38. struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  39. unsigned int max_hz, unsigned int mode)
  40. {
  41. struct atmel_spi_slave *as;
  42. unsigned int scbr;
  43. u32 csrx;
  44. void *regs;
  45. if (!spi_cs_is_valid(bus, cs))
  46. return NULL;
  47. switch (bus) {
  48. case 0:
  49. regs = (void *)ATMEL_BASE_SPI0;
  50. break;
  51. #ifdef ATMEL_BASE_SPI1
  52. case 1:
  53. regs = (void *)ATMEL_BASE_SPI1;
  54. break;
  55. #endif
  56. #ifdef ATMEL_BASE_SPI2
  57. case 2:
  58. regs = (void *)ATMEL_BASE_SPI2;
  59. break;
  60. #endif
  61. #ifdef ATMEL_BASE_SPI3
  62. case 3:
  63. regs = (void *)ATMEL_BASE_SPI3;
  64. break;
  65. #endif
  66. default:
  67. return NULL;
  68. }
  69. scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz;
  70. if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
  71. /* Too low max SCK rate */
  72. return NULL;
  73. if (scbr < 1)
  74. scbr = 1;
  75. csrx = ATMEL_SPI_CSRx_SCBR(scbr);
  76. csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);
  77. if (!(mode & SPI_CPHA))
  78. csrx |= ATMEL_SPI_CSRx_NCPHA;
  79. if (mode & SPI_CPOL)
  80. csrx |= ATMEL_SPI_CSRx_CPOL;
  81. as = spi_alloc_slave(struct atmel_spi_slave, bus, cs);
  82. if (!as)
  83. return NULL;
  84. as->regs = regs;
  85. as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS
  86. | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf);
  87. if (spi_has_wdrbt(as))
  88. as->mr |= ATMEL_SPI_MR_WDRBT;
  89. spi_writel(as, CSR(cs), csrx);
  90. return &as->slave;
  91. }
  92. void spi_free_slave(struct spi_slave *slave)
  93. {
  94. struct atmel_spi_slave *as = to_atmel_spi(slave);
  95. free(as);
  96. }
  97. int spi_claim_bus(struct spi_slave *slave)
  98. {
  99. struct atmel_spi_slave *as = to_atmel_spi(slave);
  100. /* Enable the SPI hardware */
  101. spi_writel(as, CR, ATMEL_SPI_CR_SPIEN);
  102. /*
  103. * Select the slave. This should set SCK to the correct
  104. * initial state, etc.
  105. */
  106. spi_writel(as, MR, as->mr);
  107. return 0;
  108. }
  109. void spi_release_bus(struct spi_slave *slave)
  110. {
  111. struct atmel_spi_slave *as = to_atmel_spi(slave);
  112. /* Disable the SPI hardware */
  113. spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS);
  114. }
  115. int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  116. const void *dout, void *din, unsigned long flags)
  117. {
  118. struct atmel_spi_slave *as = to_atmel_spi(slave);
  119. unsigned int len_tx;
  120. unsigned int len_rx;
  121. unsigned int len;
  122. u32 status;
  123. const u8 *txp = dout;
  124. u8 *rxp = din;
  125. u8 value;
  126. if (bitlen == 0)
  127. /* Finish any previously submitted transfers */
  128. goto out;
  129. /*
  130. * TODO: The controller can do non-multiple-of-8 bit
  131. * transfers, but this driver currently doesn't support it.
  132. *
  133. * It's also not clear how such transfers are supposed to be
  134. * represented as a stream of bytes...this is a limitation of
  135. * the current SPI interface.
  136. */
  137. if (bitlen % 8) {
  138. /* Errors always terminate an ongoing transfer */
  139. flags |= SPI_XFER_END;
  140. goto out;
  141. }
  142. len = bitlen / 8;
  143. /*
  144. * The controller can do automatic CS control, but it is
  145. * somewhat quirky, and it doesn't really buy us much anyway
  146. * in the context of U-Boot.
  147. */
  148. if (flags & SPI_XFER_BEGIN) {
  149. spi_cs_activate(slave);
  150. /*
  151. * sometimes the RDR is not empty when we get here,
  152. * in theory that should not happen, but it DOES happen.
  153. * Read it here to be on the safe side.
  154. * That also clears the OVRES flag. Required if the
  155. * following loop exits due to OVRES!
  156. */
  157. spi_readl(as, RDR);
  158. }
  159. for (len_tx = 0, len_rx = 0; len_rx < len; ) {
  160. status = spi_readl(as, SR);
  161. if (status & ATMEL_SPI_SR_OVRES)
  162. return -1;
  163. if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) {
  164. if (txp)
  165. value = *txp++;
  166. else
  167. value = 0;
  168. spi_writel(as, TDR, value);
  169. len_tx++;
  170. }
  171. if (status & ATMEL_SPI_SR_RDRF) {
  172. value = spi_readl(as, RDR);
  173. if (rxp)
  174. *rxp++ = value;
  175. len_rx++;
  176. }
  177. }
  178. out:
  179. if (flags & SPI_XFER_END) {
  180. /*
  181. * Wait until the transfer is completely done before
  182. * we deactivate CS.
  183. */
  184. do {
  185. status = spi_readl(as, SR);
  186. } while (!(status & ATMEL_SPI_SR_TXEMPTY));
  187. spi_cs_deactivate(slave);
  188. }
  189. return 0;
  190. }