diff options
Diffstat (limited to 'drivers/dma/at_hdmac.c')
-rw-r--r-- | drivers/dma/at_hdmac.c | 130 |
1 files changed, 82 insertions, 48 deletions
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index ca9dd2613283..1e1a4c567542 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -42,6 +42,11 @@ | |||
42 | #define ATC_DEFAULT_CFG (ATC_FIFOCFG_HALFFIFO) | 42 | #define ATC_DEFAULT_CFG (ATC_FIFOCFG_HALFFIFO) |
43 | #define ATC_DEFAULT_CTRLB (ATC_SIF(AT_DMA_MEM_IF) \ | 43 | #define ATC_DEFAULT_CTRLB (ATC_SIF(AT_DMA_MEM_IF) \ |
44 | |ATC_DIF(AT_DMA_MEM_IF)) | 44 | |ATC_DIF(AT_DMA_MEM_IF)) |
45 | #define ATC_DMA_BUSWIDTHS\ | ||
46 | (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\ | ||
47 | BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |\ | ||
48 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\ | ||
49 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) | ||
45 | 50 | ||
46 | /* | 51 | /* |
47 | * Initial number of descriptors to allocate for each channel. This could | 52 | * Initial number of descriptors to allocate for each channel. This could |
@@ -972,11 +977,13 @@ err_out: | |||
972 | return NULL; | 977 | return NULL; |
973 | } | 978 | } |
974 | 979 | ||
975 | static int set_runtime_config(struct dma_chan *chan, | 980 | static int atc_config(struct dma_chan *chan, |
976 | struct dma_slave_config *sconfig) | 981 | struct dma_slave_config *sconfig) |
977 | { | 982 | { |
978 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 983 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
979 | 984 | ||
985 | dev_vdbg(chan2dev(chan), "%s\n", __func__); | ||
986 | |||
980 | /* Check if it is chan is configured for slave transfers */ | 987 | /* Check if it is chan is configured for slave transfers */ |
981 | if (!chan->private) | 988 | if (!chan->private) |
982 | return -EINVAL; | 989 | return -EINVAL; |
@@ -989,9 +996,28 @@ static int set_runtime_config(struct dma_chan *chan, | |||
989 | return 0; | 996 | return 0; |
990 | } | 997 | } |
991 | 998 | ||
999 | static int atc_pause(struct dma_chan *chan) | ||
1000 | { | ||
1001 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | ||
1002 | struct at_dma *atdma = to_at_dma(chan->device); | ||
1003 | int chan_id = atchan->chan_common.chan_id; | ||
1004 | unsigned long flags; | ||
992 | 1005 | ||
993 | static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 1006 | LIST_HEAD(list); |
994 | unsigned long arg) | 1007 | |
1008 | dev_vdbg(chan2dev(chan), "%s\n", __func__); | ||
1009 | |||
1010 | spin_lock_irqsave(&atchan->lock, flags); | ||
1011 | |||
1012 | dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id)); | ||
1013 | set_bit(ATC_IS_PAUSED, &atchan->status); | ||
1014 | |||
1015 | spin_unlock_irqrestore(&atchan->lock, flags); | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int atc_resume(struct dma_chan *chan) | ||
995 | { | 1021 | { |
996 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 1022 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
997 | struct at_dma *atdma = to_at_dma(chan->device); | 1023 | struct at_dma *atdma = to_at_dma(chan->device); |
@@ -1000,60 +1026,61 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
1000 | 1026 | ||
1001 | LIST_HEAD(list); | 1027 | LIST_HEAD(list); |
1002 | 1028 | ||
1003 | dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd); | 1029 | dev_vdbg(chan2dev(chan), "%s\n", __func__); |
1004 | 1030 | ||
1005 | if (cmd == DMA_PAUSE) { | 1031 | if (!atc_chan_is_paused(atchan)) |
1006 | spin_lock_irqsave(&atchan->lock, flags); | 1032 | return 0; |
1007 | 1033 | ||
1008 | dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id)); | 1034 | spin_lock_irqsave(&atchan->lock, flags); |
1009 | set_bit(ATC_IS_PAUSED, &atchan->status); | ||
1010 | 1035 | ||
1011 | spin_unlock_irqrestore(&atchan->lock, flags); | 1036 | dma_writel(atdma, CHDR, AT_DMA_RES(chan_id)); |
1012 | } else if (cmd == DMA_RESUME) { | 1037 | clear_bit(ATC_IS_PAUSED, &atchan->status); |
1013 | if (!atc_chan_is_paused(atchan)) | ||
1014 | return 0; | ||
1015 | 1038 | ||
1016 | spin_lock_irqsave(&atchan->lock, flags); | 1039 | spin_unlock_irqrestore(&atchan->lock, flags); |
1017 | 1040 | ||
1018 | dma_writel(atdma, CHDR, AT_DMA_RES(chan_id)); | 1041 | return 0; |
1019 | clear_bit(ATC_IS_PAUSED, &atchan->status); | 1042 | } |
1020 | 1043 | ||
1021 | spin_unlock_irqrestore(&atchan->lock, flags); | 1044 | static int atc_terminate_all(struct dma_chan *chan) |
1022 | } else if (cmd == DMA_TERMINATE_ALL) { | 1045 | { |
1023 | struct at_desc *desc, *_desc; | 1046 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
1024 | /* | 1047 | struct at_dma *atdma = to_at_dma(chan->device); |
1025 | * This is only called when something went wrong elsewhere, so | 1048 | int chan_id = atchan->chan_common.chan_id; |
1026 | * we don't really care about the data. Just disable the | 1049 | struct at_desc *desc, *_desc; |
1027 | * channel. We still have to poll the channel enable bit due | 1050 | unsigned long flags; |
1028 | * to AHB/HSB limitations. | ||
1029 | */ | ||
1030 | spin_lock_irqsave(&atchan->lock, flags); | ||
1031 | 1051 | ||
1032 | /* disabling channel: must also remove suspend state */ | 1052 | LIST_HEAD(list); |
1033 | dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask); | ||
1034 | 1053 | ||
1035 | /* confirm that this channel is disabled */ | 1054 | dev_vdbg(chan2dev(chan), "%s\n", __func__); |
1036 | while (dma_readl(atdma, CHSR) & atchan->mask) | ||
1037 | cpu_relax(); | ||
1038 | 1055 | ||
1039 | /* active_list entries will end up before queued entries */ | 1056 | /* |
1040 | list_splice_init(&atchan->queue, &list); | 1057 | * This is only called when something went wrong elsewhere, so |
1041 | list_splice_init(&atchan->active_list, &list); | 1058 | * we don't really care about the data. Just disable the |
1059 | * channel. We still have to poll the channel enable bit due | ||
1060 | * to AHB/HSB limitations. | ||
1061 | */ | ||
1062 | spin_lock_irqsave(&atchan->lock, flags); | ||
1042 | 1063 | ||
1043 | /* Flush all pending and queued descriptors */ | 1064 | /* disabling channel: must also remove suspend state */ |
1044 | list_for_each_entry_safe(desc, _desc, &list, desc_node) | 1065 | dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask); |
1045 | atc_chain_complete(atchan, desc); | ||
1046 | 1066 | ||
1047 | clear_bit(ATC_IS_PAUSED, &atchan->status); | 1067 | /* confirm that this channel is disabled */ |
1048 | /* if channel dedicated to cyclic operations, free it */ | 1068 | while (dma_readl(atdma, CHSR) & atchan->mask) |
1049 | clear_bit(ATC_IS_CYCLIC, &atchan->status); | 1069 | cpu_relax(); |
1050 | 1070 | ||
1051 | spin_unlock_irqrestore(&atchan->lock, flags); | 1071 | /* active_list entries will end up before queued entries */ |
1052 | } else if (cmd == DMA_SLAVE_CONFIG) { | 1072 | list_splice_init(&atchan->queue, &list); |
1053 | return set_runtime_config(chan, (struct dma_slave_config *)arg); | 1073 | list_splice_init(&atchan->active_list, &list); |
1054 | } else { | 1074 | |
1055 | return -ENXIO; | 1075 | /* Flush all pending and queued descriptors */ |
1056 | } | 1076 | list_for_each_entry_safe(desc, _desc, &list, desc_node) |
1077 | atc_chain_complete(atchan, desc); | ||
1078 | |||
1079 | clear_bit(ATC_IS_PAUSED, &atchan->status); | ||
1080 | /* if channel dedicated to cyclic operations, free it */ | ||
1081 | clear_bit(ATC_IS_CYCLIC, &atchan->status); | ||
1082 | |||
1083 | spin_unlock_irqrestore(&atchan->lock, flags); | ||
1057 | 1084 | ||
1058 | return 0; | 1085 | return 0; |
1059 | } | 1086 | } |
@@ -1505,7 +1532,14 @@ static int __init at_dma_probe(struct platform_device *pdev) | |||
1505 | /* controller can do slave DMA: can trigger cyclic transfers */ | 1532 | /* controller can do slave DMA: can trigger cyclic transfers */ |
1506 | dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask); | 1533 | dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask); |
1507 | atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic; | 1534 | atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic; |
1508 | atdma->dma_common.device_control = atc_control; | 1535 | atdma->dma_common.device_config = atc_config; |
1536 | atdma->dma_common.device_pause = atc_pause; | ||
1537 | atdma->dma_common.device_resume = atc_resume; | ||
1538 | atdma->dma_common.device_terminate_all = atc_terminate_all; | ||
1539 | atdma->dma_common.src_addr_widths = ATC_DMA_BUSWIDTHS; | ||
1540 | atdma->dma_common.dst_addr_widths = ATC_DMA_BUSWIDTHS; | ||
1541 | atdma->dma_common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); | ||
1542 | atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | ||
1509 | } | 1543 | } |
1510 | 1544 | ||
1511 | dma_writel(atdma, EN, AT_DMA_ENABLE); | 1545 | dma_writel(atdma, EN, AT_DMA_ENABLE); |
@@ -1622,7 +1656,7 @@ static void atc_suspend_cyclic(struct at_dma_chan *atchan) | |||
1622 | if (!atc_chan_is_paused(atchan)) { | 1656 | if (!atc_chan_is_paused(atchan)) { |
1623 | dev_warn(chan2dev(chan), | 1657 | dev_warn(chan2dev(chan), |
1624 | "cyclic channel not paused, should be done by channel user\n"); | 1658 | "cyclic channel not paused, should be done by channel user\n"); |
1625 | atc_control(chan, DMA_PAUSE, 0); | 1659 | atc_pause(chan); |
1626 | } | 1660 | } |
1627 | 1661 | ||
1628 | /* now preserve additional data for cyclic operations */ | 1662 | /* now preserve additional data for cyclic operations */ |