ssp.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * linux/arch/arm/mach-sa1100/ssp.c
  3. *
  4. * Copyright (C) 2003 Russell King.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Generic SSP driver. This provides the generic core for simple
  11. * IO-based SSP applications.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/errno.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/ioport.h>
  19. #include <linux/init.h>
  20. #include <linux/io.h>
  21. #include <asm/irq.h>
  22. #include <mach/hardware.h>
  23. #include <asm/hardware/ssp.h>
  24. #define TIMEOUT 100000
  25. static irqreturn_t ssp_interrupt(int irq, void *dev_id)
  26. {
  27. unsigned int status = Ser4SSSR;
  28. if (status & SSSR_ROR)
  29. printk(KERN_WARNING "SSP: receiver overrun\n");
  30. Ser4SSSR = SSSR_ROR;
  31. return status ? IRQ_HANDLED : IRQ_NONE;
  32. }
  33. /**
  34. * ssp_write_word - write a word to the SSP port
  35. * @data: 16-bit, MSB justified data to write.
  36. *
  37. * Wait for a free entry in the SSP transmit FIFO, and write a data
  38. * word to the SSP port. Wait for the SSP port to start sending
  39. * the data.
  40. *
  41. * The caller is expected to perform the necessary locking.
  42. *
  43. * Returns:
  44. * %-ETIMEDOUT timeout occurred
  45. * 0 success
  46. */
  47. int ssp_write_word(u16 data)
  48. {
  49. int timeout = TIMEOUT;
  50. while (!(Ser4SSSR & SSSR_TNF)) {
  51. if (!--timeout)
  52. return -ETIMEDOUT;
  53. cpu_relax();
  54. }
  55. Ser4SSDR = data;
  56. timeout = TIMEOUT;
  57. while (!(Ser4SSSR & SSSR_BSY)) {
  58. if (!--timeout)
  59. return -ETIMEDOUT;
  60. cpu_relax();
  61. }
  62. return 0;
  63. }
  64. /**
  65. * ssp_read_word - read a word from the SSP port
  66. *
  67. * Wait for a data word in the SSP receive FIFO, and return the
  68. * received data. Data is LSB justified.
  69. *
  70. * Note: Currently, if data is not expected to be received, this
  71. * function will wait for ever.
  72. *
  73. * The caller is expected to perform the necessary locking.
  74. *
  75. * Returns:
  76. * %-ETIMEDOUT timeout occurred
  77. * 16-bit data success
  78. */
  79. int ssp_read_word(u16 *data)
  80. {
  81. int timeout = TIMEOUT;
  82. while (!(Ser4SSSR & SSSR_RNE)) {
  83. if (!--timeout)
  84. return -ETIMEDOUT;
  85. cpu_relax();
  86. }
  87. *data = (u16)Ser4SSDR;
  88. return 0;
  89. }
  90. /**
  91. * ssp_flush - flush the transmit and receive FIFOs
  92. *
  93. * Wait for the SSP to idle, and ensure that the receive FIFO
  94. * is empty.
  95. *
  96. * The caller is expected to perform the necessary locking.
  97. *
  98. * Returns:
  99. * %-ETIMEDOUT timeout occurred
  100. * 0 success
  101. */
  102. int ssp_flush(void)
  103. {
  104. int timeout = TIMEOUT * 2;
  105. do {
  106. while (Ser4SSSR & SSSR_RNE) {
  107. if (!--timeout)
  108. return -ETIMEDOUT;
  109. (void) Ser4SSDR;
  110. }
  111. if (!--timeout)
  112. return -ETIMEDOUT;
  113. } while (Ser4SSSR & SSSR_BSY);
  114. return 0;
  115. }
  116. /**
  117. * ssp_enable - enable the SSP port
  118. *
  119. * Turn on the SSP port.
  120. */
  121. void ssp_enable(void)
  122. {
  123. Ser4SSCR0 |= SSCR0_SSE;
  124. }
  125. /**
  126. * ssp_disable - shut down the SSP port
  127. *
  128. * Turn off the SSP port, optionally powering it down.
  129. */
  130. void ssp_disable(void)
  131. {
  132. Ser4SSCR0 &= ~SSCR0_SSE;
  133. }
  134. /**
  135. * ssp_save_state - save the SSP configuration
  136. * @ssp: pointer to structure to save SSP configuration
  137. *
  138. * Save the configured SSP state for suspend.
  139. */
  140. void ssp_save_state(struct ssp_state *ssp)
  141. {
  142. ssp->cr0 = Ser4SSCR0;
  143. ssp->cr1 = Ser4SSCR1;
  144. Ser4SSCR0 &= ~SSCR0_SSE;
  145. }
  146. /**
  147. * ssp_restore_state - restore a previously saved SSP configuration
  148. * @ssp: pointer to configuration saved by ssp_save_state
  149. *
  150. * Restore the SSP configuration saved previously by ssp_save_state.
  151. */
  152. void ssp_restore_state(struct ssp_state *ssp)
  153. {
  154. Ser4SSSR = SSSR_ROR;
  155. Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
  156. Ser4SSCR1 = ssp->cr1;
  157. Ser4SSCR0 = ssp->cr0;
  158. }
  159. /**
  160. * ssp_init - setup the SSP port
  161. *
  162. * initialise and claim resources for the SSP port.
  163. *
  164. * Returns:
  165. * %-ENODEV if the SSP port is unavailable
  166. * %-EBUSY if the resources are already in use
  167. * %0 on success
  168. */
  169. int ssp_init(void)
  170. {
  171. int ret;
  172. if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
  173. return -ENODEV;
  174. if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
  175. return -EBUSY;
  176. }
  177. Ser4SSSR = SSSR_ROR;
  178. ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
  179. if (ret)
  180. goto out_region;
  181. return 0;
  182. out_region:
  183. release_mem_region(__PREG(Ser4SSCR0), 0x18);
  184. return ret;
  185. }
  186. /**
  187. * ssp_exit - undo the effects of ssp_init
  188. *
  189. * release and free resources for the SSP port.
  190. */
  191. void ssp_exit(void)
  192. {
  193. Ser4SSCR0 &= ~SSCR0_SSE;
  194. free_irq(IRQ_Ser4SSP, NULL);
  195. release_mem_region(__PREG(Ser4SSCR0), 0x18);
  196. }
  197. MODULE_AUTHOR("Russell King");
  198. MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
  199. MODULE_LICENSE("GPL");
  200. EXPORT_SYMBOL(ssp_write_word);
  201. EXPORT_SYMBOL(ssp_read_word);
  202. EXPORT_SYMBOL(ssp_flush);
  203. EXPORT_SYMBOL(ssp_enable);
  204. EXPORT_SYMBOL(ssp_disable);
  205. EXPORT_SYMBOL(ssp_save_state);
  206. EXPORT_SYMBOL(ssp_restore_state);
  207. EXPORT_SYMBOL(ssp_init);
  208. EXPORT_SYMBOL(ssp_exit);