dma.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * arch/arm/mach-sa1100/dma.c
  3. *
  4. * Support functions for the SA11x0 internal DMA channels.
  5. *
  6. * Copyright (C) 2000, 2001 by Nicolas Pitre
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/init.h>
  15. #include <linux/spinlock.h>
  16. #include <linux/errno.h>
  17. #include <asm/system.h>
  18. #include <asm/irq.h>
  19. #include <mach/hardware.h>
  20. #include <mach/dma.h>
  21. #undef DEBUG
  22. #ifdef DEBUG
  23. #define DPRINTK( s, arg... ) printk( "dma<%p>: " s, regs , ##arg )
  24. #else
  25. #define DPRINTK( x... )
  26. #endif
  27. typedef struct {
  28. const char *device_id; /* device name */
  29. u_long device; /* this channel device, 0 if unused*/
  30. dma_callback_t callback; /* to call when DMA completes */
  31. void *data; /* ... with private data ptr */
  32. } sa1100_dma_t;
  33. static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
  34. static DEFINE_SPINLOCK(dma_list_lock);
  35. static irqreturn_t dma_irq_handler(int irq, void *dev_id)
  36. {
  37. dma_regs_t *dma_regs = dev_id;
  38. sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7);
  39. int status = dma_regs->RdDCSR;
  40. if (status & (DCSR_ERROR)) {
  41. printk(KERN_CRIT "DMA on \"%s\" caused an error\n", dma->device_id);
  42. dma_regs->ClrDCSR = DCSR_ERROR;
  43. }
  44. dma_regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
  45. if (dma->callback) {
  46. if (status & DCSR_DONEA)
  47. dma->callback(dma->data);
  48. if (status & DCSR_DONEB)
  49. dma->callback(dma->data);
  50. }
  51. return IRQ_HANDLED;
  52. }
  53. /**
  54. * sa1100_request_dma - allocate one of the SA11x0's DMA channels
  55. * @device: The SA11x0 peripheral targeted by this request
  56. * @device_id: An ascii name for the claiming device
  57. * @callback: Function to be called when the DMA completes
  58. * @data: A cookie passed back to the callback function
  59. * @dma_regs: Pointer to the location of the allocated channel's identifier
  60. *
  61. * This function will search for a free DMA channel and returns the
  62. * address of the hardware registers for that channel as the channel
  63. * identifier. This identifier is written to the location pointed by
  64. * @dma_regs. The list of possible values for @device are listed into
  65. * arch/arm/mach-sa1100/include/mach/dma.h as a dma_device_t enum.
  66. *
  67. * Note that reading from a port and writing to the same port are
  68. * actually considered as two different streams requiring separate
  69. * DMA registrations.
  70. *
  71. * The @callback function is called from interrupt context when one
  72. * of the two possible DMA buffers in flight has terminated. That
  73. * function has to be small and efficient while posponing more complex
  74. * processing to a lower priority execution context.
  75. *
  76. * If no channels are available, or if the desired @device is already in
  77. * use by another DMA channel, then an error code is returned. This
  78. * function must be called before any other DMA calls.
  79. **/
  80. int sa1100_request_dma (dma_device_t device, const char *device_id,
  81. dma_callback_t callback, void *data,
  82. dma_regs_t **dma_regs)
  83. {
  84. sa1100_dma_t *dma = NULL;
  85. dma_regs_t *regs;
  86. int i, err;
  87. *dma_regs = NULL;
  88. err = 0;
  89. spin_lock(&dma_list_lock);
  90. for (i = 0; i < SA1100_DMA_CHANNELS; i++) {
  91. if (dma_chan[i].device == device) {
  92. err = -EBUSY;
  93. break;
  94. } else if (!dma_chan[i].device && !dma) {
  95. dma = &dma_chan[i];
  96. }
  97. }
  98. if (!err) {
  99. if (dma)
  100. dma->device = device;
  101. else
  102. err = -ENOSR;
  103. }
  104. spin_unlock(&dma_list_lock);
  105. if (err)
  106. return err;
  107. i = dma - dma_chan;
  108. regs = (dma_regs_t *)&DDAR(i);
  109. err = request_irq(IRQ_DMA0 + i, dma_irq_handler, IRQF_DISABLED,
  110. device_id, regs);
  111. if (err) {
  112. printk(KERN_ERR
  113. "%s: unable to request IRQ %d for %s\n",
  114. __func__, IRQ_DMA0 + i, device_id);
  115. dma->device = 0;
  116. return err;
  117. }
  118. *dma_regs = regs;
  119. dma->device_id = device_id;
  120. dma->callback = callback;
  121. dma->data = data;
  122. regs->ClrDCSR =
  123. (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
  124. DCSR_IE | DCSR_ERROR | DCSR_RUN);
  125. regs->DDAR = device;
  126. return 0;
  127. }
  128. /**
  129. * sa1100_free_dma - free a SA11x0 DMA channel
  130. * @regs: identifier for the channel to free
  131. *
  132. * This clears all activities on a given DMA channel and releases it
  133. * for future requests. The @regs identifier is provided by a
  134. * successful call to sa1100_request_dma().
  135. **/
  136. void sa1100_free_dma(dma_regs_t *regs)
  137. {
  138. int i;
  139. for (i = 0; i < SA1100_DMA_CHANNELS; i++)
  140. if (regs == (dma_regs_t *)&DDAR(i))
  141. break;
  142. if (i >= SA1100_DMA_CHANNELS) {
  143. printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
  144. return;
  145. }
  146. if (!dma_chan[i].device) {
  147. printk(KERN_ERR "%s: Trying to free free DMA\n", __func__);
  148. return;
  149. }
  150. regs->ClrDCSR =
  151. (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
  152. DCSR_IE | DCSR_ERROR | DCSR_RUN);
  153. free_irq(IRQ_DMA0 + i, regs);
  154. dma_chan[i].device = 0;
  155. }
  156. /**
  157. * sa1100_start_dma - submit a data buffer for DMA
  158. * @regs: identifier for the channel to use
  159. * @dma_ptr: buffer physical (or bus) start address
  160. * @size: buffer size
  161. *
  162. * This function hands the given data buffer to the hardware for DMA
  163. * access. If another buffer is already in flight then this buffer
  164. * will be queued so the DMA engine will switch to it automatically
  165. * when the previous one is done. The DMA engine is actually toggling
  166. * between two buffers so at most 2 successful calls can be made before
  167. * one of them terminates and the callback function is called.
  168. *
  169. * The @regs identifier is provided by a successful call to
  170. * sa1100_request_dma().
  171. *
  172. * The @size must not be larger than %MAX_DMA_SIZE. If a given buffer
  173. * is larger than that then it's the caller's responsibility to split
  174. * it into smaller chunks and submit them separately. If this is the
  175. * case then a @size of %CUT_DMA_SIZE is recommended to avoid ending
  176. * up with too small chunks. The callback function can be used to chain
  177. * submissions of buffer chunks.
  178. *
  179. * Error return values:
  180. * %-EOVERFLOW: Given buffer size is too big.
  181. * %-EBUSY: Both DMA buffers are already in use.
  182. * %-EAGAIN: Both buffers were busy but one of them just completed
  183. * but the interrupt handler has to execute first.
  184. *
  185. * This function returs 0 on success.
  186. **/
  187. int sa1100_start_dma(dma_regs_t *regs, dma_addr_t dma_ptr, u_int size)
  188. {
  189. unsigned long flags;
  190. u_long status;
  191. int ret;
  192. if (dma_ptr & 3)
  193. printk(KERN_WARNING "DMA: unaligned start address (0x%08lx)\n",
  194. (unsigned long)dma_ptr);
  195. if (size > MAX_DMA_SIZE)
  196. return -EOVERFLOW;
  197. local_irq_save(flags);
  198. status = regs->RdDCSR;
  199. /* If both DMA buffers are started, there's nothing else we can do. */
  200. if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
  201. DPRINTK("start: st %#x busy\n", status);
  202. ret = -EBUSY;
  203. goto out;
  204. }
  205. if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
  206. (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
  207. if (status & DCSR_DONEA) {
  208. /* give a chance for the interrupt to be processed */
  209. ret = -EAGAIN;
  210. goto out;
  211. }
  212. regs->DBSA = dma_ptr;
  213. regs->DBTA = size;
  214. regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
  215. DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
  216. } else {
  217. if (status & DCSR_DONEB) {
  218. /* give a chance for the interrupt to be processed */
  219. ret = -EAGAIN;
  220. goto out;
  221. }
  222. regs->DBSB = dma_ptr;
  223. regs->DBTB = size;
  224. regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
  225. DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
  226. }
  227. ret = 0;
  228. out:
  229. local_irq_restore(flags);
  230. return ret;
  231. }
  232. /**
  233. * sa1100_get_dma_pos - return current DMA position
  234. * @regs: identifier for the channel to use
  235. *
  236. * This function returns the current physical (or bus) address for the
  237. * given DMA channel. If the channel is running i.e. not in a stopped
  238. * state then the caller must disable interrupts prior calling this
  239. * function and process the returned value before re-enabling them to
  240. * prevent races with the completion interrupt handler and the callback
  241. * function. The validation of the returned value is the caller's
  242. * responsibility as well -- the hardware seems to return out of range
  243. * values when the DMA engine completes a buffer.
  244. *
  245. * The @regs identifier is provided by a successful call to
  246. * sa1100_request_dma().
  247. **/
  248. dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs)
  249. {
  250. int status;
  251. /*
  252. * We must determine whether buffer A or B is active.
  253. * Two possibilities: either we are in the middle of
  254. * a buffer, or the DMA controller just switched to the
  255. * next toggle but the interrupt hasn't been serviced yet.
  256. * The former case is straight forward. In the later case,
  257. * we'll do like if DMA is just at the end of the previous
  258. * toggle since all registers haven't been reset yet.
  259. * This goes around the edge case and since we're always
  260. * a little behind anyways it shouldn't make a big difference.
  261. * If DMA has been stopped prior calling this then the
  262. * position is exact.
  263. */
  264. status = regs->RdDCSR;
  265. if ((!(status & DCSR_BIU) && (status & DCSR_STRTA)) ||
  266. ( (status & DCSR_BIU) && !(status & DCSR_STRTB)))
  267. return regs->DBSA;
  268. else
  269. return regs->DBSB;
  270. }
  271. /**
  272. * sa1100_reset_dma - reset a DMA channel
  273. * @regs: identifier for the channel to use
  274. *
  275. * This function resets and reconfigure the given DMA channel. This is
  276. * particularly useful after a sleep/wakeup event.
  277. *
  278. * The @regs identifier is provided by a successful call to
  279. * sa1100_request_dma().
  280. **/
  281. void sa1100_reset_dma(dma_regs_t *regs)
  282. {
  283. int i;
  284. for (i = 0; i < SA1100_DMA_CHANNELS; i++)
  285. if (regs == (dma_regs_t *)&DDAR(i))
  286. break;
  287. if (i >= SA1100_DMA_CHANNELS) {
  288. printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
  289. return;
  290. }
  291. regs->ClrDCSR =
  292. (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
  293. DCSR_IE | DCSR_ERROR | DCSR_RUN);
  294. regs->DDAR = dma_chan[i].device;
  295. }
  296. EXPORT_SYMBOL(sa1100_request_dma);
  297. EXPORT_SYMBOL(sa1100_free_dma);
  298. EXPORT_SYMBOL(sa1100_start_dma);
  299. EXPORT_SYMBOL(sa1100_get_dma_pos);
  300. EXPORT_SYMBOL(sa1100_reset_dma);