|
42 | 42 | * @ddev: DMA device
|
43 | 43 | * @base: base address of register map
|
44 | 44 | * @dma_parms: DMA parameters (to convey 1 GByte max segment size to clients)
|
| 45 | + * @zero_page: bus address of zero page (to detect transactions copying from |
| 46 | + * zero page and avoid accessing memory if so) |
45 | 47 | */
|
46 | 48 | struct bcm2835_dmadev {
|
47 | 49 | struct dma_device ddev;
|
48 | 50 | void __iomem *base;
|
49 | 51 | struct device_dma_parameters dma_parms;
|
| 52 | + dma_addr_t zero_page; |
50 | 53 | };
|
51 | 54 |
|
52 | 55 | struct bcm2835_dma_cb {
|
@@ -693,6 +696,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
|
693 | 696 | size_t period_len, enum dma_transfer_direction direction,
|
694 | 697 | unsigned long flags)
|
695 | 698 | {
|
| 699 | + struct bcm2835_dmadev *od = to_bcm2835_dma_dev(chan->device); |
696 | 700 | struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
|
697 | 701 | struct bcm2835_desc *d;
|
698 | 702 | dma_addr_t src, dst;
|
@@ -743,6 +747,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
|
743 | 747 | dst = c->cfg.dst_addr;
|
744 | 748 | src = buf_addr;
|
745 | 749 | info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
|
| 750 | + |
| 751 | + /* non-lite channels can write zeroes w/o accessing memory */ |
| 752 | + if (buf_addr == od->zero_page && !c->is_lite_channel) |
| 753 | + info |= BCM2835_DMA_S_IGNORE; |
746 | 754 | }
|
747 | 755 |
|
748 | 756 | /* calculate number of frames */
|
@@ -842,6 +850,9 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
|
842 | 850 | list_del(&c->vc.chan.device_node);
|
843 | 851 | tasklet_kill(&c->vc.task);
|
844 | 852 | }
|
| 853 | + |
| 854 | + dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE, |
| 855 | + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
845 | 856 | }
|
846 | 857 |
|
847 | 858 | static const struct of_device_id bcm2835_dma_of_match[] = {
|
@@ -924,6 +935,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
|
924 | 935 |
|
925 | 936 | platform_set_drvdata(pdev, od);
|
926 | 937 |
|
| 938 | + od->zero_page = dma_map_page_attrs(od->ddev.dev, ZERO_PAGE(0), 0, |
| 939 | + PAGE_SIZE, DMA_TO_DEVICE, |
| 940 | + DMA_ATTR_SKIP_CPU_SYNC); |
| 941 | + if (dma_mapping_error(od->ddev.dev, od->zero_page)) { |
| 942 | + dev_err(&pdev->dev, "Failed to map zero page\n"); |
| 943 | + return -ENOMEM; |
| 944 | + } |
| 945 | + |
927 | 946 | /* Request DMA channel mask from device tree */
|
928 | 947 | if (of_property_read_u32(pdev->dev.of_node,
|
929 | 948 | "brcm,dma-channel-mask",
|
|
0 commit comments