atmel_spi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. void spi_init()
  30. {
  31. }
  32. struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  33. unsigned int max_hz, unsigned int mode)
  34. {
  35. struct atmel_spi_slave *as;
  36. unsigned int scbr;
  37. u32 csrx;
  38. void *regs;
  39. if (!spi_cs_is_valid(bus, cs))
  40. return NULL;
  41. switch (bus) {
  42. case 0:
  43. regs = (void *)ATMEL_BASE_SPI0;
  44. break;
  45. #ifdef ATMEL_BASE_SPI1
  46. case 1:
  47. regs = (void *)ATMEL_BASE_SPI1;
  48. break;
  49. #endif
  50. #ifdef ATMEL_BASE_SPI2
  51. case 2:
  52. regs = (void *)ATMEL_BASE_SPI2;
  53. break;
  54. #endif
  55. #ifdef ATMEL_BASE_SPI3
  56. case 3:
  57. regs = (void *)ATMEL_BASE_SPI3;
  58. break;
  59. #endif
  60. default:
  61. return NULL;
  62. }
  63. scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz;
  64. if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
  65. /* Too low max SCK rate */
  66. return NULL;
  67. if (scbr < 1)
  68. scbr = 1;
  69. csrx = ATMEL_SPI_CSRx_SCBR(scbr);
  70. csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);
  71. if (!(mode & SPI_CPHA))
  72. csrx |= ATMEL_SPI_CSRx_NCPHA;
  73. if (mode & SPI_CPOL)
  74. csrx |= ATMEL_SPI_CSRx_CPOL;
  75. as = malloc(sizeof(struct atmel_spi_slave));
  76. if (!as)
  77. return NULL;
  78. as->slave.bus = bus;
  79. as->slave.cs = cs;
  80. as->regs = regs;
  81. as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS
  82. #if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9M10G45)
  83. | ATMEL_SPI_MR_WDRBT
  84. #endif
  85. | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf);
  86. spi_writel(as, CSR(cs), csrx);
  87. return &as->slave;
  88. }
  89. void spi_free_slave(struct spi_slave *slave)
  90. {
  91. struct atmel_spi_slave *as = to_atmel_spi(slave);
  92. free(as);
  93. }
  94. int spi_claim_bus(struct spi_slave *slave)
  95. {
  96. struct atmel_spi_slave *as = to_atmel_spi(slave);
  97. /* Enable the SPI hardware */
  98. spi_writel(as, CR, ATMEL_SPI_CR_SPIEN);
  99. /*
  100. * Select the slave. This should set SCK to the correct
  101. * initial state, etc.
  102. */
  103. spi_writel(as, MR, as->mr);
  104. return 0;
  105. }
  106. void spi_release_bus(struct spi_slave *slave)
  107. {
  108. struct atmel_spi_slave *as = to_atmel_spi(slave);
  109. /* Disable the SPI hardware */
  110. spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS);
  111. }
  112. int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  113. const void *dout, void *din, unsigned long flags)
  114. {
  115. struct atmel_spi_slave *as = to_atmel_spi(slave);
  116. unsigned int len_tx;
  117. unsigned int len_rx;
  118. unsigned int len;
  119. u32 status;
  120. const u8 *txp = dout;
  121. u8 *rxp = din;
  122. u8 value;
  123. if (bitlen == 0)
  124. /* Finish any previously submitted transfers */
  125. goto out;
  126. /*
  127. * TODO: The controller can do non-multiple-of-8 bit
  128. * transfers, but this driver currently doesn't support it.
  129. *
  130. * It's also not clear how such transfers are supposed to be
  131. * represented as a stream of bytes...this is a limitation of
  132. * the current SPI interface.
  133. */
  134. if (bitlen % 8) {
  135. /* Errors always terminate an ongoing transfer */
  136. flags |= SPI_XFER_END;
  137. goto out;
  138. }
  139. len = bitlen / 8;
  140. /*
  141. * The controller can do automatic CS control, but it is
  142. * somewhat quirky, and it doesn't really buy us much anyway
  143. * in the context of U-Boot.
  144. */
  145. if (flags & SPI_XFER_BEGIN) {
  146. spi_cs_activate(slave);
  147. /*
  148. * sometimes the RDR is not empty when we get here,
  149. * in theory that should not happen, but it DOES happen.
  150. * Read it here to be on the safe side.
  151. * That also clears the OVRES flag. Required if the
  152. * following loop exits due to OVRES!
  153. */
  154. spi_readl(as, RDR);
  155. }
  156. for (len_tx = 0, len_rx = 0; len_rx < len; ) {
  157. status = spi_readl(as, SR);
  158. if (status & ATMEL_SPI_SR_OVRES)
  159. return -1;
  160. if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) {
  161. if (txp)
  162. value = *txp++;
  163. else
  164. value = 0;
  165. spi_writel(as, TDR, value);
  166. len_tx++;
  167. }
  168. if (status & ATMEL_SPI_SR_RDRF) {
  169. value = spi_readl(as, RDR);
  170. if (rxp)
  171. *rxp++ = value;
  172. len_rx++;
  173. }
  174. }
  175. out:
  176. if (flags & SPI_XFER_END) {
  177. /*
  178. * Wait until the transfer is completely done before
  179. * we deactivate CS.
  180. */
  181. do {
  182. status = spi_readl(as, SR);
  183. } while (!(status & ATMEL_SPI_SR_TXEMPTY));
  184. spi_cs_deactivate(slave);
  185. }
  186. return 0;
  187. }