dmaengine: dw: Split DW and iDMA 32-bit operations
PATCH 3/5 dmaengine: dw: Split DW and iDMA 32-bit operations
Quoted 7 lines · Andy Shevchenko
Here is a kinda big refactoring that should have been done in the first place, when Intel iDMA 32-bit support appeared.
It splits operations which are different to Synopsys DesignWare and Intel iDMA 32-bit controllers.
No functional change intended.
While first two are real bug fixes and really small, this one bigger and suddenly has a typo which I didn't notice during my tests.
Vinod, please, consider applying first two until I will come with better this one and might be something more.
Quoted 889 lines
Signed-off-by Andy Shevchenko <[email protected]>--- drivers/dma/dw/Makefile | 2 +- drivers/dma/dw/core.c | 188 +++++---------------------- drivers/dma/dw/dw.c | 109 ++++++++++++++++ drivers/dma/dw/idma32.c | 137 +++++++++++++++++++ drivers/dma/dw/internal.h | 10 +- drivers/dma/dw/pci.c | 45 ++++--- drivers/dma/dw/platform.c | 8 +- drivers/dma/dw/regs.h | 13 ++ include/linux/dma/dw.h | 4 + include/linux/platform_data/dma-dw.h | 2 - 10 files changed, 339 insertions(+), 179 deletions(-) create mode 100644 drivers/dma/dw/dw.c create mode 100644 drivers/dma/dw/idma32.cdrivers/dma/dw/Makefile +1
-1@@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_DMAC_CORE) += dw_dmac_core.o -dw_dmac_core-objs := core.o +dw_dmac_core-objs := core.o dw.o idma32.o obj-$(CONFIG_DW_DMAC) += dw_dmac.o dw_dmac-objs := platform.odrivers/dma/dw/core.c +34
-154@@ -138,42 +138,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) dwc->descs_allocated--; } -static void dwc_initialize_chan_idma32 (struct dw_dma_chan *dwc) -{ -u32 cfghi =0 ; -u32 cfglo =0 ; - -/* Set default burst alignment */ - cfglo |=IDMA32C_CFGL_DST_BURST_ALIGN |IDMA32C_CFGL_SRC_BURST_ALIGN ; - -/* Low 4 bits of the request lines */ - cfghi |=IDMA32C_CFGH_DST_PER (dwc->dws.dst_id &0xf ); - cfghi |=IDMA32C_CFGH_SRC_PER (dwc->dws.src_id &0xf ); - -/* Request line extension (2 bits) */ - cfghi |=IDMA32C_CFGH_DST_PER_EXT (dwc->dws.dst_id >>4 &0x3 ); - cfghi |=IDMA32C_CFGH_SRC_PER_EXT (dwc->dws.src_id >>4 &0x3 ); - -channel_writel (dwc,CFG_LO , cfglo); -channel_writel (dwc,CFG_HI , cfghi); -} - -static void dwc_initialize_chan_dw (struct dw_dma_chan *dwc) -{ -u32 cfghi =DWC_CFGH_FIFO_MODE ; -u32 cfglo =DWC_CFGL_CH_PRIOR (dwc->priority); -bool hs_polarity = dwc->dws.hs_polarity; - - cfghi |=DWC_CFGH_DST_PER (dwc->dws.dst_id); - cfghi |=DWC_CFGH_SRC_PER (dwc->dws.src_id); - -/* Set polarity of handshake interface */ - cfglo |= hs_polarity ?DWC_CFGL_HS_DST_POL |DWC_CFGL_HS_SRC_POL :0 ; - -channel_writel (dwc,CFG_LO , cfglo); -channel_writel (dwc,CFG_HI , cfghi); -} -static void dwc_initialize (struct dw_dma_chan *dwc) {struct dw_dma *dw =to_dw_dma (dwc->chan.device);@@ -181,10 +145,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)if (test_bit (DW_DMA_IS_INITIALIZED , &dwc->flags))return ; -if (dw->pdata->is_idma32) -dwc_initialize_chan_idma32 (dwc); -else -dwc_initialize_chan_dw (dwc); + dw->initialize_chan (dwc);/* Enable interrupts */ channel_set_bit (dw,MASK .XFER, dwc->mask);@@ -213,37 +174,6 @@ static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc)cpu_relax (); } -static u32 bytes2block (struct dw_dma_chan *dwc,size_t bytes, -unsigned int width,size_t *len) -{ -struct dw_dma *dw =to_dw_dma (dwc->chan.device); -u32 block; - -/* Always in bytes for iDMA 32-bit */ -if (dw->pdata->is_idma32) - width =0 ; - -if ((bytes >> width) > dwc->block_size) { - block = dwc->block_size; - *len = block << width; - }else { - block = bytes >> width; - *len = bytes; - } - -return block; -} - -static size_t block2bytes (struct dw_dma_chan *dwc,u32 block,u32 width) -{ -struct dw_dma *dw =to_dw_dma (dwc->chan.device); - -if (dw->pdata->is_idma32) -return IDMA32C_CTLH_BLOCK_TS (block); - -return DWC_CTLH_BLOCK_TS (block) << width; -} -/*----------------------------------------------------------------------*/ /* Perform single block transfer */ @@ -389,10 +319,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)/* Returns how many bytes were already received from source */ static inline u32 dwc_get_sent (struct dw_dma_chan *dwc) { +struct dw_dma *dw =to_dw_dma (dwc->chan.device);u32 ctlhi =channel_readl (dwc,CTL_HI );u32 ctllo =channel_readl (dwc,CTL_LO ); -return block2bytes (dwc, ctlhi, ctllo >>4 &7 ); +return dw->block2bytes (dwc, ctlhi, ctllo >>4 &7 ); }static void dwc_scan_descriptors (struct dw_dma *dw,struct dw_dma_chan *dwc)@@ -649,7 +580,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,unsigned int src_width;unsigned int dst_width;unsigned int data_width = dw->pdata->data_width[m_master]; -u32 ctllo; +u32 ctllo, ctlhi;u8 lms =DWC_LLP_LMS (m_master); dev_vdbg(chan2dev(chan),@@ -678,10 +609,12 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,if (!desc) goto err_desc_get; + ctlhi = dw->bytes2block (dwc, len - offset, src_width, &xfer_count); +lli_write (desc, sar, src + offset);lli_write (desc, dar, dest + offset);lli_write (desc, ctllo, ctllo); -lli_write (desc, ctlhi,bytes2block (dwc, len - offset, src_width, &xfer_count)); +lli_write (desc, ctlhi, ctlhi); desc->len = xfer_count;if (!first) {@@ -719,7 +652,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,struct dma_slave_config *sconfig = &dwc->dma_sconfig;struct dw_desc *prev;struct dw_desc *first; -u32 ctllo; +u32 ctllo, ctlhi;u8 m_master = dwc->dws.m_master;u8 lms =DWC_LLP_LMS (m_master);dma_addr_t reg;@@ -766,9 +699,11 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,if (!desc) goto err_desc_get; + ctlhi = dw->bytes2block (dwc, len, mem_width, &dlen); +lli_write (desc, sar, mem);lli_write (desc, dar, reg); -lli_write (desc, ctlhi,bytes2block (dwc, len, mem_width, &dlen)); +lli_write (desc, ctlhi, ctlhi);lli_write (desc, ctllo, ctllo |DWC_CTLL_SRC_WIDTH (mem_width)); desc->len = dlen;@@ -812,9 +747,11 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,if (!desc) goto err_desc_get; + ctlhi = dw->bytes2block (dwc, len, reg_width, &dlen); +lli_write (desc, sar, reg);lli_write (desc, dar, mem); -lli_write (desc, ctlhi,bytes2block (dwc, len, reg_width, &dlen)); +lli_write (desc, ctlhi, ctlhi); mem_width =__ffs (data_width | mem | dlen);lli_write (desc, ctllo, ctllo |DWC_CTLL_DST_WIDTH (mem_width)); desc->len = dlen;@@ -874,22 +811,12 @@ EXPORT_SYMBOL_GPL(dw_dma_filter);static int dwc_config (struct dma_chan *chan,struct dma_slave_config *sconfig) {struct dw_dma_chan *dwc =to_dw_dma_chan (chan); -struct dma_slave_config *sc = &dwc->dma_sconfig;struct dw_dma *dw =to_dw_dma (chan->device); -/* -* Fix sconfig's burst size according to dw_dmac. We need to convert -* them as: -* 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. -* -* NOTE: burst size 2 is not supported by DesignWare controller. -* iDMA 32-bit supports it. -*/ -u32 s = dw->pdata->is_idma32 ?1 :2 ;memcpy (&dwc->dma_sconfig, sconfig,sizeof (*sconfig)); - sc->src_maxburst = sc->src_maxburst >1 ?fls (sc->src_maxburst) - s :0 ; - sc->dst_maxburst = sc->dst_maxburst >1 ?fls (sc->dst_maxburst) - s :0 ; + dw->encode_maxburst (dwc, &dwc->dma_sconfig.src_maxburst); + dw->encode_maxburst (dwc, &dwc->dma_sconfig.dst_maxburst);return 0 ; }@@ -898,16 +825,9 @@ static void dwc_chan_pause(struct dw_dma_chan *dwc, bool drain) {struct dw_dma *dw =to_dw_dma (dwc->chan.device);unsigned int count =20 ;/* timeout iterations */ -u32 cfglo; - cfglo =channel_readl (dwc,CFG_LO ); -if (dw->pdata->is_idma32) { -if (drain) - cfglo |=IDMA32C_CFGL_CH_DRAIN ; -else - cfglo &= ~IDMA32C_CFGL_CH_DRAIN ; - } -channel_writel (dwc,CFG_LO , cfglo |DWC_CFGL_CH_SUSP ); + dw->suspend_chan (dwc, drain); +while (!(channel_readl (dwc,CFG_LO ) &DWC_CFGL_FIFO_EMPTY ) && count--)udelay (2 );@@ -1056,33 +976,7 @@ static void dwc_issue_pending(struct dma_chan *chan)/*----------------------------------------------------------------------*/ -/* -* Program FIFO size of channels. -* -* By default full FIFO (512 bytes) is assigned to channel 0. Here we -* slice FIFO on equal parts between channels. -*/ -static void idma32_fifo_partition (struct dw_dma *dw) -{ -u64 value =IDMA32C_FP_PSIZE_CH0 (64 ) |IDMA32C_FP_PSIZE_CH1 (64 ) | -IDMA32C_FP_UPDATE ; -u64 fifo_partition =0 ; - -if (!dw->pdata->is_idma32) -return ; - -/* Fill FIFO_PARTITION low bits (Channels 0..1, 4..5) */ - fifo_partition |= value <<0 ; - -/* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */ - fifo_partition |= value <<32 ; - -/* Program FIFO Partition registers - 128 bytes for each channel */ -idma32_writeq (dw,FIFO_PARTITION1 , fifo_partition); -idma32_writeq (dw,FIFO_PARTITION0 , fifo_partition); -} - -static void dw_dma_off (struct dw_dma *dw) +void do_dma_off (struct dw_dma *dw) {unsigned int i;@@ -1101,7 +995,7 @@ static void dw_dma_off(struct dw_dma *dw)clear_bit (DW_DMA_IS_INITIALIZED , &dw->chan[i].flags); } -static void dw_dma_on (struct dw_dma *dw) +void do_dma_on (struct dw_dma *dw) {dma_writel (dw,CFG ,DW_CFG_DMA_EN ); }@@ -1137,7 +1031,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)/* Enable controller here if needed */ if (!dw->in_use) -dw_dma_on (dw); +do_dma_on (dw); dw->in_use |= dwc->mask;return 0 ;@@ -1175,30 +1069,25 @@ static void dwc_free_chan_resources(struct dma_chan *chan)/* Disable controller in case it was a last user */ dw->in_use &= ~dwc->mask;if (!dw->in_use) -dw_dma_off (dw); +do_dma_off (dw);dev_vdbg (chan2dev (chan),"%s: done\n" , __func__); } -int dw_dma_probe (struct dw_dma_chip *chip) +int do_dma_probe (struct dw_dma_chip *chip) { +struct dw_dma *dw = chip->dw;struct dw_dma_platform_data *pdata; -struct dw_dma *dw;bool autocfg = false;unsigned int dw_params;unsigned int i;int err; - dw =devm_kzalloc (chip->dev,sizeof (*dw),GFP_KERNEL ); -if (!dw) -return -ENOMEM ; - dw->pdata =devm_kzalloc (chip->dev,sizeof (*dw->pdata),GFP_KERNEL );if (!dw->pdata)return -ENOMEM ; dw->regs = chip->regs; - chip->dw = dw;pm_runtime_get_sync (chip->dev);@@ -1250,15 +1139,10 @@ int dw_dma_probe(struct dw_dma_chip *chip) dw->all_chan_mask = (1 << pdata->nr_channels) -1 ;/* Force dma off, just in case */ -dw_dma_off (dw); - -idma32_fifo_partition (dw); + dw->disable (dw);/* Device and instance ID for IRQ and DMA pool */ -if (pdata->is_idma32) -snprintf (dw->name,sizeof (dw->name),"idma32:dmac%d" , chip->id); -else -snprintf (dw->name,sizeof (dw->name),"dw:dmac%d" , chip->id); + dw->set_device_name (dw, chip->id);/* Create a pool of consistent memory blocks for hardware descriptors */ dw->desc_pool = dmam_pool_create(dw->name, chip->dev,@@ -1382,16 +1266,15 @@ int dw_dma_probe(struct dw_dma_chip *chip)pm_runtime_put_sync_suspend (chip->dev);return err; } -EXPORT_SYMBOL_GPL (dw_dma_probe); -int dw_dma_remove (struct dw_dma_chip *chip) +int do_dma_remove (struct dw_dma_chip *chip) {struct dw_dma *dw = chip->dw;struct dw_dma_chan *dwc, *_dwc;pm_runtime_get_sync (chip->dev); -dw_dma_off (dw); +do_dma_off (dw);dma_async_device_unregister (&dw->dma);free_irq (chip->irq, dw);@@ -1406,27 +1289,24 @@ int dw_dma_remove(struct dw_dma_chip *chip)pm_runtime_put_sync_suspend (chip->dev);return 0 ; } -EXPORT_SYMBOL_GPL (dw_dma_remove); -int dw_dma_disable (struct dw_dma_chip *chip) +int do_dw_dma_disable (struct dw_dma_chip *chip) {struct dw_dma *dw = chip->dw; -dw_dma_off (dw); + dw->disable (dw);return 0 ; } -EXPORT_SYMBOL_GPL (dw_dma_disable); +EXPORT_SYMBOL_GPL (do_dw_dma_disable); -int dw_dma_enable (struct dw_dma_chip *chip) +int do_dw_dma_enable (struct dw_dma_chip *chip) {struct dw_dma *dw = chip->dw; -idma32_fifo_partition (dw); - -dw_dma_on (dw); + dw->disable (dw);return 0 ; } -EXPORT_SYMBOL_GPL (dw_dma_enable); +EXPORT_SYMBOL_GPL (do_dw_dma_enable);MODULE_LICENSE ("GPL v2" );MODULE_DESCRIPTION ("Synopsys DesignWare DMA Controller core driver" );drivers/dma/dw/dw.c new file +109
-0@@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2007-2008 Atmel Corporation +// Copyright (C) 2010-2011 ST Microelectronics +// Copyright (C) 2013,2018 Intel Corporation + +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/slab.h> + +#include "internal.h" + +static void dw_dma_initialize_chan (struct dw_dma_chan *dwc) +{ +u32 cfghi =DWC_CFGH_FIFO_MODE ; +u32 cfglo =DWC_CFGL_CH_PRIOR (dwc->priority); +bool hs_polarity = dwc->dws.hs_polarity; + + cfghi |=DWC_CFGH_DST_PER (dwc->dws.dst_id); + cfghi |=DWC_CFGH_SRC_PER (dwc->dws.src_id); + +/* Set polarity of handshake interface */ + cfglo |= hs_polarity ?DWC_CFGL_HS_DST_POL |DWC_CFGL_HS_SRC_POL :0 ; + +channel_writel (dwc,CFG_LO , cfglo); +channel_writel (dwc,CFG_HI , cfghi); +} + +static void dw_dma_suspend_chan (struct dw_dma_chan *dwc,bool drain) +{ +u32 cfglo =channel_readl (dwc,CFG_LO ); + +channel_writel (dwc,CFG_LO , cfglo |DWC_CFGL_CH_SUSP ); +} + +static u32 dw_dma_bytes2block (struct dw_dma_chan *dwc, +size_t bytes,unsigned int width,size_t *len) +{ +u32 block; + +if ((bytes >> width) > dwc->block_size) { + block = dwc->block_size; + *len = block << width; + }else { + block = bytes >> width; + *len = bytes; + } + +return block; +} + +static size_t dw_dma_block2bytes (struct dw_dma_chan *dwc,u32 block,u32 width) +{ +return DWC_CTLH_BLOCK_TS (block) << width; +} + +static void dw_dma_encode_maxburst (struct dw_dma_chan *dwc,u32 *maxburst) +{ +/* +* Fix burst size according to dw_dmac. We need to convert them as: +* 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. +*/ + *maxburst = *maxburst >1 ?fls (*maxburst) -2 :0 ; +} + +static void dw_dma_set_device_name (struct dw_dma *dw,int id) +{ +snprintf (dw->name,sizeof (dw->name),"dw:dmac%d" , id); +} + +static void dw_dma_disable (struct dw_dma *dw) +{ +do_dma_off (dw); +} + +static void dw_dma_enable (struct dw_dma *dw) +{ +do_dma_on (dw); +} + +int dw_dma_probe (struct dw_dma_chip *chip) +{ +struct dw_dma *dw; + + dw =devm_kzalloc (chip->dev,sizeof (*dw),GFP_KERNEL ); +if (!dw) +return -ENOMEM ; + +/* Channel operations */ + dw->initialize_chan = dw_dma_initialize_chan; + dw->suspend_chan = dw_dma_suspend_chan; + dw->encode_maxburst = dw_dma_encode_maxburst; + dw->bytes2block = dw_dma_bytes2block; + dw->block2bytes = dw_dma_block2bytes; + +/* Device operations */ + dw->set_device_name = dw_dma_set_device_name; + dw->disable = dw_dma_disable; + dw->enable = dw_dma_enable; + + chip->dw = dw; +return do_dma_probe (chip); +} +EXPORT_SYMBOL_GPL (dw_dma_probe); + +int dw_dma_remove (struct dw_dma_chip *chip) +{ +return do_dma_remove (chip); +} +EXPORT_SYMBOL_GPL (dw_dma_remove);drivers/dma/dw/idma32.c new file +137
-0@@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2013,2018 Intel Corporation + +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/slab.h> + +#include "internal.h" + +static void idma32_initialize_chan (struct dw_dma_chan *dwc) +{ +u32 cfghi =0 ; +u32 cfglo =0 ; + +/* Set default burst alignment */ + cfglo |=IDMA32C_CFGL_DST_BURST_ALIGN |IDMA32C_CFGL_SRC_BURST_ALIGN ; + +/* Low 4 bits of the request lines */ + cfghi |=IDMA32C_CFGH_DST_PER (dwc->dws.dst_id &0xf ); + cfghi |=IDMA32C_CFGH_SRC_PER (dwc->dws.src_id &0xf ); + +/* Request line extension (2 bits) */ + cfghi |=IDMA32C_CFGH_DST_PER_EXT (dwc->dws.dst_id >>4 &0x3 ); + cfghi |=IDMA32C_CFGH_SRC_PER_EXT (dwc->dws.src_id >>4 &0x3 ); + +channel_writel (dwc,CFG_LO , cfglo); +channel_writel (dwc,CFG_HI , cfghi); +} + +static void idma32_suspend_chan (struct dw_dma_chan *dwc,bool drain) +{ +u32 cfglo =channel_readl (dwc,CFG_LO ); + +if (drain) + cfglo |=IDMA32C_CFGL_CH_DRAIN ; +else + cfglo &= ~IDMA32C_CFGL_CH_DRAIN ; + +channel_writel (dwc,CFG_LO , cfglo |DWC_CFGL_CH_SUSP ); +} + +static u32 idma32_bytes2block (struct dw_dma_chan *dwc, +size_t bytes,unsigned int width,size_t *len) +{ +u32 block; + +if (bytes > dwc->block_size) { + block = dwc->block_size; + *len = dwc->block_size; + }else { + block = bytes; + *len = bytes; + } + +return block; +} + +static size_t idma32_block2bytes (struct dw_dma_chan *dwc,u32 block,u32 width) +{ +return IDMA32C_CTLH_BLOCK_TS (block); +} + +static void idma32_encode_maxburst (struct dw_dma_chan *dwc,u32 *maxburst) +{ + *maxburst = *maxburst >1 ?fls (*maxburst) -1 :0 ; +} + +static void idma32_set_device_name (struct dw_dma *dw,int id) +{ +snprintf (dw->name,sizeof (dw->name),"idma32:dmac%d" , id); +} + +/* +* Program FIFO size of channels. +* +* By default full FIFO (512 bytes) is assigned to channel 0. Here we +* slice FIFO on equal parts between channels. +*/ +static void idma32_fifo_partition (struct dw_dma *dw) +{ +u64 value =IDMA32C_FP_PSIZE_CH0 (64 ) |IDMA32C_FP_PSIZE_CH1 (64 ) | +IDMA32C_FP_UPDATE ; +u64 fifo_partition =0 ; + +/* Fill FIFO_PARTITION low bits (Channels 0..1, 4..5) */ + fifo_partition |= value <<0 ; + +/* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */ + fifo_partition |= value <<32 ; + +/* Program FIFO Partition registers - 128 bytes for each channel */ +idma32_writeq (dw,FIFO_PARTITION1 , fifo_partition); +idma32_writeq (dw,FIFO_PARTITION0 , fifo_partition); +} + +static void idma32_disable (struct dw_dma *dw) +{ +do_dma_off (dw); +idma32_fifo_partition (dw); +} + +static void idma32_enable (struct dw_dma *dw) +{ +idma32_fifo_partition (dw); +do_dma_on (dw); +} + +int idma32_dma_probe (struct dw_dma_chip *chip) +{ +struct dw_dma *dw; + + dw =devm_kzalloc (chip->dev,sizeof (*dw),GFP_KERNEL ); +if (!dw) +return -ENOMEM ; + +/* Channel operations */ + dw->initialize_chan = idma32_initialize_chan; + dw->suspend_chan = idma32_suspend_chan; + dw->encode_maxburst = idma32_encode_maxburst; + dw->bytes2block = idma32_bytes2block; + dw->block2bytes = idma32_block2bytes; + +/* Device operations */ + dw->set_device_name = idma32_set_device_name; + dw->disable = idma32_disable; + dw->enable = idma32_enable; + + chip->dw = dw; +return do_dma_probe (chip); +} +EXPORT_SYMBOL_GPL (idma32_dma_probe); + +int idma32_dma_remove (struct dw_dma_chip *chip) +{ +return do_dma_remove (chip); +} +EXPORT_SYMBOL_GPL (idma32_dma_remove);drivers/dma/dw/internal.h +8
-2@@ -15,8 +15,14 @@#include "regs.h" -int dw_dma_disable (struct dw_dma_chip *chip); -int dw_dma_enable (struct dw_dma_chip *chip); +int do_dma_probe (struct dw_dma_chip *chip); +int do_dma_remove (struct dw_dma_chip *chip); + +void do_dma_on (struct dw_dma *dw); +void do_dma_off (struct dw_dma *dw); + +int do_dw_dma_disable (struct dw_dma_chip *chip); +int do_dw_dma_enable (struct dw_dma_chip *chip);extern bool dw_dma_filter (struct dma_chan *chan,void *param);drivers/dma/dw/pci.c +29
-16@@ -15,11 +15,19 @@#include "internal.h" -static struct dw_dma_platform_data mrfld_pdata = { +static struct dw_dma_pci_data { +const struct dw_dma_platform_data *pdata; +int (*probe)(struct dw_dma_chip *chip); +}; + +static const struct dw_dma_pci_data dw_pci_data = { + .probe = dw_dma_probe, +}; + +static const struct dw_dma_platform_data idma32_pdata = { .nr_channels =8 , .is_private = true, .is_memcpy = true, - .is_idma32 = true, .chan_allocation_order =CHAN_ALLOCATION_ASCENDING , .chan_priority =CHAN_PRIORITY_ASCENDING , .block_size =131071 ,@@ -28,9 +36,14 @@ static struct dw_dma_platform_data mrfld_pdata = { .multi_block = {true, true, true, true, true, true, true, true}, }; +static const struct dw_dma_pci_data idma32_pci_data = { + .pdata = &idma32_pdata, + .probe = idma32_dma_probe, +}; +static int dw_pci_probe (struct pci_dev *pdev,const struct pci_device_id *pid) { -const struct dw_dma_platform_data *pdata = (void *)pid->driver_data; +const struct dw_dma_pci_data *data = (void *)pid->driver_data;struct dw_dma_chip *chip;int ret;@@ -63,9 +76,9 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) chip->id = pdev->devfn; chip->regs =pcim_iomap_table (pdev)[0 ]; chip->irq = pdev->irq; - chip->pdata = pdata; + chip->pdata = data->pdata; - ret =dw_dma_probe (chip); + ret = data->probe (chip);if (ret)return ret;@@ -91,7 +104,7 @@ static int dw_pci_suspend_late(struct device *dev)struct pci_dev *pci =to_pci_dev (dev);struct dw_dma_chip *chip =pci_get_drvdata (pci); -return dw_dma_disable (chip); +return do_dw_dma_disable (chip); };static int dw_pci_resume_early (struct device *dev)@@ -99,7 +112,7 @@ static int dw_pci_resume_early(struct device *dev)struct pci_dev *pci =to_pci_dev (dev);struct dw_dma_chip *chip =pci_get_drvdata (pci); - return dw_dma_enable(chip); + return do_dw_dma_enable(chip); };#endif /* CONFIG_PM_SLEEP */ @@ -110,24 +123,24 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = {static const struct pci_device_id dw_pci_id_table[] = {/* Medfield (GPDMA) */ - {PCI_VDEVICE (INTEL ,0x0827 ) }, + {PCI_VDEVICE (INTEL ,0x0827 ), (kernel_ulong_t)&dw_pci_data },/* BayTrail */ - {PCI_VDEVICE (INTEL ,0x0f06 ) }, - {PCI_VDEVICE (INTEL ,0x0f40 ) }, + {PCI_VDEVICE (INTEL ,0x0f06 ), (kernel_ulong_t)&dw_pci_data }, + {PCI_VDEVICE (INTEL ,0x0f40 ), (kernel_ulong_t)&dw_pci_data }, -/* Merrifield iDMA 32-bit (GPDMA) */ - {PCI_VDEVICE (INTEL ,0x11a2 ), (kernel_ulong_t)&mrfld_pdata }, +/* Merrifield */ + {PCI_VDEVICE (INTEL ,0x11a2 ), (kernel_ulong_t)&idma32_pci_data },/* Braswell */ - {PCI_VDEVICE (INTEL ,0x2286 ) }, - {PCI_VDEVICE (INTEL ,0x22c0 ) }, + {PCI_VDEVICE (INTEL ,0x2286 ), (kernel_ulong_t)&dw_pci_data }, + {PCI_VDEVICE (INTEL ,0x22c0 ), (kernel_ulong_t)&dw_pci_data },/* Haswell */ - {PCI_VDEVICE (INTEL ,0x9c60 ) }, + {PCI_VDEVICE (INTEL ,0x9c60 ), (kernel_ulong_t)&dw_pci_data },/* Broadwell */ - {PCI_VDEVICE (INTEL ,0x9ce0 ) }, + {PCI_VDEVICE (INTEL ,0x9ce0 ), (kernel_ulong_t)&dw_pci_data }, { } };drivers/dma/dw/platform.c +4
-4@@ -258,7 +258,7 @@ static void dw_shutdown(struct platform_device *pdev)struct dw_dma_chip *chip =platform_get_drvdata (pdev);/* -* We have to call dw_dma_disable() to stop any ongoing transfer. On +* We have to call do_dw_dma_disable() to stop any ongoing transfer. On * some platforms we can't do that since DMA device is powered off. * Moreover we have no possibility to check if the platform is affected * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put() @@ -267,7 +267,7 @@ static void dw_shutdown(struct platform_device *pdev)* used by the driver. */ pm_runtime_get_sync (chip->dev); -dw_dma_disable (chip); +do_dw_dma_disable (chip);pm_runtime_put_sync_suspend (chip->dev);clk_disable_unprepare (chip->clk);@@ -297,7 +297,7 @@ static int dw_suspend_late(struct device *dev) {struct dw_dma_chip *chip =dev_get_drvdata (dev); -dw_dma_disable (chip); +do_dw_dma_disable (chip);clk_disable_unprepare (chip->clk);return 0 ;@@ -312,7 +312,7 @@ static int dw_resume_early(struct device *dev)if (ret)return ret; - return dw_dma_enable(chip); + return do_dw_dma_enable(chip); }#endif /* CONFIG_PM_SLEEP */ drivers/dma/dw/regs.h +13
-0@@ -308,6 +308,19 @@ struct dw_dma {u8 all_chan_mask;u8 in_use; +/* Channel operations */ +void (*initialize_chan)(struct dw_dma_chan *dwc); +void (*suspend_chan)(struct dw_dma_chan *dwc,bool drain); +void (*encode_maxburst)(struct dw_dma_chan *dwc,u32 *maxburst); +u32 (*bytes2block)(struct dw_dma_chan *dwc,size_t bytes, +unsigned int width,size_t *len); +size_t (*block2bytes)(struct dw_dma_chan *dwc,u32 block,u32 width); + +/* Device operations */ +void (*set_device_name)(struct dw_dma *dw,int id); +void (*disable)(struct dw_dma *dw); +void (*enable)(struct dw_dma *dw); +/* platform data */ struct dw_dma_platform_data *pdata; };include/linux/dma/dw.h +4
-0@@ -45,9 +45,13 @@ struct dw_dma_chip {#if IS_ENABLED (CONFIG_DW_DMAC_CORE )int dw_dma_probe (struct dw_dma_chip *chip);int dw_dma_remove (struct dw_dma_chip *chip); +int idma32_dma_probe (struct dw_dma_chip *chip); +int idma32_dma_remove (struct dw_dma_chip *chip);#else static inline int dw_dma_probe (struct dw_dma_chip *chip) {return -ENODEV ; }static inline int dw_dma_remove (struct dw_dma_chip *chip) {return 0 ; } +static inline int idma32_dma_probe (struct dw_dma_chip *chip) {return -ENODEV ; } +static inline int idma32_dma_remove (struct dw_dma_chip *chip) {return 0 ; }#endif /* CONFIG_DW_DMAC_CORE */ #endif /* _DMA_DW_H */ include/linux/platform_data/dma-dw.h +0
-2@@ -41,7 +41,6 @@ struct dw_dma_slave {* @is_private: The device channels should be marked as private and not for * by the general purpose DMA channel allocator. * @is_memcpy: The device channels do support memory-to-memory transfers. -* @is_idma32: The type of the DMA controller is iDMA32 * @chan_allocation_order: Allocate channels starting from 0 or 7 * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. * @block_size: Maximum block size supported by the controller @@ -54,7 +53,6 @@ struct dw_dma_platform_data {unsigned int nr_channels;bool is_private;bool is_memcpy; -bool is_idma32;#define CHAN_ALLOCATION_ASCENDING 0/* zero to seven */ #define CHAN_ALLOCATION_DESCENDING 1/* seven to zero */ unsigned char chan_allocation_order;Signature · 1 line
2.19.2