spi.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net>
  3. * Stephan Linz <linz@li-pro.net>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <linux/ctype.h>
  25. #if defined(CONFIG_NIOS_SPI)
  26. #include <nios-io.h>
  27. #include <spi.h>
  28. #if !defined(CFG_NIOS_SPIBASE)
  29. #error "*** CFG_NIOS_SPIBASE not defined ***"
  30. #endif
  31. #if !defined(CFG_NIOS_SPIBITS)
  32. #error "*** CFG_NIOS_SPIBITS not defined ***"
  33. #endif
  34. #if (CFG_NIOS_SPIBITS != 8) && (CFG_NIOS_SPIBITS != 16)
  35. #error "*** CFG_NIOS_SPIBITS should be either 8 or 16 ***"
  36. #endif
  37. static nios_spi_t *spi = (nios_spi_t *)CFG_NIOS_SPIBASE;
  38. /* Warning:
  39. * You cannot enable DEBUG for early system initalization, i. e. when
  40. * this driver is used to read environment parameters like "baudrate"
  41. * from EEPROM which are used to initialize the serial port which is
  42. * needed to print the debug messages...
  43. */
  44. #undef DEBUG
  45. #ifdef DEBUG
  46. #define DPRINT(a) printf a;
  47. /* -----------------------------------------------
  48. * Helper functions to peek into tx and rx buffers
  49. * ----------------------------------------------- */
  50. static const char * const hex_digit = "0123456789ABCDEF";
  51. static char quickhex (int i)
  52. {
  53. return hex_digit[i];
  54. }
  55. static void memdump (const void *pv, int num)
  56. {
  57. int i;
  58. const unsigned char *pc = (const unsigned char *) pv;
  59. for (i = 0; i < num; i++)
  60. printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
  61. printf ("\t");
  62. for (i = 0; i < num; i++)
  63. printf ("%c", isprint (pc[i]) ? pc[i] : '.');
  64. printf ("\n");
  65. }
  66. #else /* !DEBUG */
  67. #define DPRINT(a)
  68. #define memdump(p,n)
  69. #endif /* DEBUG */
  70. struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  71. unsigned int max_hz, unsigned int mode)
  72. {
  73. struct spi_slave *slave;
  74. if (!spi_cs_is_valid(bus, cs))
  75. return NULL;
  76. slave = malloc(sizeof(struct spi_slave));
  77. if (!slave)
  78. return NULL;
  79. slave->bus = bus;
  80. slave->cs = cs;
  81. /* TODO: Add support for different modes and speeds */
  82. return slave;
  83. }
  84. void spi_free_slave(struct spi_slave *slave)
  85. {
  86. free(slave);
  87. }
  88. int spi_claim_bus(struct spi_slave *slave)
  89. {
  90. return 0;
  91. }
  92. void spi_release_bus(struct spi_slave *slave)
  93. {
  94. }
  95. /*
  96. * SPI transfer:
  97. *
  98. * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf
  99. * for more informations.
  100. */
  101. int spi_xfer(struct spi_slave *slave, int bitlen, const void *dout,
  102. void *din, unsigned long flags)
  103. {
  104. const u8 *txd = dout;
  105. u8 *rxd = din;
  106. int j;
  107. DPRINT(("spi_xfer: slave %u:%u dout %08X din %08X bitlen %d\n",
  108. slave->bus, slave->cs, *(uint *)dout, *(uint *)din, bitlen));
  109. memdump(dout, (bitlen + 7) / 8);
  110. if (flags & SPI_XFER_BEGIN)
  111. spi_cs_activate(slave);
  112. if (!(flags & SPI_XFER_END) || bitlen > CFG_NIOS_SPIBITS) {
  113. /* leave chip select active */
  114. spi->control |= NIOS_SPI_SSO;
  115. }
  116. for ( j = 0; /* count each byte in */
  117. j < ((bitlen + 7) / 8); /* dout[] and din[] */
  118. #if (CFG_NIOS_SPIBITS == 8)
  119. j++) {
  120. while ((spi->status & NIOS_SPI_TRDY) == 0)
  121. ;
  122. spi->txdata = (unsigned)(txd[j]);
  123. while ((spi->status & NIOS_SPI_RRDY) == 0)
  124. ;
  125. rxd[j] = (unsigned char)(spi->rxdata & 0xff);
  126. #elif (CFG_NIOS_SPIBITS == 16)
  127. j++, j++) {
  128. while ((spi->status & NIOS_SPI_TRDY) == 0)
  129. ;
  130. if ((j+1) < ((bitlen + 7) / 8))
  131. spi->txdata = (unsigned)((txd[j] << 8) | txd[j+1]);
  132. else
  133. spi->txdata = (unsigned)(txd[j] << 8);
  134. while ((spi->status & NIOS_SPI_RRDY) == 0)
  135. ;
  136. rxd[j] = (unsigned char)((spi->rxdata >> 8) & 0xff);
  137. if ((j+1) < ((bitlen + 7) / 8))
  138. rxd[j+1] = (unsigned char)(spi->rxdata & 0xff);
  139. #else
  140. #error "*** unsupported value of CFG_NIOS_SPIBITS ***"
  141. #endif
  142. }
  143. if (bitlen > CFG_NIOS_SPIBITS && (flags & SPI_XFER_END)) {
  144. spi->control &= ~NIOS_SPI_SSO;
  145. }
  146. if (flags & SPI_XFER_END)
  147. spi_cs_deactivate(slave);
  148. memdump(din, (bitlen + 7) / 8);
  149. return 0;
  150. }
  151. #endif /* CONFIG_NIOS_SPI */