hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
kernel/drivers/dma/bcm2835-dma.c
....@@ -29,6 +29,7 @@
2929 #include <linux/slab.h>
3030 #include <linux/io.h>
3131 #include <linux/spinlock.h>
32
+#include <linux/irqstage.h>
3233 #include <linux/of.h>
3334 #include <linux/of_dma.h>
3435
....@@ -435,10 +436,20 @@
435436 writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
436437 }
437438
439
+static inline void bcm2835_dma_enable_channel(struct bcm2835_chan *c)
440
+{
441
+ writel(c->desc->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
442
+ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
443
+}
444
+
445
+static inline bool bcm2835_dma_oob_capable(void)
446
+{
447
+ return IS_ENABLED(CONFIG_DMA_BCM2835_OOB);
448
+}
449
+
438450 static void bcm2835_dma_start_desc(struct bcm2835_chan *c)
439451 {
440452 struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
441
- struct bcm2835_desc *d;
442453
443454 if (!vd) {
444455 c->desc = NULL;
....@@ -447,10 +458,41 @@
447458
448459 list_del(&vd->node);
449460
450
- c->desc = d = to_bcm2835_dma_desc(&vd->tx);
461
+ c->desc = to_bcm2835_dma_desc(&vd->tx);
462
+ if (!bcm2835_dma_oob_capable() || !vchan_oob_pulsed(vd))
463
+ bcm2835_dma_enable_channel(c);
464
+}
451465
452
- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
453
- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
466
+static bool do_channel(struct bcm2835_chan *c, struct bcm2835_desc *d)
467
+{
468
+ struct dmaengine_desc_callback cb;
469
+
470
+ if (running_oob()) {
471
+ if (!vchan_oob_handled(&d->vd))
472
+ return false;
473
+ dmaengine_desc_get_callback(&d->vd.tx, &cb);
474
+ if (dmaengine_desc_callback_valid(&cb)) {
475
+ vchan_unlock(&c->vc);
476
+ dmaengine_desc_callback_invoke(&cb, NULL);
477
+ vchan_lock(&c->vc);
478
+ }
479
+ return true;
480
+ }
481
+
482
+ if (d->cyclic) {
483
+ /* call the cyclic callback */
484
+ vchan_cyclic_callback(&d->vd);
485
+ } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
486
+ vchan_cookie_complete(&c->desc->vd);
487
+ bcm2835_dma_start_desc(c);
488
+ }
489
+
490
+ return true;
491
+}
492
+
493
+static inline bool is_base_irq_handler(void)
494
+{
495
+ return !bcm2835_dma_oob_capable() || running_oob();
454496 }
455497
456498 static irqreturn_t bcm2835_dma_callback(int irq, void *data)
....@@ -460,7 +502,7 @@
460502 unsigned long flags;
461503
462504 /* check the shared interrupt */
463
- if (c->irq_flags & IRQF_SHARED) {
505
+ if (is_base_irq_handler() && c->irq_flags & IRQF_SHARED) {
464506 /* check if the interrupt is enabled */
465507 flags = readl(c->chan_base + BCM2835_DMA_CS);
466508 /* if not set then we are not the reason for the irq */
....@@ -468,7 +510,8 @@
468510 return IRQ_NONE;
469511 }
470512
471
- spin_lock_irqsave(&c->vc.lock, flags);
513
+ /* CAUTION: If running in-band, hard irqs are on. */
514
+ vchan_lock_irqsave(&c->vc, flags);
472515
473516 /*
474517 * Clear the INT flag to receive further interrupts. Keep the channel
....@@ -477,22 +520,27 @@
477520 * if this IRQ handler is threaded.) If the channel is finished, it
478521 * will remain idle despite the ACTIVE flag being set.
479522 */
480
- writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
481
- c->chan_base + BCM2835_DMA_CS);
523
+ if (is_base_irq_handler())
524
+ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
525
+ c->chan_base + BCM2835_DMA_CS);
482526
483527 d = c->desc;
528
+ if (!d)
529
+ goto out;
484530
485
- if (d) {
486
- if (d->cyclic) {
487
- /* call the cyclic callback */
488
- vchan_cyclic_callback(&d->vd);
489
- } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
490
- vchan_cookie_complete(&c->desc->vd);
491
- bcm2835_dma_start_desc(c);
492
- }
531
+ if (bcm2835_dma_oob_capable() && running_oob()) {
532
+ /*
533
+ * If we cannot process this from the out-of-band
534
+ * stage, schedule a callback from in-band context.
535
+ */
536
+ if (!do_channel(c, d))
537
+ irq_post_inband(irq);
538
+ } else {
539
+ do_channel(c, d);
493540 }
494541
495
- spin_unlock_irqrestore(&c->vc.lock, flags);
542
+out:
543
+ vchan_unlock_irqrestore(&c->vc, flags);
496544
497545 return IRQ_HANDLED;
498546 }
....@@ -571,7 +619,7 @@
571619 if (ret == DMA_COMPLETE || !txstate)
572620 return ret;
573621
574
- spin_lock_irqsave(&c->vc.lock, flags);
622
+ vchan_lock_irqsave(&c->vc, flags);
575623 vd = vchan_find_desc(&c->vc, cookie);
576624 if (vd) {
577625 txstate->residue =
....@@ -592,7 +640,7 @@
592640 txstate->residue = 0;
593641 }
594642
595
- spin_unlock_irqrestore(&c->vc.lock, flags);
643
+ vchan_unlock_irqrestore(&c->vc, flags);
596644
597645 return ret;
598646 }
....@@ -602,12 +650,35 @@
602650 struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
603651 unsigned long flags;
604652
605
- spin_lock_irqsave(&c->vc.lock, flags);
653
+ vchan_lock_irqsave(&c->vc, flags);
606654 if (vchan_issue_pending(&c->vc) && !c->desc)
607655 bcm2835_dma_start_desc(c);
608656
609
- spin_unlock_irqrestore(&c->vc.lock, flags);
657
+ vchan_unlock_irqrestore(&c->vc, flags);
610658 }
659
+
660
+#ifdef CONFIG_DMA_BCM2835_OOB
661
+static int bcm2835_dma_pulse_oob(struct dma_chan *chan)
662
+{
663
+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
664
+ unsigned long flags;
665
+ int ret = -EIO;
666
+
667
+ vchan_lock_irqsave(&c->vc, flags);
668
+ if (c->desc && vchan_oob_pulsed(&c->desc->vd)) {
669
+ bcm2835_dma_enable_channel(c);
670
+ ret = 0;
671
+ }
672
+ vchan_unlock_irqrestore(&c->vc, flags);
673
+
674
+ return ret;
675
+}
676
+#else
677
+static int bcm2835_dma_pulse_oob(struct dma_chan *chan)
678
+{
679
+ return -ENOTSUPP;
680
+}
681
+#endif
611682
612683 static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy(
613684 struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
....@@ -649,6 +720,15 @@
649720 u32 info = BCM2835_DMA_WAIT_RESP;
650721 u32 extra = BCM2835_DMA_INT_EN;
651722 size_t frames;
723
+
724
+ if (!bcm2835_dma_oob_capable()) {
725
+ if (flags & (DMA_OOB_INTERRUPT|DMA_OOB_PULSE)) {
726
+ dev_err(chan->device->dev,
727
+ "%s: out-of-band slave transfers disabled\n",
728
+ __func__);
729
+ return NULL;
730
+ }
731
+ }
652732
653733 if (!is_slave_direction(direction)) {
654734 dev_err(chan->device->dev,
....@@ -715,7 +795,21 @@
715795 return NULL;
716796 }
717797
718
- if (flags & DMA_PREP_INTERRUPT)
798
+ if (!bcm2835_dma_oob_capable()) {
799
+ if (flags & DMA_OOB_INTERRUPT) {
800
+ dev_err(chan->device->dev,
801
+ "%s: out-of-band cyclic transfers disabled\n",
802
+ __func__);
803
+ return NULL;
804
+ }
805
+ } else if (flags & DMA_OOB_PULSE) {
806
+ dev_err(chan->device->dev,
807
+ "%s: no pulse mode with out-of-band cyclic transfers\n",
808
+ __func__);
809
+ return NULL;
810
+ }
811
+
812
+ if (flags & (DMA_PREP_INTERRUPT|DMA_OOB_INTERRUPT))
719813 extra |= BCM2835_DMA_INT_EN;
720814 else
721815 period_len = buf_len;
....@@ -791,7 +885,7 @@
791885 unsigned long flags;
792886 LIST_HEAD(head);
793887
794
- spin_lock_irqsave(&c->vc.lock, flags);
888
+ vchan_lock_irqsave(&c->vc, flags);
795889
796890 /* stop DMA activity */
797891 if (c->desc) {
....@@ -801,7 +895,7 @@
801895 }
802896
803897 vchan_get_all_descriptors(&c->vc, &head);
804
- spin_unlock_irqrestore(&c->vc.lock, flags);
898
+ vchan_unlock_irqrestore(&c->vc, flags);
805899 vchan_dma_desc_free_list(&c->vc, &head);
806900
807901 return 0;
....@@ -912,11 +1006,13 @@
9121006 dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
9131007 dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask);
9141008 dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
1009
+ dma_cap_set(DMA_OOB, od->ddev.cap_mask);
9151010 dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask);
9161011 od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources;
9171012 od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources;
9181013 od->ddev.device_tx_status = bcm2835_dma_tx_status;
9191014 od->ddev.device_issue_pending = bcm2835_dma_issue_pending;
1015
+ od->ddev.device_pulse_oob = bcm2835_dma_pulse_oob;
9201016 od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic;
9211017 od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg;
9221018 od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy;
....@@ -982,10 +1078,10 @@
9821078 continue;
9831079
9841080 /* check if there are other channels that also use this irq */
985
- irq_flags = 0;
1081
+ irq_flags = IS_ENABLED(CONFIG_DMA_BCM2835_OOB) ? IRQF_OOB : 0;
9861082 for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
9871083 if ((i != j) && (irq[j] == irq[i])) {
988
- irq_flags = IRQF_SHARED;
1084
+ irq_flags |= IRQF_SHARED;
9891085 break;
9901086 }
9911087