spi.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 (void *pv, int num)
  56. {
  57. int i;
  58. unsigned char *pc = (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. /*
  71. * SPI transfer:
  72. *
  73. * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf
  74. * for more informations.
  75. */
  76. int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
  77. {
  78. int j;
  79. DPRINT(("spi_xfer: chipsel %08X dout %08X din %08X bitlen %d\n",
  80. (int)chipsel, *(uint *)dout, *(uint *)din, bitlen));
  81. memdump((void*)dout, (bitlen + 7) / 8);
  82. if(chipsel != NULL) {
  83. chipsel(1); /* select the target chip */
  84. }
  85. if (bitlen > CFG_NIOS_SPIBITS) { /* leave chip select active */
  86. spi->control |= NIOS_SPI_SSO;
  87. }
  88. for ( j = 0; /* count each byte in */
  89. j < ((bitlen + 7) / 8); /* dout[] and din[] */
  90. #if (CFG_NIOS_SPIBITS == 8)
  91. j++) {
  92. while ((spi->status & NIOS_SPI_TRDY) == 0)
  93. ;
  94. spi->txdata = (unsigned)(dout[j]);
  95. while ((spi->status & NIOS_SPI_RRDY) == 0)
  96. ;
  97. din[j] = (unsigned char)(spi->rxdata & 0xff);
  98. #elif (CFG_NIOS_SPIBITS == 16)
  99. j++, j++) {
  100. while ((spi->status & NIOS_SPI_TRDY) == 0)
  101. ;
  102. if ((j+1) < ((bitlen + 7) / 8))
  103. spi->txdata = (unsigned)((dout[j] << 8) | dout[j+1]);
  104. else
  105. spi->txdata = (unsigned)(dout[j] << 8);
  106. while ((spi->status & NIOS_SPI_RRDY) == 0)
  107. ;
  108. din[j] = (unsigned char)((spi->rxdata >> 8) & 0xff);
  109. if ((j+1) < ((bitlen + 7) / 8))
  110. din[j+1] = (unsigned char)(spi->rxdata & 0xff);
  111. #else
  112. #error "*** unsupported value of CFG_NIOS_SPIBITS ***"
  113. #endif
  114. }
  115. if (bitlen > CFG_NIOS_SPIBITS) {
  116. spi->control &= ~NIOS_SPI_SSO;
  117. }
  118. if(chipsel != NULL) {
  119. chipsel(0); /* deselect the target chip */
  120. }
  121. memdump((void*)din, (bitlen + 7) / 8);
  122. return 0;
  123. }
  124. #endif /* CONFIG_NIOS_SPI */