|
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 */
|
@@ -845,6 +853,9 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
|
845 | 853 | list_del(&c->vc.chan.device_node);
|
846 | 854 | tasklet_kill(&c->vc.task);
|
847 | 855 | }
|
| 856 | + |
| 857 | + dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE, |
| 858 | + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
848 | 859 | }
|
849 | 860 |
|
850 | 861 | static const struct of_device_id bcm2835_dma_of_match[] = {
|
@@ -927,6 +938,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
|
927 | 938 |
|
928 | 939 | platform_set_drvdata(pdev, od);
|
929 | 940 |
|
| 941 | + od->zero_page = dma_map_page_attrs(od->ddev.dev, ZERO_PAGE(0), 0, |
| 942 | + PAGE_SIZE, DMA_TO_DEVICE, |
| 943 | + DMA_ATTR_SKIP_CPU_SYNC); |
| 944 | + if (dma_mapping_error(od->ddev.dev, od->zero_page)) { |
| 945 | + dev_err(&pdev->dev, "Failed to map zero page\n"); |
| 946 | + return -ENOMEM; |
| 947 | + } |
| 948 | + |
930 | 949 | /* Request DMA channel mask from device tree */
|
931 | 950 | if (of_property_read_u32(pdev->dev.of_node,
|
932 | 951 | "brcm,dma-channel-mask",
|
|
0 commit comments