diff options
| -rw-r--r-- | Documentation/devicetree/bindings/dma/snps-dma.txt | 2 | ||||
| -rw-r--r-- | drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 2 | ||||
| -rw-r--r-- | drivers/dma/dw/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/dma/dw/Makefile | 2 | ||||
| -rw-r--r-- | drivers/dma/dw/core.c | 244 | ||||
| -rw-r--r-- | drivers/dma/dw/dw.c | 138 | ||||
| -rw-r--r-- | drivers/dma/dw/idma32.c | 160 | ||||
| -rw-r--r-- | drivers/dma/dw/internal.h | 15 | ||||
| -rw-r--r-- | drivers/dma/dw/pci.c | 53 | ||||
| -rw-r--r-- | drivers/dma/dw/platform.c | 22 | ||||
| -rw-r--r-- | drivers/dma/dw/regs.h | 30 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250_lpss.c | 1 | ||||
| -rw-r--r-- | include/linux/dma/dw.h | 9 | ||||
| -rw-r--r-- | include/linux/platform_data/dma-dw.h | 12 |
14 files changed, 426 insertions, 266 deletions
diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt index db757df7057d..0bedceed1963 100644 --- a/Documentation/devicetree/bindings/dma/snps-dma.txt +++ b/Documentation/devicetree/bindings/dma/snps-dma.txt | |||
| @@ -23,8 +23,6 @@ Deprecated properties: | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | Optional properties: | 25 | Optional properties: |
| 26 | - is_private: The device channels should be marked as private and not for by the | ||
| 27 | general purpose DMA channel allocator. False if not passed. | ||
| 28 | - multi-block: Multi block transfers supported by hardware. Array property with | 26 | - multi-block: Multi block transfers supported by hardware. Array property with |
| 29 | one cell per channel. 0: not supported, 1 (default): supported. | 27 | one cell per channel. 0: not supported, 1 (default): supported. |
| 30 | - snps,dma-protection-control: AHB HPROT[3:1] protection setting. | 28 | - snps,dma-protection-control: AHB HPROT[3:1] protection setting. |
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index f8888dc0b8dc..18b6014cf9b4 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h | |||
| @@ -75,7 +75,7 @@ struct __packed axi_dma_lli { | |||
| 75 | __le32 sstat; | 75 | __le32 sstat; |
| 76 | __le32 dstat; | 76 | __le32 dstat; |
| 77 | __le32 status_lo; | 77 | __le32 status_lo; |
| 78 | __le32 ststus_hi; | 78 | __le32 status_hi; |
| 79 | __le32 reserved_lo; | 79 | __le32 reserved_lo; |
| 80 | __le32 reserved_hi; | 80 | __le32 reserved_hi; |
| 81 | }; | 81 | }; |
diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig index 04b9728c1d26..e5162690de8f 100644 --- a/drivers/dma/dw/Kconfig +++ b/drivers/dma/dw/Kconfig | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 1 | # | 3 | # |
| 2 | # DMA engine configuration for dw | 4 | # DMA engine configuration for dw |
| 3 | # | 5 | # |
diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile index 2b949c2e4504..63ed895c09aa 100644 --- a/drivers/dma/dw/Makefile +++ b/drivers/dma/dw/Makefile | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | obj-$(CONFIG_DW_DMAC_CORE) += dw_dmac_core.o | 2 | obj-$(CONFIG_DW_DMAC_CORE) += dw_dmac_core.o |
| 3 | dw_dmac_core-objs := core.o | 3 | dw_dmac_core-objs := core.o dw.o idma32.o |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_DW_DMAC) += dw_dmac.o | 5 | obj-$(CONFIG_DW_DMAC) += dw_dmac.o |
| 6 | dw_dmac-objs := platform.o | 6 | dw_dmac-objs := platform.o |
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 290d21be4d4c..21cb2a58dbd2 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c | |||
| @@ -1,13 +1,10 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Core driver for the Synopsys DesignWare DMA Controller | 3 | * Core driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2007-2008 Atmel Corporation | 5 | * Copyright (C) 2007-2008 Atmel Corporation |
| 5 | * Copyright (C) 2010-2011 ST Microelectronics | 6 | * Copyright (C) 2010-2011 ST Microelectronics |
| 6 | * Copyright (C) 2013 Intel Corporation | 7 | * Copyright (C) 2013 Intel Corporation |
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | 8 | */ |
| 12 | 9 | ||
| 13 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| @@ -37,27 +34,6 @@ | |||
| 37 | * support descriptor writeback. | 34 | * support descriptor writeback. |
| 38 | */ | 35 | */ |
| 39 | 36 | ||
| 40 | #define DWC_DEFAULT_CTLLO(_chan) ({ \ | ||
| 41 | struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ | ||
| 42 | struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ | ||
| 43 | bool _is_slave = is_slave_direction(_dwc->direction); \ | ||
| 44 | u8 _smsize = _is_slave ? _sconfig->src_maxburst : \ | ||
| 45 | DW_DMA_MSIZE_16; \ | ||
| 46 | u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ | ||
| 47 | DW_DMA_MSIZE_16; \ | ||
| 48 | u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ? \ | ||
| 49 | _dwc->dws.p_master : _dwc->dws.m_master; \ | ||
| 50 | u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ? \ | ||
| 51 | _dwc->dws.p_master : _dwc->dws.m_master; \ | ||
| 52 | \ | ||
| 53 | (DWC_CTLL_DST_MSIZE(_dmsize) \ | ||
| 54 | | DWC_CTLL_SRC_MSIZE(_smsize) \ | ||
| 55 | | DWC_CTLL_LLP_D_EN \ | ||
| 56 | | DWC_CTLL_LLP_S_EN \ | ||
| 57 | | DWC_CTLL_DMS(_dms) \ | ||
| 58 | | DWC_CTLL_SMS(_sms)); \ | ||
| 59 | }) | ||
| 60 | |||
| 61 | /* The set of bus widths supported by the DMA controller */ | 37 | /* The set of bus widths supported by the DMA controller */ |
| 62 | #define DW_DMA_BUSWIDTHS \ | 38 | #define DW_DMA_BUSWIDTHS \ |
| 63 | BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \ | 39 | BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \ |
| @@ -138,44 +114,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
| 138 | dwc->descs_allocated--; | 114 | dwc->descs_allocated--; |
| 139 | } | 115 | } |
| 140 | 116 | ||
| 141 | static void dwc_initialize_chan_idma32(struct dw_dma_chan *dwc) | ||
| 142 | { | ||
| 143 | u32 cfghi = 0; | ||
| 144 | u32 cfglo = 0; | ||
| 145 | |||
| 146 | /* Set default burst alignment */ | ||
| 147 | cfglo |= IDMA32C_CFGL_DST_BURST_ALIGN | IDMA32C_CFGL_SRC_BURST_ALIGN; | ||
| 148 | |||
| 149 | /* Low 4 bits of the request lines */ | ||
| 150 | cfghi |= IDMA32C_CFGH_DST_PER(dwc->dws.dst_id & 0xf); | ||
| 151 | cfghi |= IDMA32C_CFGH_SRC_PER(dwc->dws.src_id & 0xf); | ||
| 152 | |||
| 153 | /* Request line extension (2 bits) */ | ||
| 154 | cfghi |= IDMA32C_CFGH_DST_PER_EXT(dwc->dws.dst_id >> 4 & 0x3); | ||
| 155 | cfghi |= IDMA32C_CFGH_SRC_PER_EXT(dwc->dws.src_id >> 4 & 0x3); | ||
| 156 | |||
| 157 | channel_writel(dwc, CFG_LO, cfglo); | ||
| 158 | channel_writel(dwc, CFG_HI, cfghi); | ||
| 159 | } | ||
| 160 | |||
| 161 | static void dwc_initialize_chan_dw(struct dw_dma_chan *dwc) | ||
| 162 | { | ||
| 163 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
| 164 | u32 cfghi = DWC_CFGH_FIFO_MODE; | ||
| 165 | u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); | ||
| 166 | bool hs_polarity = dwc->dws.hs_polarity; | ||
| 167 | |||
| 168 | cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id); | ||
| 169 | cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id); | ||
| 170 | cfghi |= DWC_CFGH_PROTCTL(dw->pdata->protctl); | ||
| 171 | |||
| 172 | /* Set polarity of handshake interface */ | ||
| 173 | cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0; | ||
| 174 | |||
| 175 | channel_writel(dwc, CFG_LO, cfglo); | ||
| 176 | channel_writel(dwc, CFG_HI, cfghi); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void dwc_initialize(struct dw_dma_chan *dwc) | 117 | static void dwc_initialize(struct dw_dma_chan *dwc) |
| 180 | { | 118 | { |
| 181 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | 119 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); |
| @@ -183,10 +121,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) | |||
| 183 | if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) | 121 | if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags)) |
| 184 | return; | 122 | return; |
| 185 | 123 | ||
| 186 | if (dw->pdata->is_idma32) | 124 | dw->initialize_chan(dwc); |
| 187 | dwc_initialize_chan_idma32(dwc); | ||
| 188 | else | ||
| 189 | dwc_initialize_chan_dw(dwc); | ||
| 190 | 125 | ||
| 191 | /* Enable interrupts */ | 126 | /* Enable interrupts */ |
| 192 | channel_set_bit(dw, MASK.XFER, dwc->mask); | 127 | channel_set_bit(dw, MASK.XFER, dwc->mask); |
| @@ -215,37 +150,6 @@ static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
| 215 | cpu_relax(); | 150 | cpu_relax(); |
| 216 | } | 151 | } |
| 217 | 152 | ||
| 218 | static u32 bytes2block(struct dw_dma_chan *dwc, size_t bytes, | ||
| 219 | unsigned int width, size_t *len) | ||
| 220 | { | ||
| 221 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
| 222 | u32 block; | ||
| 223 | |||
| 224 | /* Always in bytes for iDMA 32-bit */ | ||
| 225 | if (dw->pdata->is_idma32) | ||
| 226 | width = 0; | ||
| 227 | |||
| 228 | if ((bytes >> width) > dwc->block_size) { | ||
| 229 | block = dwc->block_size; | ||
| 230 | *len = block << width; | ||
| 231 | } else { | ||
| 232 | block = bytes >> width; | ||
| 233 | *len = bytes; | ||
| 234 | } | ||
| 235 | |||
| 236 | return block; | ||
| 237 | } | ||
| 238 | |||
| 239 | static size_t block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) | ||
| 240 | { | ||
| 241 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
| 242 | |||
| 243 | if (dw->pdata->is_idma32) | ||
| 244 | return IDMA32C_CTLH_BLOCK_TS(block); | ||
| 245 | |||
| 246 | return DWC_CTLH_BLOCK_TS(block) << width; | ||
| 247 | } | ||
| 248 | |||
| 249 | /*----------------------------------------------------------------------*/ | 153 | /*----------------------------------------------------------------------*/ |
| 250 | 154 | ||
| 251 | /* Perform single block transfer */ | 155 | /* Perform single block transfer */ |
| @@ -391,10 +295,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
| 391 | /* Returns how many bytes were already received from source */ | 295 | /* Returns how many bytes were already received from source */ |
| 392 | static inline u32 dwc_get_sent(struct dw_dma_chan *dwc) | 296 | static inline u32 dwc_get_sent(struct dw_dma_chan *dwc) |
| 393 | { | 297 | { |
| 298 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
| 394 | u32 ctlhi = channel_readl(dwc, CTL_HI); | 299 | u32 ctlhi = channel_readl(dwc, CTL_HI); |
| 395 | u32 ctllo = channel_readl(dwc, CTL_LO); | 300 | u32 ctllo = channel_readl(dwc, CTL_LO); |
| 396 | 301 | ||
| 397 | return block2bytes(dwc, ctlhi, ctllo >> 4 & 7); | 302 | return dw->block2bytes(dwc, ctlhi, ctllo >> 4 & 7); |
| 398 | } | 303 | } |
| 399 | 304 | ||
| 400 | static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) | 305 | static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) |
| @@ -651,7 +556,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
| 651 | unsigned int src_width; | 556 | unsigned int src_width; |
| 652 | unsigned int dst_width; | 557 | unsigned int dst_width; |
| 653 | unsigned int data_width = dw->pdata->data_width[m_master]; | 558 | unsigned int data_width = dw->pdata->data_width[m_master]; |
| 654 | u32 ctllo; | 559 | u32 ctllo, ctlhi; |
| 655 | u8 lms = DWC_LLP_LMS(m_master); | 560 | u8 lms = DWC_LLP_LMS(m_master); |
| 656 | 561 | ||
| 657 | dev_vdbg(chan2dev(chan), | 562 | dev_vdbg(chan2dev(chan), |
| @@ -667,7 +572,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
| 667 | 572 | ||
| 668 | src_width = dst_width = __ffs(data_width | src | dest | len); | 573 | src_width = dst_width = __ffs(data_width | src | dest | len); |
| 669 | 574 | ||
| 670 | ctllo = DWC_DEFAULT_CTLLO(chan) | 575 | ctllo = dw->prepare_ctllo(dwc) |
| 671 | | DWC_CTLL_DST_WIDTH(dst_width) | 576 | | DWC_CTLL_DST_WIDTH(dst_width) |
| 672 | | DWC_CTLL_SRC_WIDTH(src_width) | 577 | | DWC_CTLL_SRC_WIDTH(src_width) |
| 673 | | DWC_CTLL_DST_INC | 578 | | DWC_CTLL_DST_INC |
| @@ -680,10 +585,12 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
| 680 | if (!desc) | 585 | if (!desc) |
| 681 | goto err_desc_get; | 586 | goto err_desc_get; |
| 682 | 587 | ||
| 588 | ctlhi = dw->bytes2block(dwc, len - offset, src_width, &xfer_count); | ||
| 589 | |||
| 683 | lli_write(desc, sar, src + offset); | 590 | lli_write(desc, sar, src + offset); |
| 684 | lli_write(desc, dar, dest + offset); | 591 | lli_write(desc, dar, dest + offset); |
| 685 | lli_write(desc, ctllo, ctllo); | 592 | lli_write(desc, ctllo, ctllo); |
| 686 | lli_write(desc, ctlhi, bytes2block(dwc, len - offset, src_width, &xfer_count)); | 593 | lli_write(desc, ctlhi, ctlhi); |
| 687 | desc->len = xfer_count; | 594 | desc->len = xfer_count; |
| 688 | 595 | ||
| 689 | if (!first) { | 596 | if (!first) { |
| @@ -721,7 +628,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
| 721 | struct dma_slave_config *sconfig = &dwc->dma_sconfig; | 628 | struct dma_slave_config *sconfig = &dwc->dma_sconfig; |
| 722 | struct dw_desc *prev; | 629 | struct dw_desc *prev; |
| 723 | struct dw_desc *first; | 630 | struct dw_desc *first; |
| 724 | u32 ctllo; | 631 | u32 ctllo, ctlhi; |
| 725 | u8 m_master = dwc->dws.m_master; | 632 | u8 m_master = dwc->dws.m_master; |
| 726 | u8 lms = DWC_LLP_LMS(m_master); | 633 | u8 lms = DWC_LLP_LMS(m_master); |
| 727 | dma_addr_t reg; | 634 | dma_addr_t reg; |
| @@ -745,10 +652,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
| 745 | case DMA_MEM_TO_DEV: | 652 | case DMA_MEM_TO_DEV: |
| 746 | reg_width = __ffs(sconfig->dst_addr_width); | 653 | reg_width = __ffs(sconfig->dst_addr_width); |
| 747 | reg = sconfig->dst_addr; | 654 | reg = sconfig->dst_addr; |
| 748 | ctllo = (DWC_DEFAULT_CTLLO(chan) | 655 | ctllo = dw->prepare_ctllo(dwc) |
| 749 | | DWC_CTLL_DST_WIDTH(reg_width) | 656 | | DWC_CTLL_DST_WIDTH(reg_width) |
| 750 | | DWC_CTLL_DST_FIX | 657 | | DWC_CTLL_DST_FIX |
| 751 | | DWC_CTLL_SRC_INC); | 658 | | DWC_CTLL_SRC_INC; |
| 752 | 659 | ||
| 753 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : | 660 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : |
| 754 | DWC_CTLL_FC(DW_DMA_FC_D_M2P); | 661 | DWC_CTLL_FC(DW_DMA_FC_D_M2P); |
| @@ -768,9 +675,11 @@ slave_sg_todev_fill_desc: | |||
| 768 | if (!desc) | 675 | if (!desc) |
| 769 | goto err_desc_get; | 676 | goto err_desc_get; |
| 770 | 677 | ||
| 678 | ctlhi = dw->bytes2block(dwc, len, mem_width, &dlen); | ||
| 679 | |||
| 771 | lli_write(desc, sar, mem); | 680 | lli_write(desc, sar, mem); |
| 772 | lli_write(desc, dar, reg); | 681 | lli_write(desc, dar, reg); |
| 773 | lli_write(desc, ctlhi, bytes2block(dwc, len, mem_width, &dlen)); | 682 | lli_write(desc, ctlhi, ctlhi); |
| 774 | lli_write(desc, ctllo, ctllo | DWC_CTLL_SRC_WIDTH(mem_width)); | 683 | lli_write(desc, ctllo, ctllo | DWC_CTLL_SRC_WIDTH(mem_width)); |
| 775 | desc->len = dlen; | 684 | desc->len = dlen; |
| 776 | 685 | ||
| @@ -793,10 +702,10 @@ slave_sg_todev_fill_desc: | |||
| 793 | case DMA_DEV_TO_MEM: | 702 | case DMA_DEV_TO_MEM: |
| 794 | reg_width = __ffs(sconfig->src_addr_width); | 703 | reg_width = __ffs(sconfig->src_addr_width); |
| 795 | reg = sconfig->src_addr; | 704 | reg = sconfig->src_addr; |
| 796 | ctllo = (DWC_DEFAULT_CTLLO(chan) | 705 | ctllo = dw->prepare_ctllo(dwc) |
| 797 | | DWC_CTLL_SRC_WIDTH(reg_width) | 706 | | DWC_CTLL_SRC_WIDTH(reg_width) |
| 798 | | DWC_CTLL_DST_INC | 707 | | DWC_CTLL_DST_INC |
| 799 | | DWC_CTLL_SRC_FIX); | 708 | | DWC_CTLL_SRC_FIX; |
| 800 | 709 | ||
| 801 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : | 710 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : |
| 802 | DWC_CTLL_FC(DW_DMA_FC_D_P2M); | 711 | DWC_CTLL_FC(DW_DMA_FC_D_P2M); |
| @@ -814,9 +723,11 @@ slave_sg_fromdev_fill_desc: | |||
| 814 | if (!desc) | 723 | if (!desc) |
| 815 | goto err_desc_get; | 724 | goto err_desc_get; |
| 816 | 725 | ||
| 726 | ctlhi = dw->bytes2block(dwc, len, reg_width, &dlen); | ||
| 727 | |||
| 817 | lli_write(desc, sar, reg); | 728 | lli_write(desc, sar, reg); |
| 818 | lli_write(desc, dar, mem); | 729 | lli_write(desc, dar, mem); |
| 819 | lli_write(desc, ctlhi, bytes2block(dwc, len, reg_width, &dlen)); | 730 | lli_write(desc, ctlhi, ctlhi); |
| 820 | mem_width = __ffs(data_width | mem | dlen); | 731 | mem_width = __ffs(data_width | mem | dlen); |
| 821 | lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width)); | 732 | lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width)); |
| 822 | desc->len = dlen; | 733 | desc->len = dlen; |
| @@ -876,22 +787,12 @@ EXPORT_SYMBOL_GPL(dw_dma_filter); | |||
| 876 | static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) | 787 | static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) |
| 877 | { | 788 | { |
| 878 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | 789 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
| 879 | struct dma_slave_config *sc = &dwc->dma_sconfig; | ||
| 880 | struct dw_dma *dw = to_dw_dma(chan->device); | 790 | struct dw_dma *dw = to_dw_dma(chan->device); |
| 881 | /* | ||
| 882 | * Fix sconfig's burst size according to dw_dmac. We need to convert | ||
| 883 | * them as: | ||
| 884 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. | ||
| 885 | * | ||
| 886 | * NOTE: burst size 2 is not supported by DesignWare controller. | ||
| 887 | * iDMA 32-bit supports it. | ||
| 888 | */ | ||
| 889 | u32 s = dw->pdata->is_idma32 ? 1 : 2; | ||
| 890 | 791 | ||
| 891 | memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); | 792 | memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); |
| 892 | 793 | ||
| 893 | sc->src_maxburst = sc->src_maxburst > 1 ? fls(sc->src_maxburst) - s : 0; | 794 | dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst); |
| 894 | sc->dst_maxburst = sc->dst_maxburst > 1 ? fls(sc->dst_maxburst) - s : 0; | 795 | dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst); |
| 895 | 796 | ||
| 896 | return 0; | 797 | return 0; |
| 897 | } | 798 | } |
| @@ -900,16 +801,9 @@ static void dwc_chan_pause(struct dw_dma_chan *dwc, bool drain) | |||
| 900 | { | 801 | { |
| 901 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | 802 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); |
| 902 | unsigned int count = 20; /* timeout iterations */ | 803 | unsigned int count = 20; /* timeout iterations */ |
| 903 | u32 cfglo; | ||
| 904 | 804 | ||
| 905 | cfglo = channel_readl(dwc, CFG_LO); | 805 | dw->suspend_chan(dwc, drain); |
| 906 | if (dw->pdata->is_idma32) { | 806 | |
| 907 | if (drain) | ||
| 908 | cfglo |= IDMA32C_CFGL_CH_DRAIN; | ||
| 909 | else | ||
| 910 | cfglo &= ~IDMA32C_CFGL_CH_DRAIN; | ||
| 911 | } | ||
| 912 | channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP); | ||
| 913 | while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY) && count--) | 807 | while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY) && count--) |
| 914 | udelay(2); | 808 | udelay(2); |
| 915 | 809 | ||
| @@ -928,11 +822,11 @@ static int dwc_pause(struct dma_chan *chan) | |||
| 928 | return 0; | 822 | return 0; |
| 929 | } | 823 | } |
| 930 | 824 | ||
| 931 | static inline void dwc_chan_resume(struct dw_dma_chan *dwc) | 825 | static inline void dwc_chan_resume(struct dw_dma_chan *dwc, bool drain) |
| 932 | { | 826 | { |
| 933 | u32 cfglo = channel_readl(dwc, CFG_LO); | 827 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); |
| 934 | 828 | ||
| 935 | channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); | 829 | dw->resume_chan(dwc, drain); |
| 936 | 830 | ||
| 937 | clear_bit(DW_DMA_IS_PAUSED, &dwc->flags); | 831 | clear_bit(DW_DMA_IS_PAUSED, &dwc->flags); |
| 938 | } | 832 | } |
| @@ -945,7 +839,7 @@ static int dwc_resume(struct dma_chan *chan) | |||
| 945 | spin_lock_irqsave(&dwc->lock, flags); | 839 | spin_lock_irqsave(&dwc->lock, flags); |
| 946 | 840 | ||
| 947 | if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags)) | 841 | if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags)) |
| 948 | dwc_chan_resume(dwc); | 842 | dwc_chan_resume(dwc, false); |
| 949 | 843 | ||
| 950 | spin_unlock_irqrestore(&dwc->lock, flags); | 844 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 951 | 845 | ||
| @@ -968,7 +862,7 @@ static int dwc_terminate_all(struct dma_chan *chan) | |||
| 968 | 862 | ||
| 969 | dwc_chan_disable(dw, dwc); | 863 | dwc_chan_disable(dw, dwc); |
| 970 | 864 | ||
| 971 | dwc_chan_resume(dwc); | 865 | dwc_chan_resume(dwc, true); |
| 972 | 866 | ||
| 973 | /* active_list entries will end up before queued entries */ | 867 | /* active_list entries will end up before queued entries */ |
| 974 | list_splice_init(&dwc->queue, &list); | 868 | list_splice_init(&dwc->queue, &list); |
| @@ -1058,33 +952,7 @@ static void dwc_issue_pending(struct dma_chan *chan) | |||
| 1058 | 952 | ||
| 1059 | /*----------------------------------------------------------------------*/ | 953 | /*----------------------------------------------------------------------*/ |
| 1060 | 954 | ||
| 1061 | /* | 955 | void do_dw_dma_off(struct dw_dma *dw) |
| 1062 | * Program FIFO size of channels. | ||
| 1063 | * | ||
| 1064 | * By default full FIFO (512 bytes) is assigned to channel 0. Here we | ||
| 1065 | * slice FIFO on equal parts between channels. | ||
| 1066 | */ | ||
| 1067 | static void idma32_fifo_partition(struct dw_dma *dw) | ||
| 1068 | { | ||
| 1069 | u64 value = IDMA32C_FP_PSIZE_CH0(64) | IDMA32C_FP_PSIZE_CH1(64) | | ||
| 1070 | IDMA32C_FP_UPDATE; | ||
| 1071 | u64 fifo_partition = 0; | ||
| 1072 | |||
| 1073 | if (!dw->pdata->is_idma32) | ||
| 1074 | return; | ||
| 1075 | |||
| 1076 | /* Fill FIFO_PARTITION low bits (Channels 0..1, 4..5) */ | ||
| 1077 | fifo_partition |= value << 0; | ||
| 1078 | |||
| 1079 | /* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */ | ||
| 1080 | fifo_partition |= value << 32; | ||
| 1081 | |||
| 1082 | /* Program FIFO Partition registers - 64 bytes per channel */ | ||
| 1083 | idma32_writeq(dw, FIFO_PARTITION1, fifo_partition); | ||
| 1084 | idma32_writeq(dw, FIFO_PARTITION0, fifo_partition); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | static void dw_dma_off(struct dw_dma *dw) | ||
| 1088 | { | 956 | { |
| 1089 | unsigned int i; | 957 | unsigned int i; |
| 1090 | 958 | ||
| @@ -1103,7 +971,7 @@ static void dw_dma_off(struct dw_dma *dw) | |||
| 1103 | clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags); | 971 | clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags); |
| 1104 | } | 972 | } |
| 1105 | 973 | ||
| 1106 | static void dw_dma_on(struct dw_dma *dw) | 974 | void do_dw_dma_on(struct dw_dma *dw) |
| 1107 | { | 975 | { |
| 1108 | dma_writel(dw, CFG, DW_CFG_DMA_EN); | 976 | dma_writel(dw, CFG, DW_CFG_DMA_EN); |
| 1109 | } | 977 | } |
| @@ -1139,7 +1007,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) | |||
| 1139 | 1007 | ||
| 1140 | /* Enable controller here if needed */ | 1008 | /* Enable controller here if needed */ |
| 1141 | if (!dw->in_use) | 1009 | if (!dw->in_use) |
| 1142 | dw_dma_on(dw); | 1010 | do_dw_dma_on(dw); |
| 1143 | dw->in_use |= dwc->mask; | 1011 | dw->in_use |= dwc->mask; |
| 1144 | 1012 | ||
| 1145 | return 0; | 1013 | return 0; |
| @@ -1176,30 +1044,25 @@ static void dwc_free_chan_resources(struct dma_chan *chan) | |||
| 1176 | /* Disable controller in case it was a last user */ | 1044 | /* Disable controller in case it was a last user */ |
| 1177 | dw->in_use &= ~dwc->mask; | 1045 | dw->in_use &= ~dwc->mask; |
| 1178 | if (!dw->in_use) | 1046 | if (!dw->in_use) |
| 1179 | dw_dma_off(dw); | 1047 | do_dw_dma_off(dw); |
| 1180 | 1048 | ||
| 1181 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); | 1049 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); |
| 1182 | } | 1050 | } |
| 1183 | 1051 | ||
| 1184 | int dw_dma_probe(struct dw_dma_chip *chip) | 1052 | int do_dma_probe(struct dw_dma_chip *chip) |
| 1185 | { | 1053 | { |
| 1054 | struct dw_dma *dw = chip->dw; | ||
| 1186 | struct dw_dma_platform_data *pdata; | 1055 | struct dw_dma_platform_data *pdata; |
| 1187 | struct dw_dma *dw; | ||
| 1188 | bool autocfg = false; | 1056 | bool autocfg = false; |
| 1189 | unsigned int dw_params; | 1057 | unsigned int dw_params; |
| 1190 | unsigned int i; | 1058 | unsigned int i; |
| 1191 | int err; | 1059 | int err; |
| 1192 | 1060 | ||
| 1193 | dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL); | ||
| 1194 | if (!dw) | ||
| 1195 | return -ENOMEM; | ||
| 1196 | |||
| 1197 | dw->pdata = devm_kzalloc(chip->dev, sizeof(*dw->pdata), GFP_KERNEL); | 1061 | dw->pdata = devm_kzalloc(chip->dev, sizeof(*dw->pdata), GFP_KERNEL); |
| 1198 | if (!dw->pdata) | 1062 | if (!dw->pdata) |
| 1199 | return -ENOMEM; | 1063 | return -ENOMEM; |
| 1200 | 1064 | ||
| 1201 | dw->regs = chip->regs; | 1065 | dw->regs = chip->regs; |
| 1202 | chip->dw = dw; | ||
| 1203 | 1066 | ||
| 1204 | pm_runtime_get_sync(chip->dev); | 1067 | pm_runtime_get_sync(chip->dev); |
| 1205 | 1068 | ||
| @@ -1226,8 +1089,6 @@ int dw_dma_probe(struct dw_dma_chip *chip) | |||
| 1226 | pdata->block_size = dma_readl(dw, MAX_BLK_SIZE); | 1089 | pdata->block_size = dma_readl(dw, MAX_BLK_SIZE); |
| 1227 | 1090 | ||
| 1228 | /* Fill platform data with the default values */ | 1091 | /* Fill platform data with the default values */ |
| 1229 | pdata->is_private = true; | ||
| 1230 | pdata->is_memcpy = true; | ||
| 1231 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; | 1092 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; |
| 1232 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; | 1093 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; |
| 1233 | } else if (chip->pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { | 1094 | } else if (chip->pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) { |
| @@ -1251,15 +1112,10 @@ int dw_dma_probe(struct dw_dma_chip *chip) | |||
| 1251 | dw->all_chan_mask = (1 << pdata->nr_channels) - 1; | 1112 | dw->all_chan_mask = (1 << pdata->nr_channels) - 1; |
| 1252 | 1113 | ||
| 1253 | /* Force dma off, just in case */ | 1114 | /* Force dma off, just in case */ |
| 1254 | dw_dma_off(dw); | 1115 | dw->disable(dw); |
| 1255 | |||
| 1256 | idma32_fifo_partition(dw); | ||
| 1257 | 1116 | ||
| 1258 | /* Device and instance ID for IRQ and DMA pool */ | 1117 | /* Device and instance ID for IRQ and DMA pool */ |
| 1259 | if (pdata->is_idma32) | 1118 | dw->set_device_name(dw, chip->id); |
| 1260 | snprintf(dw->name, sizeof(dw->name), "idma32:dmac%d", chip->id); | ||
| 1261 | else | ||
| 1262 | snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", chip->id); | ||
| 1263 | 1119 | ||
| 1264 | /* Create a pool of consistent memory blocks for hardware descriptors */ | 1120 | /* Create a pool of consistent memory blocks for hardware descriptors */ |
| 1265 | dw->desc_pool = dmam_pool_create(dw->name, chip->dev, | 1121 | dw->desc_pool = dmam_pool_create(dw->name, chip->dev, |
| @@ -1339,10 +1195,8 @@ int dw_dma_probe(struct dw_dma_chip *chip) | |||
| 1339 | 1195 | ||
| 1340 | /* Set capabilities */ | 1196 | /* Set capabilities */ |
| 1341 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); | 1197 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); |
| 1342 | if (pdata->is_private) | 1198 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); |
| 1343 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); | 1199 | dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); |
| 1344 | if (pdata->is_memcpy) | ||
| 1345 | dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask); | ||
| 1346 | 1200 | ||
| 1347 | dw->dma.dev = chip->dev; | 1201 | dw->dma.dev = chip->dev; |
| 1348 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; | 1202 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; |
| @@ -1383,16 +1237,15 @@ err_pdata: | |||
| 1383 | pm_runtime_put_sync_suspend(chip->dev); | 1237 | pm_runtime_put_sync_suspend(chip->dev); |
| 1384 | return err; | 1238 | return err; |
| 1385 | } | 1239 | } |
| 1386 | EXPORT_SYMBOL_GPL(dw_dma_probe); | ||
| 1387 | 1240 | ||
| 1388 | int dw_dma_remove(struct dw_dma_chip *chip) | 1241 | int do_dma_remove(struct dw_dma_chip *chip) |
| 1389 | { | 1242 | { |
| 1390 | struct dw_dma *dw = chip->dw; | 1243 | struct dw_dma *dw = chip->dw; |
| 1391 | struct dw_dma_chan *dwc, *_dwc; | 1244 | struct dw_dma_chan *dwc, *_dwc; |
| 1392 | 1245 | ||
| 1393 | pm_runtime_get_sync(chip->dev); | 1246 | pm_runtime_get_sync(chip->dev); |
| 1394 | 1247 | ||
| 1395 | dw_dma_off(dw); | 1248 | do_dw_dma_off(dw); |
| 1396 | dma_async_device_unregister(&dw->dma); | 1249 | dma_async_device_unregister(&dw->dma); |
| 1397 | 1250 | ||
| 1398 | free_irq(chip->irq, dw); | 1251 | free_irq(chip->irq, dw); |
| @@ -1407,27 +1260,24 @@ int dw_dma_remove(struct dw_dma_chip *chip) | |||
| 1407 | pm_runtime_put_sync_suspend(chip->dev); | 1260 | pm_runtime_put_sync_suspend(chip->dev); |
| 1408 | return 0; | 1261 | return 0; |
| 1409 | } | 1262 | } |
| 1410 | EXPORT_SYMBOL_GPL(dw_dma_remove); | ||
| 1411 | 1263 | ||
| 1412 | int dw_dma_disable(struct dw_dma_chip *chip) | 1264 | int do_dw_dma_disable(struct dw_dma_chip *chip) |
| 1413 | { | 1265 | { |
| 1414 | struct dw_dma *dw = chip->dw; | 1266 | struct dw_dma *dw = chip->dw; |
| 1415 | 1267 | ||
| 1416 | dw_dma_off(dw); | 1268 | dw->disable(dw); |
| 1417 | return 0; | 1269 | return 0; |
| 1418 | } | 1270 | } |
| 1419 | EXPORT_SYMBOL_GPL(dw_dma_disable); | 1271 | EXPORT_SYMBOL_GPL(do_dw_dma_disable); |
| 1420 | 1272 | ||
| 1421 | int dw_dma_enable(struct dw_dma_chip *chip) | 1273 | int do_dw_dma_enable(struct dw_dma_chip *chip) |
| 1422 | { | 1274 | { |
| 1423 | struct dw_dma *dw = chip->dw; | 1275 | struct dw_dma *dw = chip->dw; |
| 1424 | 1276 | ||
| 1425 | idma32_fifo_partition(dw); | 1277 | dw->enable(dw); |
| 1426 | |||
| 1427 | dw_dma_on(dw); | ||
| 1428 | return 0; | 1278 | return 0; |
| 1429 | } | 1279 | } |
| 1430 | EXPORT_SYMBOL_GPL(dw_dma_enable); | 1280 | EXPORT_SYMBOL_GPL(do_dw_dma_enable); |
| 1431 | 1281 | ||
| 1432 | MODULE_LICENSE("GPL v2"); | 1282 | MODULE_LICENSE("GPL v2"); |
| 1433 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller core driver"); | 1283 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller core driver"); |
diff --git a/drivers/dma/dw/dw.c b/drivers/dma/dw/dw.c new file mode 100644 index 000000000000..7a085b3c1854 --- /dev/null +++ b/drivers/dma/dw/dw.c | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | // Copyright (C) 2007-2008 Atmel Corporation | ||
| 3 | // Copyright (C) 2010-2011 ST Microelectronics | ||
| 4 | // Copyright (C) 2013,2018 Intel Corporation | ||
| 5 | |||
| 6 | #include <linux/bitops.h> | ||
| 7 | #include <linux/dmaengine.h> | ||
| 8 | #include <linux/errno.h> | ||
| 9 | #include <linux/slab.h> | ||
| 10 | #include <linux/types.h> | ||
| 11 | |||
| 12 | #include "internal.h" | ||
| 13 | |||
| 14 | static void dw_dma_initialize_chan(struct dw_dma_chan *dwc) | ||
| 15 | { | ||
| 16 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
| 17 | u32 cfghi = DWC_CFGH_FIFO_MODE; | ||
| 18 | u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); | ||
| 19 | bool hs_polarity = dwc->dws.hs_polarity; | ||
| 20 | |||
| 21 | cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id); | ||
| 22 | cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id); | ||
| 23 | cfghi |= DWC_CFGH_PROTCTL(dw->pdata->protctl); | ||
| 24 | |||
| 25 | /* Set polarity of handshake interface */ | ||
| 26 | cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0; | ||
| 27 | |||
| 28 | channel_writel(dwc, CFG_LO, cfglo); | ||
| 29 | channel_writel(dwc, CFG_HI, cfghi); | ||
| 30 | } | ||
| 31 | |||
| 32 | static void dw_dma_suspend_chan(struct dw_dma_chan *dwc, bool drain) | ||
| 33 | { | ||
| 34 | u32 cfglo = channel_readl(dwc, CFG_LO); | ||
| 35 | |||
| 36 | channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP); | ||
| 37 | } | ||
| 38 | |||
| 39 | static void dw_dma_resume_chan(struct dw_dma_chan *dwc, bool drain) | ||
| 40 | { | ||
| 41 | u32 cfglo = channel_readl(dwc, CFG_LO); | ||
| 42 | |||
| 43 | channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); | ||
| 44 | } | ||
| 45 | |||
| 46 | static u32 dw_dma_bytes2block(struct dw_dma_chan *dwc, | ||
| 47 | size_t bytes, unsigned int width, size_t *len) | ||
| 48 | { | ||
| 49 | u32 block; | ||
| 50 | |||
| 51 | if ((bytes >> width) > dwc->block_size) { | ||
| 52 | block = dwc->block_size; | ||
| 53 | *len = dwc->block_size << width; | ||
| 54 | } else { | ||
| 55 | block = bytes >> width; | ||
| 56 | *len = bytes; | ||
| 57 | } | ||
| 58 | |||
| 59 | return block; | ||
| 60 | } | ||
| 61 | |||
| 62 | static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) | ||
| 63 | { | ||
| 64 | return DWC_CTLH_BLOCK_TS(block) << width; | ||
| 65 | } | ||
| 66 | |||
| 67 | static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) | ||
| 68 | { | ||
| 69 | struct dma_slave_config *sconfig = &dwc->dma_sconfig; | ||
| 70 | bool is_slave = is_slave_direction(dwc->direction); | ||
| 71 | u8 smsize = is_slave ? sconfig->src_maxburst : DW_DMA_MSIZE_16; | ||
| 72 | u8 dmsize = is_slave ? sconfig->dst_maxburst : DW_DMA_MSIZE_16; | ||
| 73 | u8 p_master = dwc->dws.p_master; | ||
| 74 | u8 m_master = dwc->dws.m_master; | ||
| 75 | u8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master; | ||
| 76 | u8 sms = (dwc->direction == DMA_DEV_TO_MEM) ? p_master : m_master; | ||
| 77 | |||
| 78 | return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | | ||
| 79 | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) | | ||
| 80 | DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void dw_dma_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst) | ||
| 84 | { | ||
| 85 | /* | ||
| 86 | * Fix burst size according to dw_dmac. We need to convert them as: | ||
| 87 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. | ||
| 88 | */ | ||
| 89 | *maxburst = *maxburst > 1 ? fls(*maxburst) - 2 : 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | static void dw_dma_set_device_name(struct dw_dma *dw, int id) | ||
| 93 | { | ||
| 94 | snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", id); | ||
| 95 | } | ||
| 96 | |||
| 97 | static void dw_dma_disable(struct dw_dma *dw) | ||
| 98 | { | ||
| 99 | do_dw_dma_off(dw); | ||
| 100 | } | ||
| 101 | |||
| 102 | static void dw_dma_enable(struct dw_dma *dw) | ||
| 103 | { | ||
| 104 | do_dw_dma_on(dw); | ||
| 105 | } | ||
| 106 | |||
| 107 | int dw_dma_probe(struct dw_dma_chip *chip) | ||
| 108 | { | ||
| 109 | struct dw_dma *dw; | ||
| 110 | |||
| 111 | dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL); | ||
| 112 | if (!dw) | ||
| 113 | return -ENOMEM; | ||
| 114 | |||
| 115 | /* Channel operations */ | ||
| 116 | dw->initialize_chan = dw_dma_initialize_chan; | ||
| 117 | dw->suspend_chan = dw_dma_suspend_chan; | ||
| 118 | dw->resume_chan = dw_dma_resume_chan; | ||
| 119 | dw->prepare_ctllo = dw_dma_prepare_ctllo; | ||
| 120 | dw->encode_maxburst = dw_dma_encode_maxburst; | ||
| 121 | dw->bytes2block = dw_dma_bytes2block; | ||
| 122 | dw->block2bytes = dw_dma_block2bytes; | ||
| 123 | |||
| 124 | /* Device operations */ | ||
| 125 | dw->set_device_name = dw_dma_set_device_name; | ||
| 126 | dw->disable = dw_dma_disable; | ||
| 127 | dw->enable = dw_dma_enable; | ||
| 128 | |||
| 129 | chip->dw = dw; | ||
| 130 | return do_dma_probe(chip); | ||
| 131 | } | ||
| 132 | EXPORT_SYMBOL_GPL(dw_dma_probe); | ||
| 133 | |||
| 134 | int dw_dma_remove(struct dw_dma_chip *chip) | ||
| 135 | { | ||
| 136 | return do_dma_remove(chip); | ||
| 137 | } | ||
| 138 | EXPORT_SYMBOL_GPL(dw_dma_remove); | ||
diff --git a/drivers/dma/dw/idma32.c b/drivers/dma/dw/idma32.c new file mode 100644 index 000000000000..f00657308811 --- /dev/null +++ b/drivers/dma/dw/idma32.c | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | // Copyright (C) 2013,2018 Intel Corporation | ||
| 3 | |||
| 4 | #include <linux/bitops.h> | ||
| 5 | #include <linux/dmaengine.h> | ||
| 6 | #include <linux/errno.h> | ||
| 7 | #include <linux/slab.h> | ||
| 8 | #include <linux/types.h> | ||
| 9 | |||
| 10 | #include "internal.h" | ||
| 11 | |||
| 12 | static void idma32_initialize_chan(struct dw_dma_chan *dwc) | ||
| 13 | { | ||
| 14 | u32 cfghi = 0; | ||
| 15 | u32 cfglo = 0; | ||
| 16 | |||
| 17 | /* Set default burst alignment */ | ||
| 18 | cfglo |= IDMA32C_CFGL_DST_BURST_ALIGN | IDMA32C_CFGL_SRC_BURST_ALIGN; | ||
| 19 | |||
| 20 | /* Low 4 bits of the request lines */ | ||
| 21 | cfghi |= IDMA32C_CFGH_DST_PER(dwc->dws.dst_id & 0xf); | ||
| 22 | cfghi |= IDMA32C_CFGH_SRC_PER(dwc->dws.src_id & 0xf); | ||
| 23 | |||
| 24 | /* Request line extension (2 bits) */ | ||
| 25 | cfghi |= IDMA32C_CFGH_DST_PER_EXT(dwc->dws.dst_id >> 4 & 0x3); | ||
| 26 | cfghi |= IDMA32C_CFGH_SRC_PER_EXT(dwc->dws.src_id >> 4 & 0x3); | ||
| 27 | |||
| 28 | channel_writel(dwc, CFG_LO, cfglo); | ||
| 29 | channel_writel(dwc, CFG_HI, cfghi); | ||
| 30 | } | ||
| 31 | |||
| 32 | static void idma32_suspend_chan(struct dw_dma_chan *dwc, bool drain) | ||
| 33 | { | ||
| 34 | u32 cfglo = channel_readl(dwc, CFG_LO); | ||
| 35 | |||
| 36 | if (drain) | ||
| 37 | cfglo |= IDMA32C_CFGL_CH_DRAIN; | ||
| 38 | |||
| 39 | channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP); | ||
| 40 | } | ||
| 41 | |||
| 42 | static void idma32_resume_chan(struct dw_dma_chan *dwc, bool drain) | ||
| 43 | { | ||
| 44 | u32 cfglo = channel_readl(dwc, CFG_LO); | ||
| 45 | |||
| 46 | if (drain) | ||
| 47 | cfglo &= ~IDMA32C_CFGL_CH_DRAIN; | ||
| 48 | |||
| 49 | channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP); | ||
| 50 | } | ||
| 51 | |||
| 52 | static u32 idma32_bytes2block(struct dw_dma_chan *dwc, | ||
| 53 | size_t bytes, unsigned int width, size_t *len) | ||
| 54 | { | ||
| 55 | u32 block; | ||
| 56 | |||
| 57 | if (bytes > dwc->block_size) { | ||
| 58 | block = dwc->block_size; | ||
| 59 | *len = dwc->block_size; | ||
| 60 | } else { | ||
| 61 | block = bytes; | ||
| 62 | *len = bytes; | ||
| 63 | } | ||
| 64 | |||
| 65 | return block; | ||
| 66 | } | ||
| 67 | |||
| 68 | static size_t idma32_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) | ||
| 69 | { | ||
| 70 | return IDMA32C_CTLH_BLOCK_TS(block); | ||
| 71 | } | ||
| 72 | |||
| 73 | static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) | ||
| 74 | { | ||
| 75 | struct dma_slave_config *sconfig = &dwc->dma_sconfig; | ||
| 76 | bool is_slave = is_slave_direction(dwc->direction); | ||
| 77 | u8 smsize = is_slave ? sconfig->src_maxburst : IDMA32_MSIZE_8; | ||
| 78 | u8 dmsize = is_slave ? sconfig->dst_maxburst : IDMA32_MSIZE_8; | ||
| 79 | |||
| 80 | return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | | ||
| 81 | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize); | ||
| 82 | } | ||
| 83 | |||
| 84 | static void idma32_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst) | ||
| 85 | { | ||
| 86 | *maxburst = *maxburst > 1 ? fls(*maxburst) - 1 : 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void idma32_set_device_name(struct dw_dma *dw, int id) | ||
| 90 | { | ||
| 91 | snprintf(dw->name, sizeof(dw->name), "idma32:dmac%d", id); | ||
| 92 | } | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Program FIFO size of channels. | ||
| 96 | * | ||
| 97 | * By default full FIFO (512 bytes) is assigned to channel 0. Here we | ||
| 98 | * slice FIFO on equal parts between channels. | ||
| 99 | */ | ||
| 100 | static void idma32_fifo_partition(struct dw_dma *dw) | ||
| 101 | { | ||
| 102 | u64 value = IDMA32C_FP_PSIZE_CH0(64) | IDMA32C_FP_PSIZE_CH1(64) | | ||
| 103 | IDMA32C_FP_UPDATE; | ||
| 104 | u64 fifo_partition = 0; | ||
| 105 | |||
| 106 | /* Fill FIFO_PARTITION low bits (Channels 0..1, 4..5) */ | ||
| 107 | fifo_partition |= value << 0; | ||
| 108 | |||
| 109 | /* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */ | ||
| 110 | fifo_partition |= value << 32; | ||
| 111 | |||
| 112 | /* Program FIFO Partition registers - 64 bytes per channel */ | ||
| 113 | idma32_writeq(dw, FIFO_PARTITION1, fifo_partition); | ||
| 114 | idma32_writeq(dw, FIFO_PARTITION0, fifo_partition); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void idma32_disable(struct dw_dma *dw) | ||
| 118 | { | ||
| 119 | do_dw_dma_off(dw); | ||
| 120 | idma32_fifo_partition(dw); | ||
| 121 | } | ||
| 122 | |||
| 123 | static void idma32_enable(struct dw_dma *dw) | ||
| 124 | { | ||
| 125 | idma32_fifo_partition(dw); | ||
| 126 | do_dw_dma_on(dw); | ||
| 127 | } | ||
| 128 | |||
| 129 | int idma32_dma_probe(struct dw_dma_chip *chip) | ||
| 130 | { | ||
| 131 | struct dw_dma *dw; | ||
| 132 | |||
| 133 | dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL); | ||
| 134 | if (!dw) | ||
| 135 | return -ENOMEM; | ||
| 136 | |||
| 137 | /* Channel operations */ | ||
| 138 | dw->initialize_chan = idma32_initialize_chan; | ||
| 139 | dw->suspend_chan = idma32_suspend_chan; | ||
| 140 | dw->resume_chan = idma32_resume_chan; | ||
| 141 | dw->prepare_ctllo = idma32_prepare_ctllo; | ||
| 142 | dw->encode_maxburst = idma32_encode_maxburst; | ||
| 143 | dw->bytes2block = idma32_bytes2block; | ||
| 144 | dw->block2bytes = idma32_block2bytes; | ||
| 145 | |||
| 146 | /* Device operations */ | ||
| 147 | dw->set_device_name = idma32_set_device_name; | ||
| 148 | dw->disable = idma32_disable; | ||
| 149 | dw->enable = idma32_enable; | ||
| 150 | |||
| 151 | chip->dw = dw; | ||
| 152 | return do_dma_probe(chip); | ||
| 153 | } | ||
| 154 | EXPORT_SYMBOL_GPL(idma32_dma_probe); | ||
| 155 | |||
| 156 | int idma32_dma_remove(struct dw_dma_chip *chip) | ||
| 157 | { | ||
| 158 | return do_dma_remove(chip); | ||
| 159 | } | ||
| 160 | EXPORT_SYMBOL_GPL(idma32_dma_remove); | ||
diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h index 41439732ff6b..1dd7a4e6dd23 100644 --- a/drivers/dma/dw/internal.h +++ b/drivers/dma/dw/internal.h | |||
| @@ -1,11 +1,8 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Driver for the Synopsys DesignWare DMA Controller | 3 | * Driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2013 Intel Corporation | 5 | * Copyright (C) 2013 Intel Corporation |
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | 6 | */ |
| 10 | 7 | ||
| 11 | #ifndef _DMA_DW_INTERNAL_H | 8 | #ifndef _DMA_DW_INTERNAL_H |
| @@ -15,8 +12,14 @@ | |||
| 15 | 12 | ||
| 16 | #include "regs.h" | 13 | #include "regs.h" |
| 17 | 14 | ||
| 18 | int dw_dma_disable(struct dw_dma_chip *chip); | 15 | int do_dma_probe(struct dw_dma_chip *chip); |
| 19 | int dw_dma_enable(struct dw_dma_chip *chip); | 16 | int do_dma_remove(struct dw_dma_chip *chip); |
| 17 | |||
| 18 | void do_dw_dma_on(struct dw_dma *dw); | ||
| 19 | void do_dw_dma_off(struct dw_dma *dw); | ||
| 20 | |||
| 21 | int do_dw_dma_disable(struct dw_dma_chip *chip); | ||
| 22 | int do_dw_dma_enable(struct dw_dma_chip *chip); | ||
| 20 | 23 | ||
| 21 | extern bool dw_dma_filter(struct dma_chan *chan, void *param); | 24 | extern bool dw_dma_filter(struct dma_chan *chan, void *param); |
| 22 | 25 | ||
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index 7778ed705a1a..e79a75db0852 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c | |||
| @@ -1,12 +1,9 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * PCI driver for the Synopsys DesignWare DMA Controller | 3 | * PCI driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2013 Intel Corporation | 5 | * Copyright (C) 2013 Intel Corporation |
| 5 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 6 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | 7 | */ |
| 11 | 8 | ||
| 12 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| @@ -15,21 +12,33 @@ | |||
| 15 | 12 | ||
| 16 | #include "internal.h" | 13 | #include "internal.h" |
| 17 | 14 | ||
| 18 | static struct dw_dma_platform_data mrfld_pdata = { | 15 | struct dw_dma_pci_data { |
| 16 | const struct dw_dma_platform_data *pdata; | ||
| 17 | int (*probe)(struct dw_dma_chip *chip); | ||
| 18 | }; | ||
| 19 | |||
| 20 | static const struct dw_dma_pci_data dw_pci_data = { | ||
| 21 | .probe = dw_dma_probe, | ||
| 22 | }; | ||
| 23 | |||
| 24 | static const struct dw_dma_platform_data idma32_pdata = { | ||
| 19 | .nr_channels = 8, | 25 | .nr_channels = 8, |
| 20 | .is_private = true, | ||
| 21 | .is_memcpy = true, | ||
| 22 | .is_idma32 = true, | ||
| 23 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, | 26 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, |
| 24 | .chan_priority = CHAN_PRIORITY_ASCENDING, | 27 | .chan_priority = CHAN_PRIORITY_ASCENDING, |
| 25 | .block_size = 131071, | 28 | .block_size = 131071, |
| 26 | .nr_masters = 1, | 29 | .nr_masters = 1, |
| 27 | .data_width = {4}, | 30 | .data_width = {4}, |
| 31 | .multi_block = {1, 1, 1, 1, 1, 1, 1, 1}, | ||
| 32 | }; | ||
| 33 | |||
| 34 | static const struct dw_dma_pci_data idma32_pci_data = { | ||
| 35 | .pdata = &idma32_pdata, | ||
| 36 | .probe = idma32_dma_probe, | ||
| 28 | }; | 37 | }; |
| 29 | 38 | ||
| 30 | static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | 39 | static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) |
| 31 | { | 40 | { |
| 32 | const struct dw_dma_platform_data *pdata = (void *)pid->driver_data; | 41 | const struct dw_dma_pci_data *data = (void *)pid->driver_data; |
| 33 | struct dw_dma_chip *chip; | 42 | struct dw_dma_chip *chip; |
| 34 | int ret; | 43 | int ret; |
| 35 | 44 | ||
| @@ -62,9 +71,9 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 62 | chip->id = pdev->devfn; | 71 | chip->id = pdev->devfn; |
| 63 | chip->regs = pcim_iomap_table(pdev)[0]; | 72 | chip->regs = pcim_iomap_table(pdev)[0]; |
| 64 | chip->irq = pdev->irq; | 73 | chip->irq = pdev->irq; |
| 65 | chip->pdata = pdata; | 74 | chip->pdata = data->pdata; |
| 66 | 75 | ||
| 67 | ret = dw_dma_probe(chip); | 76 | ret = data->probe(chip); |
| 68 | if (ret) | 77 | if (ret) |
| 69 | return ret; | 78 | return ret; |
| 70 | 79 | ||
| @@ -90,7 +99,7 @@ static int dw_pci_suspend_late(struct device *dev) | |||
| 90 | struct pci_dev *pci = to_pci_dev(dev); | 99 | struct pci_dev *pci = to_pci_dev(dev); |
| 91 | struct dw_dma_chip *chip = pci_get_drvdata(pci); | 100 | struct dw_dma_chip *chip = pci_get_drvdata(pci); |
| 92 | 101 | ||
| 93 | return dw_dma_disable(chip); | 102 | return do_dw_dma_disable(chip); |
| 94 | }; | 103 | }; |
| 95 | 104 | ||
| 96 | static int dw_pci_resume_early(struct device *dev) | 105 | static int dw_pci_resume_early(struct device *dev) |
| @@ -98,7 +107,7 @@ static int dw_pci_resume_early(struct device *dev) | |||
| 98 | struct pci_dev *pci = to_pci_dev(dev); | 107 | struct pci_dev *pci = to_pci_dev(dev); |
| 99 | struct dw_dma_chip *chip = pci_get_drvdata(pci); | 108 | struct dw_dma_chip *chip = pci_get_drvdata(pci); |
| 100 | 109 | ||
| 101 | return dw_dma_enable(chip); | 110 | return do_dw_dma_enable(chip); |
| 102 | }; | 111 | }; |
| 103 | 112 | ||
| 104 | #endif /* CONFIG_PM_SLEEP */ | 113 | #endif /* CONFIG_PM_SLEEP */ |
| @@ -109,24 +118,24 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = { | |||
| 109 | 118 | ||
| 110 | static const struct pci_device_id dw_pci_id_table[] = { | 119 | static const struct pci_device_id dw_pci_id_table[] = { |
| 111 | /* Medfield (GPDMA) */ | 120 | /* Medfield (GPDMA) */ |
| 112 | { PCI_VDEVICE(INTEL, 0x0827) }, | 121 | { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_data }, |
| 113 | 122 | ||
| 114 | /* BayTrail */ | 123 | /* BayTrail */ |
| 115 | { PCI_VDEVICE(INTEL, 0x0f06) }, | 124 | { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_data }, |
| 116 | { PCI_VDEVICE(INTEL, 0x0f40) }, | 125 | { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_data }, |
| 117 | 126 | ||
| 118 | /* Merrifield iDMA 32-bit (GPDMA) */ | 127 | /* Merrifield */ |
| 119 | { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&mrfld_pdata }, | 128 | { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&idma32_pci_data }, |
| 120 | 129 | ||
| 121 | /* Braswell */ | 130 | /* Braswell */ |
| 122 | { PCI_VDEVICE(INTEL, 0x2286) }, | 131 | { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_data }, |
| 123 | { PCI_VDEVICE(INTEL, 0x22c0) }, | 132 | { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_data }, |
| 124 | 133 | ||
| 125 | /* Haswell */ | 134 | /* Haswell */ |
| 126 | { PCI_VDEVICE(INTEL, 0x9c60) }, | 135 | { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_data }, |
| 127 | 136 | ||
| 128 | /* Broadwell */ | 137 | /* Broadwell */ |
| 129 | { PCI_VDEVICE(INTEL, 0x9ce0) }, | 138 | { PCI_VDEVICE(INTEL, 0x9ce0), (kernel_ulong_t)&dw_pci_data }, |
| 130 | 139 | ||
| 131 | { } | 140 | { } |
| 132 | }; | 141 | }; |
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 31ff8113c3de..382dfd9e9600 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Platform driver for the Synopsys DesignWare DMA Controller | 3 | * Platform driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| @@ -6,10 +7,6 @@ | |||
| 6 | * Copyright (C) 2013 Intel Corporation | 7 | * Copyright (C) 2013 Intel Corporation |
| 7 | * | 8 | * |
| 8 | * Some parts of this driver are derived from the original dw_dmac. | 9 | * Some parts of this driver are derived from the original dw_dmac. |
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | 10 | */ |
| 14 | 11 | ||
| 15 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| @@ -128,15 +125,6 @@ dw_dma_parse_dt(struct platform_device *pdev) | |||
| 128 | pdata->nr_masters = nr_masters; | 125 | pdata->nr_masters = nr_masters; |
| 129 | pdata->nr_channels = nr_channels; | 126 | pdata->nr_channels = nr_channels; |
| 130 | 127 | ||
| 131 | if (of_property_read_bool(np, "is_private")) | ||
| 132 | pdata->is_private = true; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * All known devices, which use DT for configuration, support | ||
| 136 | * memory-to-memory transfers. So enable it by default. | ||
| 137 | */ | ||
| 138 | pdata->is_memcpy = true; | ||
| 139 | |||
| 140 | if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) | 128 | if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) |
| 141 | pdata->chan_allocation_order = (unsigned char)tmp; | 129 | pdata->chan_allocation_order = (unsigned char)tmp; |
| 142 | 130 | ||
| @@ -264,7 +252,7 @@ static void dw_shutdown(struct platform_device *pdev) | |||
| 264 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | 252 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); |
| 265 | 253 | ||
| 266 | /* | 254 | /* |
| 267 | * We have to call dw_dma_disable() to stop any ongoing transfer. On | 255 | * We have to call do_dw_dma_disable() to stop any ongoing transfer. On |
| 268 | * some platforms we can't do that since DMA device is powered off. | 256 | * some platforms we can't do that since DMA device is powered off. |
| 269 | * Moreover we have no possibility to check if the platform is affected | 257 | * Moreover we have no possibility to check if the platform is affected |
| 270 | * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put() | 258 | * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put() |
| @@ -273,7 +261,7 @@ static void dw_shutdown(struct platform_device *pdev) | |||
| 273 | * used by the driver. | 261 | * used by the driver. |
| 274 | */ | 262 | */ |
| 275 | pm_runtime_get_sync(chip->dev); | 263 | pm_runtime_get_sync(chip->dev); |
| 276 | dw_dma_disable(chip); | 264 | do_dw_dma_disable(chip); |
| 277 | pm_runtime_put_sync_suspend(chip->dev); | 265 | pm_runtime_put_sync_suspend(chip->dev); |
| 278 | 266 | ||
| 279 | clk_disable_unprepare(chip->clk); | 267 | clk_disable_unprepare(chip->clk); |
| @@ -303,7 +291,7 @@ static int dw_suspend_late(struct device *dev) | |||
| 303 | { | 291 | { |
| 304 | struct dw_dma_chip *chip = dev_get_drvdata(dev); | 292 | struct dw_dma_chip *chip = dev_get_drvdata(dev); |
| 305 | 293 | ||
| 306 | dw_dma_disable(chip); | 294 | do_dw_dma_disable(chip); |
| 307 | clk_disable_unprepare(chip->clk); | 295 | clk_disable_unprepare(chip->clk); |
| 308 | 296 | ||
| 309 | return 0; | 297 | return 0; |
| @@ -318,7 +306,7 @@ static int dw_resume_early(struct device *dev) | |||
| 318 | if (ret) | 306 | if (ret) |
| 319 | return ret; | 307 | return ret; |
| 320 | 308 | ||
| 321 | return dw_dma_enable(chip); | 309 | return do_dw_dma_enable(chip); |
| 322 | } | 310 | } |
| 323 | 311 | ||
| 324 | #endif /* CONFIG_PM_SLEEP */ | 312 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 646c9c960c07..3fce66ecee7a 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h | |||
| @@ -1,13 +1,10 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Driver for the Synopsys DesignWare AHB DMA Controller | 3 | * Driver for the Synopsys DesignWare AHB DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2005-2007 Atmel Corporation | 5 | * Copyright (C) 2005-2007 Atmel Corporation |
| 5 | * Copyright (C) 2010-2011 ST Microelectronics | 6 | * Copyright (C) 2010-2011 ST Microelectronics |
| 6 | * Copyright (C) 2016 Intel Corporation | 7 | * Copyright (C) 2016 Intel Corporation |
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | 8 | */ |
| 12 | 9 | ||
| 13 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| @@ -222,6 +219,16 @@ enum dw_dma_msize { | |||
| 222 | 219 | ||
| 223 | /* iDMA 32-bit support */ | 220 | /* iDMA 32-bit support */ |
| 224 | 221 | ||
| 222 | /* bursts size */ | ||
| 223 | enum idma32_msize { | ||
| 224 | IDMA32_MSIZE_1, | ||
| 225 | IDMA32_MSIZE_2, | ||
| 226 | IDMA32_MSIZE_4, | ||
| 227 | IDMA32_MSIZE_8, | ||
| 228 | IDMA32_MSIZE_16, | ||
| 229 | IDMA32_MSIZE_32, | ||
| 230 | }; | ||
| 231 | |||
| 225 | /* Bitfields in CTL_HI */ | 232 | /* Bitfields in CTL_HI */ |
| 226 | #define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0) | 233 | #define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0) |
| 227 | #define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK) | 234 | #define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK) |
| @@ -312,6 +319,21 @@ struct dw_dma { | |||
| 312 | u8 all_chan_mask; | 319 | u8 all_chan_mask; |
| 313 | u8 in_use; | 320 | u8 in_use; |
| 314 | 321 | ||
| 322 | /* Channel operations */ | ||
| 323 | void (*initialize_chan)(struct dw_dma_chan *dwc); | ||
| 324 | void (*suspend_chan)(struct dw_dma_chan *dwc, bool drain); | ||
| 325 | void (*resume_chan)(struct dw_dma_chan *dwc, bool drain); | ||
| 326 | u32 (*prepare_ctllo)(struct dw_dma_chan *dwc); | ||
| 327 | void (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst); | ||
| 328 | u32 (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes, | ||
| 329 | unsigned int width, size_t *len); | ||
| 330 | size_t (*block2bytes)(struct dw_dma_chan *dwc, u32 block, u32 width); | ||
| 331 | |||
| 332 | /* Device operations */ | ||
| 333 | void (*set_device_name)(struct dw_dma *dw, int id); | ||
| 334 | void (*disable)(struct dw_dma *dw); | ||
| 335 | void (*enable)(struct dw_dma *dw); | ||
| 336 | |||
| 315 | /* platform data */ | 337 | /* platform data */ |
| 316 | struct dw_dma_platform_data *pdata; | 338 | struct dw_dma_platform_data *pdata; |
| 317 | }; | 339 | }; |
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 98dbc796353f..53ca9ba6ab4b 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c | |||
| @@ -153,7 +153,6 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port) | |||
| 153 | #ifdef CONFIG_SERIAL_8250_DMA | 153 | #ifdef CONFIG_SERIAL_8250_DMA |
| 154 | static const struct dw_dma_platform_data qrk_serial_dma_pdata = { | 154 | static const struct dw_dma_platform_data qrk_serial_dma_pdata = { |
| 155 | .nr_channels = 2, | 155 | .nr_channels = 2, |
| 156 | .is_private = true, | ||
| 157 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, | 156 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, |
| 158 | .chan_priority = CHAN_PRIORITY_ASCENDING, | 157 | .chan_priority = CHAN_PRIORITY_ASCENDING, |
| 159 | .block_size = 4095, | 158 | .block_size = 4095, |
diff --git a/include/linux/dma/dw.h b/include/linux/dma/dw.h index e166cac8e870..9752f3745f76 100644 --- a/include/linux/dma/dw.h +++ b/include/linux/dma/dw.h | |||
| @@ -1,13 +1,10 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Driver for the Synopsys DesignWare DMA Controller | 3 | * Driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2007 Atmel Corporation | 5 | * Copyright (C) 2007 Atmel Corporation |
| 5 | * Copyright (C) 2010-2011 ST Microelectronics | 6 | * Copyright (C) 2010-2011 ST Microelectronics |
| 6 | * Copyright (C) 2014 Intel Corporation | 7 | * Copyright (C) 2014 Intel Corporation |
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | 8 | */ |
| 12 | #ifndef _DMA_DW_H | 9 | #ifndef _DMA_DW_H |
| 13 | #define _DMA_DW_H | 10 | #define _DMA_DW_H |
| @@ -45,9 +42,13 @@ struct dw_dma_chip { | |||
| 45 | #if IS_ENABLED(CONFIG_DW_DMAC_CORE) | 42 | #if IS_ENABLED(CONFIG_DW_DMAC_CORE) |
| 46 | int dw_dma_probe(struct dw_dma_chip *chip); | 43 | int dw_dma_probe(struct dw_dma_chip *chip); |
| 47 | int dw_dma_remove(struct dw_dma_chip *chip); | 44 | int dw_dma_remove(struct dw_dma_chip *chip); |
| 45 | int idma32_dma_probe(struct dw_dma_chip *chip); | ||
| 46 | int idma32_dma_remove(struct dw_dma_chip *chip); | ||
| 48 | #else | 47 | #else |
| 49 | static inline int dw_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; } | 48 | static inline int dw_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; } |
| 50 | static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; } | 49 | static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; } |
| 50 | static inline int idma32_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; } | ||
| 51 | static inline int idma32_dma_remove(struct dw_dma_chip *chip) { return 0; } | ||
| 51 | #endif /* CONFIG_DW_DMAC_CORE */ | 52 | #endif /* CONFIG_DW_DMAC_CORE */ |
| 52 | 53 | ||
| 53 | #endif /* _DMA_DW_H */ | 54 | #endif /* _DMA_DW_H */ |
diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h index 1a1d58ebffbf..f3eaf9ec00a1 100644 --- a/include/linux/platform_data/dma-dw.h +++ b/include/linux/platform_data/dma-dw.h | |||
| @@ -1,12 +1,9 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Driver for the Synopsys DesignWare DMA Controller | 3 | * Driver for the Synopsys DesignWare DMA Controller |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2007 Atmel Corporation | 5 | * Copyright (C) 2007 Atmel Corporation |
| 5 | * Copyright (C) 2010-2011 ST Microelectronics | 6 | * Copyright (C) 2010-2011 ST Microelectronics |
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | 7 | */ |
| 11 | #ifndef _PLATFORM_DATA_DMA_DW_H | 8 | #ifndef _PLATFORM_DATA_DMA_DW_H |
| 12 | #define _PLATFORM_DATA_DMA_DW_H | 9 | #define _PLATFORM_DATA_DMA_DW_H |
| @@ -38,10 +35,6 @@ struct dw_dma_slave { | |||
| 38 | /** | 35 | /** |
| 39 | * struct dw_dma_platform_data - Controller configuration parameters | 36 | * struct dw_dma_platform_data - Controller configuration parameters |
| 40 | * @nr_channels: Number of channels supported by hardware (max 8) | 37 | * @nr_channels: Number of channels supported by hardware (max 8) |
| 41 | * @is_private: The device channels should be marked as private and not for | ||
| 42 | * by the general purpose DMA channel allocator. | ||
| 43 | * @is_memcpy: The device channels do support memory-to-memory transfers. | ||
| 44 | * @is_idma32: The type of the DMA controller is iDMA32 | ||
| 45 | * @chan_allocation_order: Allocate channels starting from 0 or 7 | 38 | * @chan_allocation_order: Allocate channels starting from 0 or 7 |
| 46 | * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. | 39 | * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. |
| 47 | * @block_size: Maximum block size supported by the controller | 40 | * @block_size: Maximum block size supported by the controller |
| @@ -53,9 +46,6 @@ struct dw_dma_slave { | |||
| 53 | */ | 46 | */ |
| 54 | struct dw_dma_platform_data { | 47 | struct dw_dma_platform_data { |
| 55 | unsigned int nr_channels; | 48 | unsigned int nr_channels; |
| 56 | bool is_private; | ||
| 57 | bool is_memcpy; | ||
| 58 | bool is_idma32; | ||
| 59 | #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ | 49 | #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ |
| 60 | #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ | 50 | #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ |
| 61 | unsigned char chan_allocation_order; | 51 | unsigned char chan_allocation_order; |
