0399-dmaengine-bcm2835-use-platform_get_irq_byname.patch 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. From 2913407433c67a96d02bc4b4c1e5111fdb6d356d Mon Sep 17 00:00:00 2001
  2. From: Martin Sperl <kernel@martin.sperl.org>
  3. Date: Mon, 11 Apr 2016 13:29:08 +0000
  4. Subject: [PATCH] dmaengine: bcm2835: use platform_get_irq_byname
  5. Use platform_get_irq_byname to allow for correct mapping of
  6. interrupts to dma channels.
  7. The currently implemented device tree is unfortunately
  8. implemented with the wrong assumption, that each dma-channel
  9. has its own dma channel, but dma-irq 11 is handling
  10. dma-channel 11-14 and dma-irq 12 is actually a "catch all"
  11. interrupt.
  12. So here we use the byname variant and require that interrupts
  13. are explicitly named via the interrupts-name property in the
  14. device tree.
  15. The use of shared interrupts is also implemented.
  16. As a side-effect this means we can now use dma channels 12, 13 and 14
  17. in a correct manner - also testing shows that onl using
  18. channels 11 to 14 for spi and i2s works perfectly (when playing
  19. some video)
  20. Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
  21. Acked-by: Eric Anholt <eric@anholt.net>
  22. Acked-by: Mark Rutland <mark.rutland@arm.com>
  23. Signed-off-by: Vinod Koul <vinod.koul@intel.com>
  24. ---
  25. drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++++++++---------
  26. 1 file changed, 63 insertions(+), 14 deletions(-)
  27. --- a/drivers/dma/bcm2835-dma.c
  28. +++ b/drivers/dma/bcm2835-dma.c
  29. @@ -46,6 +46,9 @@
  30. #include "virt-dma.h"
  31. +#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
  32. +#define BCM2835_DMA_CHAN_NAME_SIZE 8
  33. +
  34. struct bcm2835_dmadev {
  35. struct dma_device ddev;
  36. spinlock_t lock;
  37. @@ -81,6 +84,7 @@ struct bcm2835_chan {
  38. void __iomem *chan_base;
  39. int irq_number;
  40. + unsigned int irq_flags;
  41. bool is_lite_channel;
  42. };
  43. @@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(
  44. struct bcm2835_desc *d;
  45. unsigned long flags;
  46. + /* check the shared interrupt */
  47. + if (c->irq_flags & IRQF_SHARED) {
  48. + /* check if the interrupt is enabled */
  49. + flags = readl(c->chan_base + BCM2835_DMA_CS);
  50. + /* if not set then we are not the reason for the irq */
  51. + if (!(flags & BCM2835_DMA_INT))
  52. + return IRQ_NONE;
  53. + }
  54. +
  55. spin_lock_irqsave(&c->vc.lock, flags);
  56. /* Acknowledge interrupt */
  57. @@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resour
  58. return -ENOMEM;
  59. }
  60. - return request_irq(c->irq_number,
  61. - bcm2835_dma_callback, 0, "DMA IRQ", c);
  62. + return request_irq(c->irq_number, bcm2835_dma_callback,
  63. + c->irq_flags, "DMA IRQ", c);
  64. }
  65. static void bcm2835_dma_free_chan_resources(struct dma_chan *chan)
  66. @@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(str
  67. return 0;
  68. }
  69. -static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq)
  70. +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
  71. + int irq, unsigned int irq_flags)
  72. {
  73. struct bcm2835_chan *c;
  74. @@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct
  75. c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id);
  76. c->ch = chan_id;
  77. c->irq_number = irq;
  78. + c->irq_flags = irq_flags;
  79. /* check in DEBUG register if this is a LITE channel */
  80. if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
  81. @@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct plat
  82. struct resource *res;
  83. void __iomem *base;
  84. int rc;
  85. - int i;
  86. - int irq;
  87. + int i, j;
  88. + int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1];
  89. + int irq_flags;
  90. uint32_t chans_available;
  91. + char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
  92. if (!pdev->dev.dma_mask)
  93. pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
  94. @@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct plat
  95. goto err_no_dma;
  96. }
  97. - for (i = 0; i < pdev->num_resources; i++) {
  98. - irq = platform_get_irq(pdev, i);
  99. - if (irq < 0)
  100. - break;
  101. -
  102. - if (chans_available & (1 << i)) {
  103. - rc = bcm2835_dma_chan_init(od, i, irq);
  104. - if (rc)
  105. - goto err_no_dma;
  106. + /* get irqs for each channel that we support */
  107. + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
  108. + /* skip masked out channels */
  109. + if (!(chans_available & (1 << i))) {
  110. + irq[i] = -1;
  111. + continue;
  112. }
  113. +
  114. + /* get the named irq */
  115. + snprintf(chan_name, sizeof(chan_name), "dma%i", i);
  116. + irq[i] = platform_get_irq_byname(pdev, chan_name);
  117. + if (irq[i] >= 0)
  118. + continue;
  119. +
  120. + /* legacy device tree case handling */
  121. + dev_warn_once(&pdev->dev,
  122. + "missing interrupts-names property in device tree - legacy interpretation is used");
  123. + /*
  124. + * in case of channel >= 11
  125. + * use the 11th interrupt and that is shared
  126. + */
  127. + irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
  128. + }
  129. +
  130. + /* get irqs for each channel */
  131. + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
  132. + /* skip channels without irq */
  133. + if (irq[i] < 0)
  134. + continue;
  135. +
  136. + /* check if there are other channels that also use this irq */
  137. + irq_flags = 0;
  138. + for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
  139. + if ((i != j) && (irq[j] == irq[i])) {
  140. + irq_flags = IRQF_SHARED;
  141. + break;
  142. + }
  143. +
  144. + /* initialize the channel */
  145. + rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
  146. + if (rc)
  147. + goto err_no_dma;
  148. }
  149. dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);