spi_txx9.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
  3. * Copyright (C) 2000-2001 Toshiba Corporation
  4. *
  5. * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
  6. * terms of the GNU General Public License version 2. This program is
  7. * licensed "as is" without any warranty of any kind, whether express
  8. * or implied.
  9. *
  10. * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
  11. */
  12. #include <linux/init.h>
  13. #include <linux/delay.h>
  14. #include <linux/errno.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/module.h>
  17. #include <linux/sched.h>
  18. #include <linux/spinlock.h>
  19. #include <linux/wait.h>
  20. #include <asm/tx4938/spi.h>
  21. #include <asm/tx4938/tx4938.h>
  22. static int (*txx9_spi_cs_func)(int chipid, int on);
  23. static DEFINE_SPINLOCK(txx9_spi_lock);
  24. extern unsigned int txx9_gbus_clock;
  25. #define SPI_FIFO_SIZE 4
  26. void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
  27. {
  28. txx9_spi_cs_func = cs_func;
  29. /* enter config mode */
  30. tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
  31. }
  32. static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
  33. static void txx9_spi_interrupt(int irq, void *dev_id)
  34. {
  35. /* disable rx intr */
  36. tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
  37. wake_up(&txx9_spi_wait);
  38. }
  39. static struct irqaction txx9_spi_action = {
  40. txx9_spi_interrupt, 0, 0, "spi", NULL, NULL,
  41. };
  42. void __init txx9_spi_irqinit(int irc_irq)
  43. {
  44. setup_irq(irc_irq, &txx9_spi_action);
  45. }
  46. int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
  47. unsigned char **inbufs, unsigned int *incounts,
  48. unsigned char **outbufs, unsigned int *outcounts,
  49. int cansleep)
  50. {
  51. unsigned int incount, outcount;
  52. unsigned char *inp, *outp;
  53. int ret;
  54. unsigned long flags;
  55. spin_lock_irqsave(&txx9_spi_lock, flags);
  56. if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
  57. spin_unlock_irqrestore(&txx9_spi_lock, flags);
  58. return -EBUSY;
  59. }
  60. /* enter config mode */
  61. tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
  62. tx4938_spiptr->cr0 =
  63. (desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
  64. (desc->polarity ? TXx9_SPCR0_SPOL : 0) |
  65. (desc->phase ? TXx9_SPCR0_SPHA : 0) |
  66. 0x08;
  67. tx4938_spiptr->cr1 =
  68. (((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
  69. 0x08 /* 8 bit only */;
  70. /* enter active mode */
  71. tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
  72. spin_unlock_irqrestore(&txx9_spi_lock, flags);
  73. /* CS ON */
  74. if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
  75. spin_unlock_irqrestore(&txx9_spi_lock, flags);
  76. return ret;
  77. }
  78. udelay(desc->tcss);
  79. /* do scatter IO */
  80. inp = inbufs ? *inbufs : NULL;
  81. outp = outbufs ? *outbufs : NULL;
  82. incount = 0;
  83. outcount = 0;
  84. while (1) {
  85. unsigned char data;
  86. unsigned int count;
  87. int i;
  88. if (!incount) {
  89. incount = incounts ? *incounts++ : 0;
  90. inp = (incount && inbufs) ? *inbufs++ : NULL;
  91. }
  92. if (!outcount) {
  93. outcount = outcounts ? *outcounts++ : 0;
  94. outp = (outcount && outbufs) ? *outbufs++ : NULL;
  95. }
  96. if (!inp && !outp)
  97. break;
  98. count = SPI_FIFO_SIZE;
  99. if (incount)
  100. count = min(count, incount);
  101. if (outcount)
  102. count = min(count, outcount);
  103. /* now tx must be idle... */
  104. while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
  105. ;
  106. tx4938_spiptr->cr0 =
  107. (tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
  108. ((count - 1) << 12);
  109. if (cansleep) {
  110. /* enable rx intr */
  111. tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
  112. }
  113. /* send */
  114. for (i = 0; i < count; i++)
  115. tx4938_spiptr->dr = inp ? *inp++ : 0;
  116. /* wait all rx data */
  117. if (cansleep) {
  118. wait_event(txx9_spi_wait,
  119. tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
  120. } else {
  121. while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
  122. ;
  123. }
  124. /* receive */
  125. for (i = 0; i < count; i++) {
  126. data = tx4938_spiptr->dr;
  127. if (outp)
  128. *outp++ = data;
  129. }
  130. if (incount)
  131. incount -= count;
  132. if (outcount)
  133. outcount -= count;
  134. }
  135. /* CS OFF */
  136. udelay(desc->tcsh);
  137. txx9_spi_cs_func(chipid, 0);
  138. udelay(desc->tcsr);
  139. spin_lock_irqsave(&txx9_spi_lock, flags);
  140. /* enter config mode */
  141. tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
  142. spin_unlock_irqrestore(&txx9_spi_lock, flags);
  143. return 0;
  144. }