|
53 | 53 | * @ddev: DMA device
|
54 | 54 | * @base: base address of register map
|
55 | 55 | * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients)
|
| 56 | + * @zero_page: bus address of zero page (to detect transactions copying from |
| 57 | + * zero page and avoid accessing memory if so) |
56 | 58 | */
|
57 | 59 | struct bcm2835_dmadev {
|
58 | 60 | struct dma_device ddev;
|
59 | 61 | void __iomem *base;
|
60 | 62 | struct device_dma_parameters dma_parms;
|
| 63 | + dma_addr_t zero_page; |
61 | 64 | };
|
62 | 65 |
|
63 | 66 | struct bcm2835_dma_cb {
|
@@ -705,6 +708,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
|
705 | 708 | size_t period_len, enum dma_transfer_direction direction,
|
706 | 709 | unsigned long flags)
|
707 | 710 | {
|
| 711 | + struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); |
708 | 712 | struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
|
709 | 713 | struct bcm2835_desc *d;
|
710 | 714 | dma_addr_t src, dst;
|
@@ -755,6 +759,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
|
755 | 759 | dst = c->cfg.dst_addr;
|
756 | 760 | src = buf_addr;
|
757 | 761 | info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
|
| 762 | + |
| 763 | + /* non-lite channels can write zeroes w/o accessing memory */ |
| 764 | + if (buf_addr == od->zero_page && !c->is_lite_channel) |
| 765 | + info |= BCM2835_DMA_S_IGNORE; |
758 | 766 | }
|
759 | 767 |
|
760 | 768 | /* calculate number of frames */
|
@@ -854,6 +862,9 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
|
854 | 862 | list_del(&c->vc.chan.device_node);
|
855 | 863 | tasklet_kill(&c->vc.task);
|
856 | 864 | }
|
| 865 | + |
| 866 | + dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE, |
| 867 | + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
857 | 868 | }
|
858 | 869 |
|
859 | 870 | static const struct of_device_id bcm2835_dma_of_match[] = {
|
@@ -940,6 +951,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
|
940 | 951 |
|
941 | 952 | platform_set_drvdata(pdev, od);
|
942 | 953 |
|
| 954 | + od->zero_page = dma_map_page_attrs(od->ddev.dev, ZERO_PAGE(0), 0, |
| 955 | + PAGE_SIZE, DMA_TO_DEVICE, |
| 956 | + DMA_ATTR_SKIP_CPU_SYNC); |
| 957 | + if (dma_mapping_error(od->ddev.dev, od->zero_page)) { |
| 958 | + dev_err(&pdev->dev, "Failed to map zero page\n"); |
| 959 | + return -ENOMEM; |
| 960 | + } |
| 961 | + |
943 | 962 | /* Request DMA channel mask from device tree */
|
944 | 963 | if (of_property_read_u32(pdev->dev.of_node,
|
945 | 964 | "brcm,dma-channel-mask",
|
|
0 commit comments