diff options
Diffstat (limited to 'drivers/dma/bcm2835-dma.c')
| -rw-r--r-- | drivers/dma/bcm2835-dma.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 4768ef26013b..321748e2983e 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -41,14 +41,12 @@ * struct bcm2835_dmadev - BCM2835 DMA controller * @ddev: DMA device * @base: base address of register map - * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients) * @zero_page: bus address of zero page (to detect transactions copying from * zero page and avoid accessing memory if so) */ struct bcm2835_dmadev { struct dma_device ddev; void __iomem *base; - struct device_dma_parameters dma_parms; dma_addr_t zero_page; }; @@ -371,7 +369,7 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( /* the last frame requires extra flags */ d->cb_list[d->frames - 1].cb->info |= finalextrainfo; - /* detect a size missmatch */ + /* detect a size mismatch */ if (buf_len && (d->size != buf_len)) goto error_cb; @@ -877,10 +875,30 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, return chan; } +static int bcm2835_dma_suspend_late(struct device *dev) +{ + struct bcm2835_dmadev *od = dev_get_drvdata(dev); + struct bcm2835_chan *c, *next; + + list_for_each_entry_safe(c, next, &od->ddev.channels, + vc.chan.device_node) { + void __iomem *chan_base = c->chan_base; + + /* Check if DMA channel is busy */ + if (readl(chan_base + BCM2835_DMA_ADDR)) + return -EBUSY; + } + + return 0; +} + +static const struct dev_pm_ops bcm2835_dma_pm_ops = { + LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late, NULL) +}; + static int bcm2835_dma_probe(struct platform_device *pdev) { struct bcm2835_dmadev *od; - struct resource *res; void __iomem *base; int rc; int i, j; @@ -902,11 +920,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) if (!od) return -ENOMEM; - pdev->dev.dma_parms = &od->dma_parms; dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -1024,28 +1040,26 @@ err_no_dma: return rc; } -static int bcm2835_dma_remove(struct platform_device *pdev) +static void bcm2835_dma_remove(struct platform_device *pdev) { struct bcm2835_dmadev *od = platform_get_drvdata(pdev); dma_async_device_unregister(&od->ddev); bcm2835_dma_free(od); - - return 0; } static struct platform_driver bcm2835_dma_driver = { .probe = bcm2835_dma_probe, - .remove = bcm2835_dma_remove, + .remove = bcm2835_dma_remove, .driver = { .name = "bcm2835-dma", .of_match_table = of_match_ptr(bcm2835_dma_of_match), + .pm = pm_ptr(&bcm2835_dma_pm_ops), }, }; module_platform_driver(bcm2835_dma_driver); -MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); MODULE_LICENSE("GPL"); |
