Loading drivers/dma/bcm2835-dma.c +31 −61 Original line number Diff line number Diff line Loading @@ -2,9 +2,6 @@ /* * BCM2835 DMA engine support * * This driver only supports cyclic DMA transfers * as needed for the I2S module. * * Author: Florian Meier <florian.meier@koalo.de> * Copyright 2013 * Loading Loading @@ -42,7 +39,6 @@ struct bcm2835_dmadev { struct dma_device ddev; spinlock_t lock; void __iomem *base; struct device_dma_parameters dma_parms; }; Loading @@ -64,7 +60,6 @@ struct bcm2835_cb_entry { struct bcm2835_chan { struct virt_dma_chan vc; struct list_head node; struct dma_slave_config cfg; unsigned int dreq; Loading Loading @@ -405,39 +400,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg( } } static int bcm2835_dma_abort(void __iomem *chan_base) static void bcm2835_dma_abort(struct bcm2835_chan *c) { unsigned long cs; void __iomem *chan_base = c->chan_base; long int timeout = 10000; cs = readl(chan_base + BCM2835_DMA_CS); if (!(cs & BCM2835_DMA_ACTIVE)) return 0; /* * A zero control block address means the channel is idle. * (The ACTIVE flag in the CS register is not a reliable indicator.) */ if (!readl(chan_base + BCM2835_DMA_ADDR)) return; /* Write 0 to the active bit - Pause the DMA */ writel(0, chan_base + BCM2835_DMA_CS); /* Wait for any current AXI transfer to complete */ while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) { while ((readl(chan_base + BCM2835_DMA_CS) & BCM2835_DMA_WAITING_FOR_WRITES) && --timeout) cpu_relax(); cs = readl(chan_base + BCM2835_DMA_CS); } /* We'll un-pause when we set of our next DMA */ /* Peripheral might be stuck and fail to signal AXI write responses */ if (!timeout) return -ETIMEDOUT; if (!(cs & BCM2835_DMA_ACTIVE)) return 0; dev_err(c->vc.chan.device->dev, "failed to complete outstanding writes\n"); /* Terminate the control block chain */ writel(0, chan_base + BCM2835_DMA_NEXTCB); /* Abort the whole DMA */ writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE, chan_base + BCM2835_DMA_CS); return 0; writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS); } static void bcm2835_dma_start_desc(struct bcm2835_chan *c) Loading Loading @@ -475,8 +463,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) spin_lock_irqsave(&c->vc.lock, flags); /* Acknowledge interrupt */ writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS); /* * Clear the INT flag to receive further interrupts. Keep the channel * active in case the descriptor is cyclic or in case the client has * already terminated the descriptor and issued a new one. (May happen * if this IRQ handler is threaded.) If the channel is finished, it * will remain idle despite the ACTIVE flag being set. */ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); d = c->desc; Loading @@ -484,11 +479,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) if (d->cyclic) { /* call the cyclic callback */ vchan_cyclic_callback(&d->vd); /* Keep the DMA engine running */ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); } else { } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) { vchan_cookie_complete(&c->desc->vd); bcm2835_dma_start_desc(c); } Loading @@ -506,8 +497,12 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) dev_dbg(dev, "Allocating DMA channel %d\n", c->ch); /* * Control blocks are 256 bit in length and must start at a 256 bit * (32 byte) aligned address (BCM2835 ARM Peripherals, sec. 4.2.1.1). */ c->cb_pool = dma_pool_create(dev_name(dev), dev, sizeof(struct bcm2835_dma_cb), 0, 0); sizeof(struct bcm2835_dma_cb), 32, 0); if (!c->cb_pool) { dev_err(dev, "unable to allocate descriptor pool\n"); return -ENOMEM; Loading Loading @@ -776,39 +771,16 @@ static int bcm2835_dma_slave_config(struct dma_chan *chan, static int bcm2835_dma_terminate_all(struct dma_chan *chan) { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); unsigned long flags; int timeout = 10000; LIST_HEAD(head); spin_lock_irqsave(&c->vc.lock, flags); /* Prevent this channel being scheduled */ spin_lock(&d->lock); list_del_init(&c->node); spin_unlock(&d->lock); /* * Stop DMA activity: we assume the callback will not be called * after bcm_dma_abort() returns (even if it does, it will see * c->desc is NULL and exit.) */ /* stop DMA activity */ if (c->desc) { vchan_terminate_vdesc(&c->desc->vd); c->desc = NULL; bcm2835_dma_abort(c->chan_base); /* Wait for stopping */ while (--timeout) { if (!(readl(c->chan_base + BCM2835_DMA_CS) & BCM2835_DMA_ACTIVE)) break; cpu_relax(); } if (!timeout) dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); bcm2835_dma_abort(c); } vchan_get_all_descriptors(&c->vc, &head); Loading Loading @@ -836,7 +808,6 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, c->vc.desc_free = bcm2835_dma_desc_free; vchan_init(&c->vc, &d->ddev); INIT_LIST_HEAD(&c->node); c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); c->ch = chan_id; Loading Loading @@ -939,7 +910,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); spin_lock_init(&od->lock); platform_set_drvdata(pdev, od); Loading Loading
drivers/dma/bcm2835-dma.c +31 −61 Original line number Diff line number Diff line Loading @@ -2,9 +2,6 @@ /* * BCM2835 DMA engine support * * This driver only supports cyclic DMA transfers * as needed for the I2S module. * * Author: Florian Meier <florian.meier@koalo.de> * Copyright 2013 * Loading Loading @@ -42,7 +39,6 @@ struct bcm2835_dmadev { struct dma_device ddev; spinlock_t lock; void __iomem *base; struct device_dma_parameters dma_parms; }; Loading @@ -64,7 +60,6 @@ struct bcm2835_cb_entry { struct bcm2835_chan { struct virt_dma_chan vc; struct list_head node; struct dma_slave_config cfg; unsigned int dreq; Loading Loading @@ -405,39 +400,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg( } } static int bcm2835_dma_abort(void __iomem *chan_base) static void bcm2835_dma_abort(struct bcm2835_chan *c) { unsigned long cs; void __iomem *chan_base = c->chan_base; long int timeout = 10000; cs = readl(chan_base + BCM2835_DMA_CS); if (!(cs & BCM2835_DMA_ACTIVE)) return 0; /* * A zero control block address means the channel is idle. * (The ACTIVE flag in the CS register is not a reliable indicator.) */ if (!readl(chan_base + BCM2835_DMA_ADDR)) return; /* Write 0 to the active bit - Pause the DMA */ writel(0, chan_base + BCM2835_DMA_CS); /* Wait for any current AXI transfer to complete */ while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) { while ((readl(chan_base + BCM2835_DMA_CS) & BCM2835_DMA_WAITING_FOR_WRITES) && --timeout) cpu_relax(); cs = readl(chan_base + BCM2835_DMA_CS); } /* We'll un-pause when we set of our next DMA */ /* Peripheral might be stuck and fail to signal AXI write responses */ if (!timeout) return -ETIMEDOUT; if (!(cs & BCM2835_DMA_ACTIVE)) return 0; dev_err(c->vc.chan.device->dev, "failed to complete outstanding writes\n"); /* Terminate the control block chain */ writel(0, chan_base + BCM2835_DMA_NEXTCB); /* Abort the whole DMA */ writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE, chan_base + BCM2835_DMA_CS); return 0; writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS); } static void bcm2835_dma_start_desc(struct bcm2835_chan *c) Loading Loading @@ -475,8 +463,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) spin_lock_irqsave(&c->vc.lock, flags); /* Acknowledge interrupt */ writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS); /* * Clear the INT flag to receive further interrupts. Keep the channel * active in case the descriptor is cyclic or in case the client has * already terminated the descriptor and issued a new one. (May happen * if this IRQ handler is threaded.) If the channel is finished, it * will remain idle despite the ACTIVE flag being set. */ writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); d = c->desc; Loading @@ -484,11 +479,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) if (d->cyclic) { /* call the cyclic callback */ vchan_cyclic_callback(&d->vd); /* Keep the DMA engine running */ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); } else { } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) { vchan_cookie_complete(&c->desc->vd); bcm2835_dma_start_desc(c); } Loading @@ -506,8 +497,12 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) dev_dbg(dev, "Allocating DMA channel %d\n", c->ch); /* * Control blocks are 256 bit in length and must start at a 256 bit * (32 byte) aligned address (BCM2835 ARM Peripherals, sec. 4.2.1.1). */ c->cb_pool = dma_pool_create(dev_name(dev), dev, sizeof(struct bcm2835_dma_cb), 0, 0); sizeof(struct bcm2835_dma_cb), 32, 0); if (!c->cb_pool) { dev_err(dev, "unable to allocate descriptor pool\n"); return -ENOMEM; Loading Loading @@ -776,39 +771,16 @@ static int bcm2835_dma_slave_config(struct dma_chan *chan, static int bcm2835_dma_terminate_all(struct dma_chan *chan) { struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); unsigned long flags; int timeout = 10000; LIST_HEAD(head); spin_lock_irqsave(&c->vc.lock, flags); /* Prevent this channel being scheduled */ spin_lock(&d->lock); list_del_init(&c->node); spin_unlock(&d->lock); /* * Stop DMA activity: we assume the callback will not be called * after bcm_dma_abort() returns (even if it does, it will see * c->desc is NULL and exit.) */ /* stop DMA activity */ if (c->desc) { vchan_terminate_vdesc(&c->desc->vd); c->desc = NULL; bcm2835_dma_abort(c->chan_base); /* Wait for stopping */ while (--timeout) { if (!(readl(c->chan_base + BCM2835_DMA_CS) & BCM2835_DMA_ACTIVE)) break; cpu_relax(); } if (!timeout) dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); bcm2835_dma_abort(c); } vchan_get_all_descriptors(&c->vc, &head); Loading Loading @@ -836,7 +808,6 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, c->vc.desc_free = bcm2835_dma_desc_free; vchan_init(&c->vc, &d->ddev); INIT_LIST_HEAD(&c->node); c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); c->ch = chan_id; Loading Loading @@ -939,7 +910,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; od->ddev.dev = &pdev->dev; INIT_LIST_HEAD(&od->ddev.channels); spin_lock_init(&od->lock); platform_set_drvdata(pdev, od); Loading