omap3_dma.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* Copyright (C) 2011
  2. * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17. * MA 02111-1307 USA
  18. */
  19. /* This is a basic implementation of the SDMA/DMA4 controller of OMAP3
  20. * Tested on Silicon Revision major:0x4 minor:0x0
  21. */
  22. #include <common.h>
  23. #include <asm/arch/cpu.h>
  24. #include <asm/arch/omap3.h>
  25. #include <asm/arch/dma.h>
  26. #include <asm/io.h>
  27. #include <asm/errno.h>
  28. static struct dma4 *dma4_cfg = (struct dma4 *)OMAP34XX_DMA4_BASE;
  29. uint32_t dma_active; /* if a transfer is started the respective
  30. bit is set for the logical channel */
  31. /* Check if we have the given channel
  32. * PARAMETERS:
  33. * chan: Channel number
  34. *
  35. * RETURN of non-zero means error */
  36. static inline int check_channel(uint32_t chan)
  37. {
  38. if (chan < CHAN_NR_MIN || chan > CHAN_NR_MAX)
  39. return -EINVAL;
  40. return 0;
  41. }
  42. static inline void reset_irq(uint32_t chan)
  43. {
  44. /* reset IRQ reason */
  45. writel(0x1DFE, &dma4_cfg->chan[chan].csr);
  46. /* reset IRQ */
  47. writel((1 << chan), &dma4_cfg->irqstatus_l[0]);
  48. dma_active &= ~(1 << chan);
  49. }
  50. /* Set Source, Destination and Size of DMA transfer for the
  51. * specified channel.
  52. * PARAMETERS:
  53. * chan: channel to use
  54. * src: source of the transfer
  55. * dst: destination of the transfer
  56. * sze: Size of the transfer
  57. *
  58. * RETURN of non-zero means error */
  59. int omap3_dma_conf_transfer(uint32_t chan, uint32_t *src, uint32_t *dst,
  60. uint32_t sze)
  61. {
  62. if (check_channel(chan))
  63. return -EINVAL;
  64. /* CDSA0 */
  65. writel((uint32_t)src, &dma4_cfg->chan[chan].cssa);
  66. writel((uint32_t)dst, &dma4_cfg->chan[chan].cdsa);
  67. writel(sze, &dma4_cfg->chan[chan].cen);
  68. return 0;
  69. }
  70. /* Start the DMA transfer */
  71. int omap3_dma_start_transfer(uint32_t chan)
  72. {
  73. uint32_t val;
  74. if (check_channel(chan))
  75. return -EINVAL;
  76. val = readl(&dma4_cfg->chan[chan].ccr);
  77. /* Test for channel already in use */
  78. if (val & CCR_ENABLE_ENABLE)
  79. return -EBUSY;
  80. writel((val | CCR_ENABLE_ENABLE), &dma4_cfg->chan[chan].ccr);
  81. dma_active |= (1 << chan);
  82. debug("started transfer...\n");
  83. return 0;
  84. }
  85. /* Busy-waiting for a DMA transfer
  86. * This has to be called before another transfer is started
  87. * PARAMETER
  88. * chan: Channel to wait for
  89. *
  90. * RETURN of non-zero means error*/
  91. int omap3_dma_wait_for_transfer(uint32_t chan)
  92. {
  93. uint32_t val;
  94. if (!(dma_active & (1 << chan))) {
  95. val = readl(&dma4_cfg->irqstatus_l[0]);
  96. if (!(val & chan)) {
  97. debug("dma: The channel you are trying to wait for "
  98. "was never activated - ERROR\n");
  99. return -1; /* channel was never active */
  100. }
  101. }
  102. /* all irqs on line 0 */
  103. while (!(readl(&dma4_cfg->irqstatus_l[0]) & (1 << chan)))
  104. asm("nop");
  105. val = readl(&dma4_cfg->chan[chan].csr);
  106. if ((val & CSR_TRANS_ERR) | (val & CSR_SUPERVISOR_ERR) |
  107. (val & CSR_MISALIGNED_ADRS_ERR)) {
  108. debug("err code: %X\n", val);
  109. debug("dma: transfer error detected\n");
  110. reset_irq(chan);
  111. return -1;
  112. }
  113. reset_irq(chan);
  114. return 0;
  115. }
  116. /* Get the revision of the DMA module
  117. * PARAMETER
  118. * minor: Address of minor revision to write
  119. * major: Address of major revision to write
  120. *
  121. * RETURN of non-zero means error
  122. */
  123. int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
  124. {
  125. uint32_t val;
  126. /* debug information */
  127. val = readl(&dma4_cfg->revision);
  128. *major = (val & 0x000000F0) >> 4;
  129. *minor = (val & 0x0000000F);
  130. debug("DMA Silicon revision (maj/min): 0x%X/0x%X\n", *major, *minor);
  131. return 0;
  132. }
  133. /* Initial config of omap dma
  134. */
  135. void omap3_dma_init(void)
  136. {
  137. dma_active = 0;
  138. /* All interrupts on channel 0 */
  139. writel(0xFFFFFFFF, &dma4_cfg->irqenable_l[0]);
  140. }
  141. /* set channel config to config
  142. *
  143. * RETURN of non-zero means error */
  144. int omap3_dma_conf_chan(uint32_t chan, struct dma4_chan *config)
  145. {
  146. if (check_channel(chan))
  147. return -EINVAL;
  148. dma4_cfg->chan[chan] = *config;
  149. return 0;
  150. }
  151. /* get channel config to config
  152. *
  153. * RETURN of non-zero means error */
  154. int omap3_dma_get_conf_chan(uint32_t chan, struct dma4_chan *config)
  155. {
  156. if (check_channel(chan))
  157. return -EINVAL;
  158. *config = dma4_cfg->chan[chan];
  159. return 0;
  160. }