From 49920bc66984a512f4bcc7735a61642cd0e4d6f2 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 13 Oct 2011 15:15:27 +0530 Subject: dmaengine: add new enum dma_transfer_direction This new enum removes usage of dma_data_direction for dma direction. The new enum cleans tells the DMA direction and mode This further paves way for merging the dmaengine _prep operations and also for interleaved dma Suggested-by: Jassi Brar Reviewed-by: Barry Song Signed-off-by: Vinod Koul diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index ace51af..d946ef7 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -23,7 +23,6 @@ #include #include -#include #include /** @@ -75,6 +74,19 @@ enum dma_transaction_type { /* last transaction type for creation of the capabilities mask */ #define DMA_TX_TYPE_END (DMA_CYCLIC + 1) +/** + * enum dma_transfer_direction - dma transfer mode and direction indicator + * @DMA_MEM_TO_MEM: Async/Memcpy mode + * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device + * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory + * @DMA_DEV_TO_DEV: Slave mode & From Device to Device + */ +enum dma_transfer_direction { + DMA_MEM_TO_MEM, + DMA_MEM_TO_DEV, + DMA_DEV_TO_MEM, + DMA_DEV_TO_DEV, +}; /** * enum dma_ctrl_flags - DMA flags to augment operation preparation, @@ -267,7 +279,7 @@ enum dma_slave_buswidth { * struct, if applicable. */ struct dma_slave_config { - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t src_addr; dma_addr_t dst_addr; enum dma_slave_buswidth src_addr_width; @@ -490,11 +502,11 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction); + size_t period_len, enum dma_transfer_direction direction); int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); @@ -520,7 +532,7 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, void *buf, size_t len, - enum dma_data_direction dir, unsigned long flags) + enum dma_transfer_direction dir, unsigned long flags) { struct scatterlist sg; sg_init_one(&sg, buf, len); -- cgit v0.10.2 From db8196df4bb6f117caa163aa73b0f16fd62290bd Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 13 Oct 2011 22:34:23 +0530 Subject: dmaengine: move drivers to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves dma/drivers/* to use new enum Cc: Jassi Brar Cc: Russell King Cc: Viresh Kumar Cc: Linus Walleij Cc: Nicolas Ferre Cc: Mika Westerberg Cc: H Hartley Sweeten Cc: Li Yang Cc: Zhang Wei Cc: Sascha Hauer Cc: Guennadi Liakhovetski Cc: Shawn Guo Cc: Yong Wang Cc: Tomoya MORINAGA Cc: Boojin Kim Cc: Barry Song Acked-by: Mika Westerberg Acked-by: Linus Walleij Acked-by: Viresh Kumar Acked-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h index 46d4d87..e82c642 100644 --- a/arch/arm/mach-ep93xx/include/mach/dma.h +++ b/arch/arm/mach-ep93xx/include/mach/dma.h @@ -37,7 +37,7 @@ */ struct ep93xx_dma_data { int port; - enum dma_data_direction direction; + enum dma_transfer_direction direction; const char *name; }; @@ -80,14 +80,14 @@ static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) * channel supports given DMA direction. Only M2P channels have such * limitation, for M2M channels the direction is configurable. */ -static inline enum dma_data_direction +static inline enum dma_transfer_direction ep93xx_dma_chan_direction(struct dma_chan *chan) { if (!ep93xx_dma_chan_is_m2p(chan)) return DMA_NONE; /* even channels are for TX, odd for RX */ - return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; } #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 685c787..38b041a 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -187,7 +187,7 @@ static inline struct dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, dma_addr_t addr, unsigned int size, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long flags) { struct scatterlist sg; @@ -209,7 +209,7 @@ static inline struct dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, dma_addr_t addr, unsigned int size, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long flags) { return NULL; diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index b7cbd1a..41c62fd 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -882,9 +882,9 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan, ch->signal = ret; /* Assign the flow control signal to this channel */ - if (txd->direction == DMA_TO_DEVICE) + if (txd->direction == DMA_MEM_TO_DEV) txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT; - else if (txd->direction == DMA_FROM_DEVICE) + else if (txd->direction == DMA_DEV_TO_MEM) txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT; } @@ -1102,10 +1102,10 @@ static int dma_set_runtime_config(struct dma_chan *chan, /* Transfer direction */ plchan->runtime_direction = config->direction; - if (config->direction == DMA_TO_DEVICE) { + if (config->direction == DMA_MEM_TO_DEV) { addr_width = config->dst_addr_width; maxburst = config->dst_maxburst; - } else if (config->direction == DMA_FROM_DEVICE) { + } else if (config->direction == DMA_DEV_TO_MEM) { addr_width = config->src_addr_width; maxburst = config->src_maxburst; } else { @@ -1136,7 +1136,7 @@ static int dma_set_runtime_config(struct dma_chan *chan, cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT; cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT; - if (plchan->runtime_direction == DMA_FROM_DEVICE) { + if (plchan->runtime_direction == DMA_DEV_TO_MEM) { plchan->src_addr = config->src_addr; plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR | pl08x_select_bus(plchan->cd->periph_buses, @@ -1152,7 +1152,7 @@ static int dma_set_runtime_config(struct dma_chan *chan, "configured channel %s (%s) for %s, data width %d, " "maxburst %d words, LE, CCTL=0x%08x\n", dma_chan_name(chan), plchan->name, - (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX", + (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX", addr_width, maxburst, cctl); @@ -1322,7 +1322,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy( static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); @@ -1354,10 +1354,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( */ txd->direction = direction; - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { txd->cctl = plchan->dst_cctl; slave_addr = plchan->dst_addr; - } else if (direction == DMA_FROM_DEVICE) { + } else if (direction == DMA_DEV_TO_MEM) { txd->cctl = plchan->src_cctl; slave_addr = plchan->src_addr; } else { @@ -1368,10 +1368,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( } if (plchan->cd->device_fc) - tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER : + tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER_PER : PL080_FLOW_PER2MEM_PER; else - tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER : + tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER : PL080_FLOW_PER2MEM; txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT; @@ -1387,7 +1387,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( list_add_tail(&dsg->node, &txd->dsg_list); dsg->len = sg_dma_len(sg); - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { dsg->src_addr = sg_phys(sg); dsg->dst_addr = slave_addr; } else { diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index fcfa0a8..7e76574 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -660,7 +660,7 @@ err_desc_get: */ static struct dma_async_tx_descriptor * atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct at_dma_chan *atchan = to_at_dma_chan(chan); @@ -678,7 +678,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, dev_vdbg(chan2dev(chan), "prep_slave_sg (%d): %s f0x%lx\n", sg_len, - direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE", + direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", flags); if (unlikely(!atslave || !sg_len)) { @@ -692,7 +692,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrlb = ATC_IEN; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: ctrla |= ATC_DST_WIDTH(reg_width); ctrlb |= ATC_DST_ADDR_MODE_FIXED | ATC_SRC_ADDR_MODE_INCR @@ -725,7 +725,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, total_len += len; } break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: ctrla |= ATC_SRC_WIDTH(reg_width); ctrlb |= ATC_DST_ADDR_MODE_INCR | ATC_SRC_ADDR_MODE_FIXED @@ -787,7 +787,7 @@ err_desc_get: */ static int atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { if (period_len > (ATC_BTSIZE_MAX << reg_width)) goto err_out; @@ -795,7 +795,7 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, goto err_out; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto err_out; - if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE)))) + if (unlikely(!(direction & (DMA_DEV_TO_MEM | DMA_MEM_TO_DEV)))) goto err_out; return 0; @@ -810,7 +810,7 @@ err_out: static int atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, unsigned int period_index, dma_addr_t buf_addr, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { u32 ctrla; unsigned int reg_width = atslave->reg_width; @@ -822,7 +822,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | period_len >> reg_width; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->lli.saddr = buf_addr + (period_len * period_index); desc->lli.daddr = atslave->tx_reg; desc->lli.ctrla = ctrla; @@ -833,7 +833,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | ATC_DIF(AT_DMA_PER_IF); break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->lli.saddr = atslave->rx_reg; desc->lli.daddr = buf_addr + (period_len * period_index); desc->lli.ctrla = ctrla; @@ -861,7 +861,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, */ static struct dma_async_tx_descriptor * atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma_slave *atslave = chan->private; @@ -872,7 +872,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, unsigned int i; dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n", - direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE", + direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", buf_addr, periods, buf_len, period_len); diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4234f41..d65a718 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -39,7 +39,7 @@ struct coh901318_desc { struct scatterlist *sg; unsigned int sg_len; struct coh901318_lli *lli; - enum dma_data_direction dir; + enum dma_transfer_direction dir; unsigned long flags; u32 head_config; u32 head_ctrl; @@ -1034,7 +1034,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, static struct dma_async_tx_descriptor * coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct coh901318_chan *cohc = to_coh901318_chan(chan); @@ -1077,7 +1077,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrl_last |= cohc->runtime_ctrl; ctrl |= cohc->runtime_ctrl; - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE; @@ -1085,7 +1085,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrl_chained |= tx_flags; ctrl_last |= tx_flags; ctrl |= tx_flags; - } else if (direction == DMA_FROM_DEVICE) { + } else if (direction == DMA_DEV_TO_MEM) { u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST | COH901318_CX_CTRL_DST_ADDR_INC_ENABLE; @@ -1274,11 +1274,11 @@ static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan, int i = 0; /* We only support mem to per or per to mem transfers */ - if (config->direction == DMA_FROM_DEVICE) { + if (config->direction == DMA_DEV_TO_MEM) { addr = config->src_addr; addr_width = config->src_addr_width; maxburst = config->src_maxburst; - } else if (config->direction == DMA_TO_DEVICE) { + } else if (config->direction == DMA_MEM_TO_DEV) { addr = config->dst_addr; addr_width = config->dst_addr_width; maxburst = config->dst_maxburst; diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c index 9f7e0e6a..6c0e2d4 100644 --- a/drivers/dma/coh901318_lli.c +++ b/drivers/dma/coh901318_lli.c @@ -7,11 +7,10 @@ * Author: Per Friden */ -#include #include -#include #include #include +#include #include #include "coh901318_lli.h" @@ -177,18 +176,18 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, struct coh901318_lli *lli, dma_addr_t buf, unsigned int size, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom, - enum dma_data_direction dir) + enum dma_transfer_direction dir) { int s = size; dma_addr_t src; dma_addr_t dst; - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { src = buf; dst = dev_addr; - } else if (dir == DMA_FROM_DEVICE) { + } else if (dir == DMA_DEV_TO_MEM) { src = dev_addr; dst = buf; @@ -215,9 +214,9 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, lli = coh901318_lli_next(lli); - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) src += block_size; - else if (dir == DMA_FROM_DEVICE) + else if (dir == DMA_DEV_TO_MEM) dst += block_size; } @@ -234,7 +233,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, struct scatterlist *sgl, unsigned int nents, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl, u32 ctrl_last, - enum dma_data_direction dir, u32 ctrl_irq_mask) + enum dma_transfer_direction dir, u32 ctrl_irq_mask) { int i; struct scatterlist *sg; @@ -249,9 +248,9 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, spin_lock(&pool->lock); - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) dst = dev_addr; - else if (dir == DMA_FROM_DEVICE) + else if (dir == DMA_DEV_TO_MEM) src = dev_addr; else goto err; @@ -269,7 +268,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, ctrl_sg = ctrl ? ctrl : ctrl_last; - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) /* increment source address */ src = sg_phys(sg); else @@ -293,7 +292,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, lli->src_addr = src; lli->dst_addr = dst; - if (dir == DMA_FROM_DEVICE) + if (dir == DMA_DEV_TO_MEM) dst += elem_size; else src += elem_size; diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h index 7a5c809..abff371 100644 --- a/drivers/dma/coh901318_lli.h +++ b/drivers/dma/coh901318_lli.h @@ -97,7 +97,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, struct coh901318_lli *lli, dma_addr_t buf, unsigned int size, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_last, - enum dma_data_direction dir); + enum dma_transfer_direction dir); /** * coh901318_lli_fill_single() - Prepares the lli:s for dma scatter list transfer @@ -119,6 +119,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, struct scatterlist *sg, unsigned int nents, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl, u32 ctrl_last, - enum dma_data_direction dir, u32 ctrl_irq_mask); + enum dma_transfer_direction dir, u32 ctrl_irq_mask); #endif /* COH901318_LLI_H */ diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 9bfd6d3..decca1c 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -696,7 +696,7 @@ err_desc_get: static struct dma_async_tx_descriptor * dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); @@ -720,7 +720,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, prev = first = NULL; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_FIX @@ -777,7 +777,7 @@ slave_sg_todev_fill_desc: goto slave_sg_todev_fill_desc; } break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_INC @@ -1165,7 +1165,7 @@ EXPORT_SYMBOL(dw_dma_cyclic_stop); */ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_cyclic_desc *cdesc; @@ -1206,7 +1206,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, goto out_err; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto out_err; - if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE)))) + if (unlikely(!(direction & (DMA_MEM_TO_DEV | DMA_DEV_TO_MEM)))) goto out_err; retval = ERR_PTR(-ENOMEM); @@ -1228,7 +1228,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, goto out_err_desc_get; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->lli.dar = dws->tx_reg; desc->lli.sar = buf_addr + (period_len * i); desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) @@ -1239,7 +1239,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->lli.dar = buf_addr + (period_len * i); desc->lli.sar = dws->rx_reg; desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index b47e2b8..009851b 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -330,7 +330,7 @@ static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac); u32 bus_addr; - if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE) + if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV) bus_addr = desc->src_addr; else bus_addr = desc->dst_addr; @@ -443,7 +443,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control = (5 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_NO_HDSK; - if (data->direction == DMA_TO_DEVICE) { + if (data->direction == DMA_MEM_TO_DEV) { control |= M2M_CONTROL_DAH; control |= M2M_CONTROL_TM_TX; control |= M2M_CONTROL_RSS_SSPTX; @@ -463,7 +463,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control |= M2M_CONTROL_RSS_IDE; control |= M2M_CONTROL_PW_16; - if (data->direction == DMA_TO_DEVICE) { + if (data->direction == DMA_MEM_TO_DEV) { /* Worst case from the UG */ control = (3 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_DAH; @@ -803,8 +803,8 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) switch (data->port) { case EP93XX_DMA_SSP: case EP93XX_DMA_IDE: - if (data->direction != DMA_TO_DEVICE && - data->direction != DMA_FROM_DEVICE) + if (data->direction != DMA_MEM_TO_DEV && + data->direction != DMA_DEV_TO_MEM) return -EINVAL; break; default: @@ -952,7 +952,7 @@ fail: */ static struct dma_async_tx_descriptor * ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction dir, + unsigned int sg_len, enum dma_transfer_direction dir, unsigned long flags) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); @@ -988,7 +988,7 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, goto fail; } - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { desc->src_addr = sg_dma_address(sg); desc->dst_addr = edmac->runtime_addr; } else { @@ -1032,7 +1032,7 @@ fail: static struct dma_async_tx_descriptor * ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_data_direction dir) + enum dma_transfer_direction dir) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *first; @@ -1065,7 +1065,7 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, goto fail; } - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { desc->src_addr = dma_addr + offset; desc->dst_addr = edmac->runtime_addr; } else { @@ -1133,12 +1133,12 @@ static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac, return -EINVAL; switch (config->direction) { - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: width = config->src_addr_width; addr = config->src_addr; break; - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: width = config->dst_addr_width; addr = config->dst_addr; break; diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 8a78154..b98070c 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -772,7 +772,7 @@ fail: */ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg( struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { /* * This operation is not supported on the Freescale DMA controller @@ -819,7 +819,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan, return -ENXIO; /* we set the controller burst size depending on direction */ - if (config->direction == DMA_TO_DEVICE) + if (config->direction == DMA_MEM_TO_DEV) size = config->dst_addr_width * config->dst_maxburst; else size = config->src_addr_width * config->src_maxburst; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index d746899..678cd01 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -106,7 +106,7 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, imx_dma_disable(imxdmac->imxdma_channel); return 0; case DMA_SLAVE_CONFIG: - if (dmaengine_cfg->direction == DMA_FROM_DEVICE) { + if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { imxdmac->per_address = dmaengine_cfg->src_addr; imxdmac->watermark_level = dmaengine_cfg->src_maxburst; imxdmac->word_size = dmaengine_cfg->src_addr_width; @@ -223,7 +223,7 @@ static void imxdma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct imxdma_channel *imxdmac = to_imxdma_chan(chan); @@ -240,7 +240,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( dma_length += sg->length; } - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) dmamode = DMA_MODE_READ; else dmamode = DMA_MODE_WRITE; @@ -270,7 +270,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct imxdma_channel *imxdmac = to_imxdma_chan(chan); struct imxdma_engine *imxdma = imxdmac->imxdma; @@ -316,7 +316,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( imxdmac->sg_list[periods].page_link = ((unsigned long)imxdmac->sg_list | 0x01) & ~0x02; - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) dmamode = DMA_MODE_READ; else dmamode = DMA_MODE_WRITE; diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index eab1fe7..065de54 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -246,7 +246,7 @@ struct sdma_engine; struct sdma_channel { struct sdma_engine *sdma; unsigned int channel; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum sdma_peripheral_type peripheral_type; unsigned int event_id0; unsigned int event_id1; @@ -649,7 +649,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; int ret; - if (sdmac->direction == DMA_FROM_DEVICE) { + if (sdmac->direction == DMA_DEV_TO_MEM) { load_address = sdmac->pc_from_device; } else { load_address = sdmac->pc_to_device; @@ -910,7 +910,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *sdma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct sdma_channel *sdmac = to_sdma_chan(chan); @@ -1007,7 +1007,7 @@ err_out: static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; @@ -1092,7 +1092,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, sdma_disable_channel(sdmac); return 0; case DMA_SLAVE_CONFIG: - if (dmaengine_cfg->direction == DMA_FROM_DEVICE) { + if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { sdmac->per_address = dmaengine_cfg->src_addr; sdmac->watermark_level = dmaengine_cfg->src_maxburst; sdmac->word_size = dmaengine_cfg->src_addr_width; diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 9e96c43..6deda25 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -394,10 +394,10 @@ static int midc_lli_fill_sg(struct intel_mid_dma_chan *midc, midc->dma->block_size); /*Populate SAR and DAR values*/ sg_phy_addr = sg_phys(sg); - if (desc->dirn == DMA_TO_DEVICE) { + if (desc->dirn == DMA_MEM_TO_DEV) { lli_bloc_desc->sar = sg_phy_addr; lli_bloc_desc->dar = mids->dma_slave.dst_addr; - } else if (desc->dirn == DMA_FROM_DEVICE) { + } else if (desc->dirn == DMA_DEV_TO_MEM) { lli_bloc_desc->sar = mids->dma_slave.src_addr; lli_bloc_desc->dar = sg_phy_addr; } @@ -631,13 +631,13 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy( if (midc->dma->pimr_mask) { cfg_hi.cfgx.protctl = 0x0; /*default value*/ cfg_hi.cfgx.fifo_mode = 1; - if (mids->dma_slave.direction == DMA_TO_DEVICE) { + if (mids->dma_slave.direction == DMA_MEM_TO_DEV) { cfg_hi.cfgx.src_per = 0; if (mids->device_instance == 0) cfg_hi.cfgx.dst_per = 3; if (mids->device_instance == 1) cfg_hi.cfgx.dst_per = 1; - } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) { + } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) { if (mids->device_instance == 0) cfg_hi.cfgx.src_per = 2; if (mids->device_instance == 1) @@ -681,11 +681,11 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy( ctl_lo.ctlx.sinc = 0; ctl_lo.ctlx.dinc = 0; } else { - if (mids->dma_slave.direction == DMA_TO_DEVICE) { + if (mids->dma_slave.direction == DMA_MEM_TO_DEV) { ctl_lo.ctlx.sinc = 0; ctl_lo.ctlx.dinc = 2; ctl_lo.ctlx.tt_fc = 1; - } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) { + } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) { ctl_lo.ctlx.sinc = 2; ctl_lo.ctlx.dinc = 0; ctl_lo.ctlx.tt_fc = 2; @@ -731,7 +731,7 @@ err_desc_get: */ static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct intel_mid_dma_chan *midc = NULL; diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h index aea5ee8..c6de919 100644 --- a/drivers/dma/intel_mid_dma_regs.h +++ b/drivers/dma/intel_mid_dma_regs.h @@ -262,7 +262,7 @@ struct intel_mid_dma_desc { unsigned int lli_length; unsigned int current_lli; dma_addr_t next; - enum dma_data_direction dirn; + enum dma_transfer_direction dirn; enum dma_status status; enum dma_slave_buswidth width; /*width of DMA txn*/ enum intel_mid_dma_mode cfg_mode; /*mode configuration*/ diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 6815905..0cee3b3 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1362,7 +1362,7 @@ static void ipu_gc_tasklet(unsigned long arg) /* Allocate and initialise a transfer descriptor. */ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long tx_flags) + enum dma_transfer_direction direction, unsigned long tx_flags) { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac_tx_desc *desc = NULL; @@ -1374,7 +1374,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan chan->chan_id != IDMAC_IC_7) return NULL; - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) { + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction); return NULL; } diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b4588bd..bdf4672 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -377,7 +377,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long append) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); @@ -450,7 +450,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits |= CCW_CHAIN; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; - ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ? MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND); @@ -472,7 +472,7 @@ err_out: static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; @@ -515,7 +515,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( ccw->bits |= CCW_IRQ; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; - ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ? MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND); dma_addr += period_len; diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a6d0e3d..9944e82 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -99,7 +99,7 @@ struct pch_dma_desc { struct pch_dma_chan { struct dma_chan chan; void __iomem *membase; - enum dma_data_direction dir; + enum dma_transfer_direction dir; struct tasklet_struct tasklet; unsigned long err_status; @@ -224,7 +224,7 @@ static void pdc_set_dir(struct dma_chan *chan) mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS << (DMA_CTL0_BITS_PER_CH * chan->chan_id)); val &= mask_mode; - if (pd_chan->dir == DMA_TO_DEVICE) + if (pd_chan->dir == DMA_MEM_TO_DEV) val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id + DMA_CTL0_DIR_SHIFT_BITS); else @@ -242,7 +242,7 @@ static void pdc_set_dir(struct dma_chan *chan) mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS << (DMA_CTL0_BITS_PER_CH * ch)); val &= mask_mode; - if (pd_chan->dir == DMA_TO_DEVICE) + if (pd_chan->dir == DMA_MEM_TO_DEV) val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch + DMA_CTL0_DIR_SHIFT_BITS); else @@ -607,7 +607,7 @@ static void pd_issue_pending(struct dma_chan *chan) static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct pch_dma_chan *pd_chan = to_pd_chan(chan); struct pch_dma_slave *pd_slave = chan->private; @@ -623,9 +623,9 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, return NULL; } - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) reg = pd_slave->rx_reg; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) reg = pd_slave->tx_reg; else return NULL; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 57104147..1e58eeb 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -320,14 +320,14 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned case DMA_SLAVE_CONFIG: slave_config = (struct dma_slave_config *)arg; - if (slave_config->direction == DMA_TO_DEVICE) { + if (slave_config->direction == DMA_MEM_TO_DEV) { if (slave_config->dst_addr) pch->fifo_addr = slave_config->dst_addr; if (slave_config->dst_addr_width) pch->burst_sz = __ffs(slave_config->dst_addr_width); if (slave_config->dst_maxburst) pch->burst_len = slave_config->dst_maxburst; - } else if (slave_config->direction == DMA_FROM_DEVICE) { + } else if (slave_config->direction == DMA_DEV_TO_MEM) { if (slave_config->src_addr) pch->fifo_addr = slave_config->src_addr; if (slave_config->src_addr_width) @@ -597,7 +597,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct dma_pl330_desc *desc; struct dma_pl330_chan *pch = to_pchan(chan); @@ -612,13 +612,13 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( } switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; src = dma_addr; dst = pch->fifo_addr; break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; src = pch->fifo_addr; @@ -687,7 +687,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, static struct dma_async_tx_descriptor * pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flg) { struct dma_pl330_desc *first, *desc = NULL; @@ -702,9 +702,9 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; /* Make sure the direction is consistent */ - if ((direction == DMA_TO_DEVICE && + if ((direction == DMA_MEM_TO_DEV && peri->rqtype != MEMTODEV) || - (direction == DMA_FROM_DEVICE && + (direction == DMA_DEV_TO_MEM && peri->rqtype != DEVTOMEM)) { dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n", __func__, __LINE__); @@ -747,7 +747,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, else list_add_tail(&desc->node, &first->node); - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; fill_px(&desc->px, diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 81809c2..592304f 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -479,19 +478,19 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) * @sh_chan: DMA channel * @flags: DMA transfer flags * @dest: destination DMA address, incremented when direction equals - * DMA_FROM_DEVICE or DMA_BIDIRECTIONAL + * DMA_DEV_TO_MEM * @src: source DMA address, incremented when direction equals - * DMA_TO_DEVICE or DMA_BIDIRECTIONAL + * DMA_MEM_TO_DEV * @len: DMA transfer length * @first: if NULL, set to the current descriptor and cookie set to -EBUSY * @direction: needed for slave DMA to decide which address to keep constant, - * equals DMA_BIDIRECTIONAL for MEMCPY + * equals DMA_MEM_TO_MEM for MEMCPY * Returns 0 or an error * Locks: called with desc_lock held */ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len, - struct sh_desc **first, enum dma_data_direction direction) + struct sh_desc **first, enum dma_transfer_direction direction) { struct sh_desc *new; size_t copy_size; @@ -531,9 +530,9 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, new->direction = direction; *len -= copy_size; - if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE) + if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) *src += copy_size; - if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE) + if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM) *dest += copy_size; return new; @@ -546,12 +545,12 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, * converted to scatter-gather to guarantee consistent locking and a correct * list manipulation. For slave DMA direction carries the usual meaning, and, * logically, the SG list is RAM and the addr variable contains slave address, - * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL + * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM * and the SG list contains only one element and points at the source buffer. */ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan, struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct scatterlist *sg; struct sh_desc *first = NULL, *new = NULL /* compiler... */; @@ -592,7 +591,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n", i, sg, len, (unsigned long long)sg_addr); - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) new = sh_dmae_add_desc(sh_chan, flags, &sg_addr, addr, &len, &first, direction); @@ -646,13 +645,13 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( sg_dma_address(&sg) = dma_src; sg_dma_len(&sg) = len; - return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL, + return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, flags); } static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct sh_dmae_slave *param; struct sh_dmae_chan *sh_chan; @@ -996,7 +995,7 @@ static void dmae_do_tasklet(unsigned long data) spin_lock_irq(&sh_chan->desc_lock); list_for_each_entry(desc, &sh_chan->ld_queue, node) { if (desc->mark == DESC_SUBMITTED && - ((desc->direction == DMA_FROM_DEVICE && + ((desc->direction == DMA_DEV_TO_MEM && (desc->hw.dar + desc->hw.tcr) == dar_buf) || (desc->hw.sar + desc->hw.tcr) == sar_buf)) { dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n", diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 467e4dc..0c6cbac 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -216,7 +216,7 @@ struct d40_chan { struct d40_log_lli_full *lcpa; /* Runtime reconfiguration */ dma_addr_t runtime_addr; - enum dma_data_direction runtime_direction; + enum dma_transfer_direction runtime_direction; }; /** @@ -1854,7 +1854,7 @@ err: } static dma_addr_t -d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) +d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction) { struct stedma40_platform_data *plat = chan->base->plat_data; struct stedma40_chan_cfg *cfg = &chan->dma_cfg; @@ -1863,9 +1863,9 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) if (chan->runtime_addr) return chan->runtime_addr; - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) addr = plat->dev_rx[cfg->src_dev_type]; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) addr = plat->dev_tx[cfg->dst_dev_type]; return addr; @@ -1874,7 +1874,7 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) static struct dma_async_tx_descriptor * d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, struct scatterlist *sg_dst, unsigned int sg_len, - enum dma_data_direction direction, unsigned long dma_flags) + enum dma_transfer_direction direction, unsigned long dma_flags) { struct d40_chan *chan = container_of(dchan, struct d40_chan, chan); dma_addr_t src_dev_addr = 0; @@ -1901,9 +1901,9 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, if (direction != DMA_NONE) { dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) src_dev_addr = dev_addr; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) dst_dev_addr = dev_addr; } @@ -2107,10 +2107,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan, static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long dma_flags) { - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) return NULL; return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags); @@ -2119,7 +2119,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, static struct dma_async_tx_descriptor * dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { unsigned int periods = buf_len / period_len; struct dma_async_tx_descriptor *txd; @@ -2268,7 +2268,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, dst_addr_width = config->dst_addr_width; dst_maxburst = config->dst_maxburst; - if (config->direction == DMA_FROM_DEVICE) { + if (config->direction == DMA_DEV_TO_MEM) { dma_addr_t dev_addr_rx = d40c->base->plat_data->dev_rx[cfg->src_dev_type]; @@ -2291,7 +2291,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, if (dst_maxburst == 0) dst_maxburst = src_maxburst; - } else if (config->direction == DMA_TO_DEVICE) { + } else if (config->direction == DMA_MEM_TO_DEV) { dma_addr_t dev_addr_tx = d40c->base->plat_data->dev_tx[cfg->dst_dev_type]; @@ -2356,7 +2356,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, "configured channel %s for %s, data width %d/%d, " "maxburst %d/%d elements, LE, no flow control\n", dma_chan_name(chan), - (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX", + (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX", src_addr_width, dst_addr_width, src_maxburst, dst_maxburst); diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index a4a398f..8c88072 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -90,7 +90,7 @@ struct timb_dma_chan { struct list_head queue; struct list_head free_list; unsigned int bytes_per_line; - enum dma_data_direction direction; + enum dma_transfer_direction direction; unsigned int descs; /* Descriptors to allocate */ unsigned int desc_elems; /* number of elems per descriptor */ }; @@ -235,7 +235,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan) "td_chan: %p, chan: %d, membase: %p\n", td_chan, td_chan->chan.chan_id, td_chan->membase); - if (td_chan->direction == DMA_FROM_DEVICE) { + if (td_chan->direction == DMA_DEV_TO_MEM) { /* descriptor address */ iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_DHAR); @@ -278,7 +278,7 @@ static void __td_finish(struct timb_dma_chan *td_chan) txd->cookie); /* make sure to stop the transfer */ - if (td_chan->direction == DMA_FROM_DEVICE) + if (td_chan->direction == DMA_DEV_TO_MEM) iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_ER); /* Currently no support for stopping DMA transfers else @@ -398,7 +398,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) td_desc->txd.flags = DMA_CTRL_ACK; td_desc->txd.phys = dma_map_single(chan2dmadev(chan), - td_desc->desc_list, td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list, td_desc->desc_list_len, DMA_MEM_TO_DEV); err = dma_mapping_error(chan2dmadev(chan), td_desc->txd.phys); if (err) { @@ -419,7 +419,7 @@ static void td_free_desc(struct timb_dma_desc *td_desc) { dev_dbg(chan2dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); dma_unmap_single(chan2dmadev(td_desc->txd.chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list_len, DMA_MEM_TO_DEV); kfree(td_desc->desc_list); kfree(td_desc); @@ -558,7 +558,7 @@ static void td_issue_pending(struct dma_chan *chan) static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct timb_dma_chan *td_chan = container_of(chan, struct timb_dma_chan, chan); @@ -606,7 +606,7 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, } dma_sync_single_for_device(chan2dmadev(chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list_len, DMA_MEM_TO_DEV); return &td_desc->txd; } @@ -775,8 +775,8 @@ static int __devinit td_probe(struct platform_device *pdev) td_chan->descs = pchan->descriptors; td_chan->desc_elems = pchan->descriptor_elements; td_chan->bytes_per_line = pchan->bytes_per_line; - td_chan->direction = pchan->rx ? DMA_FROM_DEVICE : - DMA_TO_DEVICE; + td_chan->direction = pchan->rx ? DMA_DEV_TO_MEM : + DMA_MEM_TO_DEV; td_chan->membase = td->membase + (i / 2) * TIMBDMA_INSTANCE_OFFSET + diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index cbd83e36..6122c36 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -845,7 +845,7 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, static struct dma_async_tx_descriptor * txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct txx9dmac_chan *dc = to_txx9dmac_chan(chan); @@ -860,9 +860,9 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, BUG_ON(!ds || !ds->reg_width); if (ds->tx_reg) - BUG_ON(direction != DMA_TO_DEVICE); + BUG_ON(direction != DMA_MEM_TO_DEV); else - BUG_ON(direction != DMA_FROM_DEVICE); + BUG_ON(direction != DMA_DEV_TO_MEM); if (unlikely(!sg_len)) return NULL; @@ -882,7 +882,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); if (__is_dmac64(ddev)) { - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->hwdesc.SAR = mem; desc->hwdesc.DAR = ds->tx_reg; } else { @@ -891,7 +891,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->hwdesc.CNTR = sg_dma_len(sg); } else { - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->hwdesc32.SAR = mem; desc->hwdesc32.DAR = ds->tx_reg; } else { @@ -900,7 +900,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->hwdesc32.CNTR = sg_dma_len(sg); } - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { sai = ds->reg_width; dai = 0; } else { diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h index 9eabffb..033f6aa 100644 --- a/include/linux/amba/pl08x.h +++ b/include/linux/amba/pl08x.h @@ -134,7 +134,7 @@ struct pl08x_txd { struct dma_async_tx_descriptor tx; struct list_head node; struct list_head dsg_list; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t llis_bus; struct pl08x_lli *llis_va; /* Default cctl value for LLIs */ @@ -197,7 +197,7 @@ struct pl08x_dma_chan { dma_addr_t dst_addr; u32 src_cctl; u32 dst_cctl; - enum dma_data_direction runtime_direction; + enum dma_transfer_direction runtime_direction; dma_cookie_t lc; struct list_head pend_list; struct pl08x_txd *at; diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 4bfe0a2..f2c64f9 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -127,7 +127,7 @@ struct dw_cyclic_desc { struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction); + enum dma_transfer_direction direction); void dw_dma_cyclic_free(struct dma_chan *chan); int dw_dma_cyclic_start(struct dma_chan *chan); void dw_dma_cyclic_stop(struct dma_chan *chan); diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index cb2dd11..62ef693 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -30,7 +30,7 @@ struct sh_desc { struct sh_dmae_regs hw; struct list_head node; struct dma_async_tx_descriptor async_tx; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_cookie_t cookie; size_t partial; int chunks; -- cgit v0.10.2 From 20dd5a356efcb5bf574baa9adccc775158f13ae1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:35:16 +0530 Subject: plat-samsung: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves samsung drivers to use new enum Cc: Ben Dooks Cc: Kukjin Kim Cc: Boojin Kim Acked-by: Kukjin Kim Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index 6e3d9ab..3df0bad 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -35,14 +35,14 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch, chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch); - if (info->direction == DMA_FROM_DEVICE) { + if (info->direction == DMA_DEV_TO_MEM) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); slave_config.direction = info->direction; slave_config.src_addr = info->fifo; slave_config.src_addr_width = info->width; slave_config.src_maxburst = 1; dmaengine_slave_config(chan, &slave_config); - } else if (info->direction == DMA_TO_DEVICE) { + } else if (info->direction == DMA_MEM_TO_DEV) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); slave_config.direction = info->direction; slave_config.dst_addr = info->fifo; diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h index 4c1a363..1256115 100644 --- a/arch/arm/plat-samsung/include/plat/dma-ops.h +++ b/arch/arm/plat-samsung/include/plat/dma-ops.h @@ -17,7 +17,7 @@ struct samsung_dma_prep_info { enum dma_transaction_type cap; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t buf; unsigned long period; unsigned long len; @@ -27,7 +27,7 @@ struct samsung_dma_prep_info { struct samsung_dma_info { enum dma_transaction_type cap; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum dma_slave_buswidth width; dma_addr_t fifo; struct s3c2410_dma_client *client; -- cgit v0.10.2 From 1003cab8276cd34d9deab8ca9d148ee59f7728a7 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:39:23 +0530 Subject: media, video: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves media and video drivers to use new enum Cc: Mauro Carvalho Chehab Cc: Paul Mundt Cc: Guennadi Liakhovetski Acked-by: Guennadi Liakhovetski Acked-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index c045b47..ec98eae 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -251,7 +251,7 @@ static int mx3_videobuf_prepare(struct vb2_buffer *vb) sg_dma_len(sg) = new_size; buf->txd = ichan->dma_chan.device->device_prep_slave_sg( - &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, + &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!buf->txd) return -EIO; diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index 84cd1b6..d542c8b 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -564,7 +564,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) spin_unlock_irq(&fh->queue_lock); desc = fh->chan->device->device_prep_slave_sg(fh->chan, - buf->sg, sg_elems, DMA_FROM_DEVICE, + buf->sg, sg_elems, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!desc) { spin_lock_irq(&fh->queue_lock); diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7e3a490..e2caf88 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -334,7 +334,7 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi) /* This enables the channel */ if (mx3_fbi->cookie < 0) { mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan, - &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); + &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!mx3_fbi->txd) { dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n", dma_chan->chan_id); @@ -1104,7 +1104,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var, async_tx_ack(mx3_fbi->txd); txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg + - mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); + mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!txd) { dev_err(fbi->device, "Error preparing a DMA transaction descriptor.\n"); -- cgit v0.10.2 From 1d0c81e876fe04295ef5df387ba057bf9cfae3d8 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:42:56 +0530 Subject: carma: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves carma drivers to use new enum Signed-off-by: Vinod Koul CC Ira W. Snyder diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index 7ce6065..20ef1ea 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c @@ -513,7 +513,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv) * transaction, and then put it under external control */ memset(&config, 0, sizeof(config)); - config.direction = DMA_TO_DEVICE; + config.direction = DMA_MEM_TO_DEV; config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4; ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG, -- cgit v0.10.2 From 05f5799cbe5c9e2c03f604b3de5783cf4d726227 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:45:11 +0530 Subject: mmc-host: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves mmc drivers to use new enum Cc: Nicolas Ferre Cc: Chris Ball Cc: Guennadi Liakhovetski Acked-by: Nicolas Ferre Acked-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fa8cae1..ac87803 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -653,6 +653,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) struct scatterlist *sg; unsigned int i; enum dma_data_direction direction; + enum dma_transfer_direction slave_dirn; unsigned int sglen; /* @@ -681,16 +682,19 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) if (atmci_is_mci2()) mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); - if (data->flags & MMC_DATA_READ) + if (data->flags & MMC_DATA_READ) { direction = DMA_FROM_DEVICE; - else + slave_dirn = DMA_DEV_TO_MEM; + } else { direction = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; + } sglen = dma_map_sg(chan->device->dev, data->sg, data->sg_len, direction); desc = chan->device->device_prep_slave_sg(chan, - data->sg, sglen, direction, + data->sg, sglen, slave_dirn, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) goto unmap_exit; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 56e9a416..3abd51a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -372,6 +372,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, struct dma_chan *chan; struct dma_device *device; struct dma_async_tx_descriptor *desc; + enum dma_data_direction buffer_dirn; int nr_sg; /* Check if next job is already prepared */ @@ -385,10 +386,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, } if (data->flags & MMC_DATA_READ) { - conf.direction = DMA_FROM_DEVICE; + conf.direction = DMA_DEV_TO_MEM; + buffer_dirn = DMA_FROM_DEVICE; chan = host->dma_rx_channel; } else { - conf.direction = DMA_TO_DEVICE; + conf.direction = DMA_MEM_TO_DEV; + buffer_dirn = DMA_TO_DEVICE; chan = host->dma_tx_channel; } @@ -401,7 +404,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, return -EINVAL; device = chan->device; - nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction); + nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn); if (nr_sg == 0) return -EINVAL; @@ -424,7 +427,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, unmap_exit: if (!next) dmaengine_terminate_all(chan); - dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction); + dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn); return -ENOMEM; } diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 14aa213..8a81663 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -217,6 +217,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) unsigned int blksz = data->blksz; unsigned int datasize = nob * blksz; struct scatterlist *sg; + enum dma_transfer_direction slave_dirn; int i, nents; if (data->flags & MMC_DATA_STREAM) @@ -239,10 +240,13 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) } } - if (data->flags & MMC_DATA_READ) + if (data->flags & MMC_DATA_READ) { host->dma_dir = DMA_FROM_DEVICE; - else + slave_dirn = DMA_DEV_TO_MEM; + } else { host->dma_dir = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; + } nents = dma_map_sg(host->dma->device->dev, data->sg, data->sg_len, host->dma_dir); @@ -250,7 +254,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) return -EINVAL; host->desc = host->dma->device->device_prep_slave_sg(host->dma, - data->sg, data->sg_len, host->dma_dir, + data->sg, data->sg_len, slave_dirn, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!host->desc) { diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index d513d47..996b9a9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -153,6 +153,7 @@ struct mxs_mmc_host { struct dma_chan *dmach; struct mxs_dma_data dma_data; unsigned int dma_dir; + enum dma_transfer_direction slave_dirn; u32 ssp_pio_words[SSP_PIO_NUM]; unsigned int version; @@ -323,7 +324,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( } desc = host->dmach->device->device_prep_slave_sg(host->dmach, - sgl, sg_len, host->dma_dir, append); + sgl, sg_len, host->slave_dirn, append); if (desc) { desc->callback = mxs_mmc_dma_irq_callback; desc->callback_param = host; @@ -432,6 +433,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) int i; unsigned short dma_data_dir, timeout; + enum dma_transfer_direction slave_dirn; unsigned int data_size = 0, log2_blksz; unsigned int blocks = data->blocks; @@ -447,9 +449,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) if (data->flags & MMC_DATA_WRITE) { dma_data_dir = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; read = 0; } else { dma_data_dir = DMA_FROM_DEVICE; + slave_dirn = DMA_DEV_TO_MEM; read = BM_SSP_CTRL0_READ; } @@ -517,6 +521,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) WARN_ON(host->data != NULL); host->data = data; host->dma_dir = dma_data_dir; + host->slave_dirn = slave_dirn; desc = mxs_mmc_prep_dma(host, 1); if (!desc) goto out; diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 557886b..0ae8d62 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -230,7 +230,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) if (ret > 0) { host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (desc) { @@ -278,7 +278,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) if (ret > 0) { host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (desc) { diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 86f259c..7a6e6cc 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -77,7 +77,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_FROM_DEVICE, DMA_CTRL_ACK); + DMA_DEV_TO_MEM, DMA_CTRL_ACK); if (desc) { cookie = dmaengine_submit(desc); @@ -158,7 +158,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_CTRL_ACK); + DMA_MEM_TO_DEV, DMA_CTRL_ACK); if (desc) { cookie = dmaengine_submit(desc); -- cgit v0.10.2 From a485df4b4404379786c4bdd258bc528b2617449d Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:47:38 +0530 Subject: spi, serial: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves spi, serial drivers to use new enum Signed-off-by: Vinod Koul Cc: Grant Likely Cc: Alan Cox Acked-by: Mika Westerberg diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 130e555..0a1fc8a 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -131,7 +131,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxchan = dws->rxchan; /* 2. Prepare the TX dma transfer */ - txconf.direction = DMA_TO_DEVICE; + txconf.direction = DMA_MEM_TO_DEV; txconf.dst_addr = dws->dma_addr; txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -147,13 +147,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) txdesc = txchan->device->device_prep_slave_sg(txchan, &dws->tx_sgl, 1, - DMA_TO_DEVICE, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP); txdesc->callback = dw_spi_dma_done; txdesc->callback_param = dws; /* 3. Prepare the RX dma transfer */ - rxconf.direction = DMA_FROM_DEVICE; + rxconf.direction = DMA_DEV_TO_MEM; rxconf.src_addr = dws->dma_addr; rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -169,7 +169,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxdesc = rxchan->device->device_prep_slave_sg(rxchan, &dws->rx_sgl, 1, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP); rxdesc->callback = dw_spi_dma_done; rxdesc->callback_param = dws; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 1cf6454..0afd87d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -550,6 +550,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) struct dma_async_tx_descriptor *txd; enum dma_slave_buswidth buswidth; struct dma_slave_config conf; + enum dma_transfer_direction slave_dirn; struct scatterlist *sg; struct sg_table *sgt; struct dma_chan *chan; @@ -572,6 +573,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) conf.src_addr = espi->sspdr_phys; conf.src_addr_width = buswidth; + slave_dirn = DMA_DEV_TO_MEM; } else { chan = espi->dma_tx; buf = t->tx_buf; @@ -579,6 +581,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) conf.dst_addr = espi->sspdr_phys; conf.dst_addr_width = buswidth; + slave_dirn = DMA_MEM_TO_DEV; } ret = dmaengine_slave_config(chan, &conf); @@ -630,7 +633,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) return ERR_PTR(-ENOMEM); txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents, - dir, DMA_CTRL_ACK); + slave_dirn, DMA_CTRL_ACK); if (!txd) { dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); return ERR_PTR(-ENOMEM); @@ -978,7 +981,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) dma_cap_set(DMA_SLAVE, mask); espi->dma_rx_data.port = EP93XX_DMA_SSP; - espi->dma_rx_data.direction = DMA_FROM_DEVICE; + espi->dma_rx_data.direction = DMA_DEV_TO_MEM; espi->dma_rx_data.name = "ep93xx-spi-rx"; espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter, @@ -989,7 +992,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) } espi->dma_tx_data.port = EP93XX_DMA_SSP; - espi->dma_tx_data.direction = DMA_TO_DEVICE; + espi->dma_tx_data.direction = DMA_MEM_TO_DEV; espi->dma_tx_data.name = "ep93xx-spi-tx"; espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter, diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 730b4a3..ddcddf4 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -910,11 +910,11 @@ static int configure_dma(struct pl022 *pl022) { struct dma_slave_config rx_conf = { .src_addr = SSP_DR(pl022->phybase), - .direction = DMA_FROM_DEVICE, + .direction = DMA_DEV_TO_MEM, }; struct dma_slave_config tx_conf = { .dst_addr = SSP_DR(pl022->phybase), - .direction = DMA_TO_DEVICE, + .direction = DMA_MEM_TO_DEV, }; unsigned int pages; int ret; @@ -1051,7 +1051,7 @@ static int configure_dma(struct pl022 *pl022) rxdesc = rxchan->device->device_prep_slave_sg(rxchan, pl022->sgt_rx.sgl, rx_sglen, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!rxdesc) goto err_rxdesc; @@ -1059,7 +1059,7 @@ static int configure_dma(struct pl022 *pl022) txdesc = txchan->device->device_prep_slave_sg(txchan, pl022->sgt_tx.sgl, tx_sglen, - DMA_TO_DEVICE, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!txdesc) goto err_txdesc; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1d23f38..7eba26e 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1051,7 +1051,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) } sg = dma->sg_rx_p; desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg, - num, DMA_FROM_DEVICE, + num, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) { dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", @@ -1086,7 +1086,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) } sg = dma->sg_tx_p; desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx, - sg, num, DMA_TO_DEVICE, + sg, num, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index f5f6831..460ff7d 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -268,7 +268,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) struct dma_slave_config tx_conf = { .dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .direction = DMA_TO_DEVICE, + .direction = DMA_MEM_TO_DEV, .dst_maxburst = uap->fifosize >> 1, }; struct dma_chan *chan; @@ -301,7 +301,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) struct dma_slave_config rx_conf = { .src_addr = uap->port.mapbase + UART01x_DR, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .direction = DMA_FROM_DEVICE, + .direction = DMA_DEV_TO_MEM, .src_maxburst = uap->fifosize >> 1, }; @@ -480,7 +480,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) return -EBUSY; } - desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE, + desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE); @@ -676,7 +676,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; dma_dev = rxchan->device; desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); /* * If the DMA engine is busy and cannot prepare a diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index b46218d..73201a1 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -747,7 +747,7 @@ static int dma_handle_rx(struct eg20t_port *priv) sg_dma_address(sg) = priv->rx_buf_dma; desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, - sg, 1, DMA_FROM_DEVICE, + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) @@ -906,7 +906,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) } desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, - priv->sg_tx_p, nent, DMA_TO_DEVICE, + priv->sg_tx_p, nent, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n", diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dbd32a1..3683a69 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1207,7 +1207,7 @@ static void sci_submit_rx(struct sci_port *s) struct dma_async_tx_descriptor *desc; desc = chan->device->device_prep_slave_sg(chan, - sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (desc) { s->desc_rx[i] = desc; @@ -1322,7 +1322,7 @@ static void work_fn_tx(struct work_struct *work) BUG_ON(!sg_dma_len(sg)); desc = chan->device->device_prep_slave_sg(chan, - sg, s->sg_len_tx, DMA_TO_DEVICE, + sg, s->sg_len_tx, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { /* switch to PIO */ -- cgit v0.10.2 From 35e16581ed6bff55009a0bac34c755140407b03f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:49:30 +0530 Subject: sound-soc: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves asoc drivers to use new enum Signed-off-by: Vinod Koul Cc: Liam Girdwood Cc: Mark Brown Acked-by: Mark Brown diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index 6fd9391..4fa1dbd 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -133,7 +133,7 @@ static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, period_len = frames_to_bytes(runtime, runtime->period_size); cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, DMA_TO_DEVICE); + period_len, DMA_MEM_TO_DEV); if (IS_ERR(cdesc)) { dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); return PTR_ERR(cdesc); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 6e5adde..cd9428b 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -102,7 +102,7 @@ static void atmel_ac97c_dma_capture_period_done(void *arg) static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, struct snd_pcm_substream *substream, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { struct dma_chan *chan; struct dw_cyclic_desc *cdesc; @@ -118,7 +118,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, return -EINVAL; } - if (direction == DMA_TO_DEVICE) + if (direction == DMA_MEM_TO_DEV) chan = chip->dma.tx_chan; else chan = chip->dma.rx_chan; @@ -133,7 +133,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, return PTR_ERR(cdesc); } - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { cdesc->period_callback = atmel_ac97c_dma_playback_period_done; set_bit(DMA_TX_READY, &chip->flags); } else { @@ -393,7 +393,7 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) if (cpu_is_at32ap7000()) { if (!test_bit(DMA_TX_READY, &chip->flags)) retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_TO_DEVICE); + DMA_MEM_TO_DEV); } else { /* Initialize and start the PDC */ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); @@ -484,7 +484,7 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) if (cpu_is_at32ap7000()) { if (!test_bit(DMA_RX_READY, &chip->flags)) retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_FROM_DEVICE); + DMA_DEV_TO_MEM); } else { /* Initialize and start the PDC */ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 8dfd3ad..faf7d4f 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -113,9 +113,9 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream) rtd->dma_data.name = dma_params->name; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->dma_data.direction = DMA_TO_DEVICE; + rtd->dma_data.direction = DMA_MEM_TO_DEV; else - rtd->dma_data.direction = DMA_FROM_DEVICE; + rtd->dma_data.direction = DMA_DEV_TO_MEM; rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter, &rtd->dma_data); diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 43fdc24f..7d28de9 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -107,12 +107,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - slave_config.direction = DMA_TO_DEVICE; + slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = dma_params->dma_addr; slave_config.dst_addr_width = buswidth; slave_config.dst_maxburst = dma_params->burstsize; } else { - slave_config.direction = DMA_FROM_DEVICE; + slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = dma_params->dma_addr; slave_config.src_addr_width = buswidth; slave_config.src_maxburst = dma_params->burstsize; @@ -159,7 +159,7 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, iprtd->period_bytes * iprtd->periods, iprtd->period_bytes, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); + DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); if (!iprtd->desc) { dev_err(&chan->dev->device, "cannot prepare slave dma\n"); return -EINVAL; diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 851346f..87a3957 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -85,7 +85,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream) dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); dma_info.fp = audio_buffdone; dma_info.fp_param = substream; dma_info.period = prtd->dma_period; @@ -170,7 +170,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream, dma_info.client = prtd->params->client; dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); dma_info.width = prtd->params->dma_size; dma_info.fifo = prtd->params->dma_addr; prtd->params->ch = prtd->params->ops->request( diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index f8f6816..0193e59 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -131,7 +131,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, - &sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dev, "Failed to allocate a dma descriptor\n"); return -ENOMEM; @@ -181,7 +181,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info, sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, - &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dev, "Failed to allocate dma descriptor\n"); return -ENOMEM; diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 3de99af..602bb68 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -134,7 +134,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) sg_dma_address(&sg) = buf_dma_addr; desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_TO_DEVICE : DMA_FROM_DEVICE, + DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(&chan->dev->device, "cannot prepare slave dma\n"); -- cgit v0.10.2 From 8af11fd3f013892c918a39acb691bc7469c5ad77 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:52:48 +0530 Subject: net-ks8842: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves net/ks8842 drivers to use new enum Signed-off-by: Vinod Koul Cc: David S. Miller Cc: Samuel Ortiz diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index 4a6ae05..de9f2e2 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -459,7 +459,7 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - &ctl->sg, 1, DMA_TO_DEVICE, + &ctl->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!ctl->adesc) return NETDEV_TX_BUSY; @@ -571,7 +571,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev) sg_dma_len(sg) = DMA_BUFFER_SIZE; ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - sg, 1, DMA_FROM_DEVICE, + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!ctl->adesc) -- cgit v0.10.2 From 67348450b86cb1b42aa4dd55cf7cde19c2e53461 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 17 Oct 2011 14:56:40 +0200 Subject: dmaengine: at_hdmac: platform data move to use .id_table We remove the use of platform data from DMA controller driver. We now use of .id_table to distinguish between compatible types. The two implementations allow to determine the number of channels and the capabilities of the controller. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index fcfa0a8..d1869c5 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1175,6 +1175,18 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +static struct platform_device_id atdma_devtypes[] = { + { + .name = "at91sam9rl_dma", + .driver_data = ATDMA_DEVTYPE_SAM9RL, + }, { + .name = "at91sam9g45_dma", + .driver_data = ATDMA_DEVTYPE_SAM9G45, + }, { + /* sentinel */ + } +}; + /** * at_dma_off - disable DMA controller * @atdma: the Atmel HDAMC device @@ -1193,18 +1205,32 @@ static void at_dma_off(struct at_dma *atdma) static int __init at_dma_probe(struct platform_device *pdev) { - struct at_dma_platform_data *pdata; struct resource *io; struct at_dma *atdma; size_t size; int irq; int err; int i; + u32 nr_channels; + dma_cap_mask_t cap_mask = {}; + enum atdma_devtype atdmatype; + + dma_cap_set(DMA_MEMCPY, cap_mask); + + /* get DMA parameters from controller type */ + atdmatype = platform_get_device_id(pdev)->driver_data; - /* get DMA Controller parameters from platform */ - pdata = pdev->dev.platform_data; - if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS) + switch (atdmatype) { + case ATDMA_DEVTYPE_SAM9RL: + nr_channels = 2; + break; + case ATDMA_DEVTYPE_SAM9G45: + nr_channels = 8; + dma_cap_set(DMA_SLAVE, cap_mask); + break; + default: return -EINVAL; + } io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) @@ -1215,14 +1241,15 @@ static int __init at_dma_probe(struct platform_device *pdev) return irq; size = sizeof(struct at_dma); - size += pdata->nr_channels * sizeof(struct at_dma_chan); + size += nr_channels * sizeof(struct at_dma_chan); atdma = kzalloc(size, GFP_KERNEL); if (!atdma) return -ENOMEM; - /* discover transaction capabilites from the platform data */ - atdma->dma_common.cap_mask = pdata->cap_mask; - atdma->all_chan_mask = (1 << pdata->nr_channels) - 1; + /* discover transaction capabilities */ + atdma->dma_common.cap_mask = cap_mask; + atdma->all_chan_mask = (1 << nr_channels) - 1; + atdma->devtype = atdmatype; size = resource_size(io); if (!request_mem_region(io->start, size, pdev->dev.driver->name)) { @@ -1268,7 +1295,7 @@ static int __init at_dma_probe(struct platform_device *pdev) /* initialize channels related values */ INIT_LIST_HEAD(&atdma->dma_common.channels); - for (i = 0; i < pdata->nr_channels; i++) { + for (i = 0; i < nr_channels; i++) { struct at_dma_chan *atchan = &atdma->chan[i]; atchan->chan_common.device = &atdma->dma_common; @@ -1313,7 +1340,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "", dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", - pdata->nr_channels); + nr_channels); dma_async_device_register(&atdma->dma_common); @@ -1495,6 +1522,7 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = { static struct platform_driver at_dma_driver = { .remove = __exit_p(at_dma_remove), .shutdown = at_dma_shutdown, + .id_table = atdma_devtypes, .driver = { .name = "at_hdmac", .pm = &at_dma_dev_pm_ops, diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index aa4c9ae..d7d6737 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -248,9 +248,16 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) /*-- Controller ------------------------------------------------------*/ +enum atdma_devtype { + ATDMA_DEVTYPE_UNDEFINED = 0, + ATDMA_DEVTYPE_SAM9RL, /* compatible with SAM9RL DMA controller */ + ATDMA_DEVTYPE_SAM9G45, /* compatible with SAM9G45 DMA controller */ +}; + /** * struct at_dma - internal representation of an Atmel HDMA Controller * @chan_common: common dmaengine dma_device object members + * @atdma_devtype: identifier of DMA controller compatibility * @ch_regs: memory mapped register base * @clk: dma controller clock * @save_imr: interrupt mask register that is saved on suspend/resume cycle @@ -260,6 +267,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) */ struct at_dma { struct dma_device dma_common; + enum atdma_devtype devtype; void __iomem *regs; struct clk *clk; u32 save_imr; -- cgit v0.10.2 From c511595390a373e19a774246c659b4f563a4c3f3 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 17 Oct 2011 14:56:41 +0200 Subject: dmaengine: at_hdmac: add device tree support Add device tree probe support for atmel at_hdmac DMA driver. Bindings are added to specify DMA controller configuration. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Vinod Koul diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt new file mode 100644 index 0000000..3c046ee --- /dev/null +++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt @@ -0,0 +1,14 @@ +* Atmel Direct Memory Access Controller (DMA) + +Required properties: +- compatible: Should be "atmel,-dma" +- reg: Should contain DMA registers location and length +- interrupts: Should contain DMA interrupt + +Examples: + +dma@ffffec00 { + compatible = "atmel,at91sam9g45-dma"; + reg = <0xffffec00 0x200>; + interrupts = <21>; +}; diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index d1869c5..f3cb4a0 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "at_hdmac_regs.h" @@ -1175,6 +1177,20 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +#if defined(CONFIG_OF) +static const struct of_device_id atmel_dma_dt_ids[] = { + { + .compatible = "atmel,at91sam9rl-dma", + .data = (void *)ATDMA_DEVTYPE_SAM9RL + }, { + .compatible = "atmel,at91sam9g45-dma", + .data = (void *)ATDMA_DEVTYPE_SAM9G45 + }, { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); +#endif + static struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", @@ -1187,6 +1203,19 @@ static struct platform_device_id atdma_devtypes[] = { } }; +static inline enum atdma_devtype __init at_dma_get_driver_data( + struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node); + if (match == NULL) + return ATDMA_DEVTYPE_UNDEFINED; + return (enum atdma_devtype)match->data; + } + return platform_get_device_id(pdev)->driver_data; +} + /** * at_dma_off - disable DMA controller * @atdma: the Atmel HDAMC device @@ -1218,7 +1247,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_MEMCPY, cap_mask); /* get DMA parameters from controller type */ - atdmatype = platform_get_device_id(pdev)->driver_data; + atdmatype = at_dma_get_driver_data(pdev); switch (atdmatype) { case ATDMA_DEVTYPE_SAM9RL: @@ -1526,6 +1555,7 @@ static struct platform_driver at_dma_driver = { .driver = { .name = "at_hdmac", .pm = &at_dma_dev_pm_ops, + .of_match_table = of_match_ptr(atmel_dma_dt_ids), }, }; -- cgit v0.10.2 From dab6538e29e68af6206ec1889c847b428f290989 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Thu, 3 Nov 2011 15:48:49 +0900 Subject: DMA: PL330: Fix build warning This patch adds to fix the build warning as following. drivers/dma/pl330.c: In function 'pl330_probe': drivers/dma/pl330.c:859: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Boojin Kim Signed-off-by: Vinod Koul diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 57104147..186b822 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -856,7 +856,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) INIT_LIST_HEAD(&pd->channels); /* Initialize channel parameters */ - num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan); + num_chan = max(pdat ? (int)pdat->nr_valid_peri : 0, + (int)pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); for (i = 0; i < num_chan; i++) { -- cgit v0.10.2 From dbb004294a934d030a9d716692a1dd6f677fc90e Mon Sep 17 00:00:00 2001 From: Ciaran McCormick Date: Mon, 31 Oct 2011 19:29:26 +0000 Subject: dma: fix spacing for method declaration, coding style issue in iop-adma.c Signed-off-by: Ciaran McCormick Signed-off-by: Vinod Koul diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index e03f811..686dc76 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -1746,12 +1746,12 @@ static struct platform_driver iop_adma_driver = { }, }; -static int __init iop_adma_init (void) +static int __init iop_adma_init(void) { return platform_driver_register(&iop_adma_driver); } -static void __exit iop_adma_exit (void) +static void __exit iop_adma_exit(void) { platform_driver_unregister(&iop_adma_driver); return; -- cgit v0.10.2 From 8e2d41f8c85613a3739e8b2600ac2c66c08422f3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 24 Aug 2011 08:41:09 +0200 Subject: dma i.MX: remove individual SOC dependency The individual SoC dependency in Kconfig hardly scales anymore. Instead of having such a fine grained dependency just depend on ARCH_MXC and risk that the uninformed user has to look in the help text to figure out which driver is the correct one. Signed-off-by: Sascha Hauer Cc: Vinod Koul Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ab8f469..e514c45 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -124,7 +124,7 @@ config MV_XOR config MX3_IPU bool "MX3x Image Processing Unit support" - depends on ARCH_MX3 + depends on ARCH_MXC select DMA_ENGINE default y help @@ -216,11 +216,11 @@ config PCH_DMA config IMX_SDMA tristate "i.MX SDMA support" - depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5 + depends on ARCH_MXC select DMA_ENGINE help Support the i.MX SDMA engine. This engine is integrated into - Freescale i.MX25/31/35/51 chips. + Freescale i.MX25/31/35/51/53 chips. config IMX_DMA tristate "i.MX DMA support" -- cgit v0.10.2 From e79e72be298dc4726a641686032b8296c2fb473e Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 17 Nov 2011 16:14:22 +0900 Subject: pch_dma: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor On October 1 in 2011, OKI SEMICONDUCTOR Co., Ltd. changed the company name in to LAPIS Semiconductor Co., Ltd. Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index e514c45..606592e 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -201,13 +201,13 @@ config PL330_DMA platform_data for a dma-pl330 device. config PCH_DMA - tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223) DMA support" + tristate "Intel EG20T PCH / LAPIS Semi IOH(ML7213/ML7223) DMA support" depends on PCI && X86 select DMA_ENGINE help Enable support for Intel EG20T PCH DMA engine. - This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ + This driver also can be used for LAPIS Semiconductor IOH(Input/ Output Hub), ML7213 and ML7223. ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is for MP(Media Phone) use. diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a6d0e3d..a9b8a79 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -1,7 +1,7 @@ /* * Topcliff PCH DMA controller driver * Copyright (c) 2010 Intel Corporation - * Copyright (C) 2011 OKI SEMICONDUCTOR CO., LTD. + * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1057,7 +1057,7 @@ static void __exit pch_dma_exit(void) module_init(pch_dma_init); module_exit(pch_dma_exit); -MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH " +MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semiconductor ML7213/ML7223 IOH " "DMA controller driver"); MODULE_AUTHOR("Yong Wang "); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From ca7fe2db892dcf91b2c72ee352eda4ff867903a7 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 17 Nov 2011 16:14:23 +0900 Subject: pch_dma: Support new device LAPIS Semiconductor ML7831 IOH ML7831 is companion chip for Intel Atom E6xx series. Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 606592e..7ec0d6c 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -201,18 +201,18 @@ config PL330_DMA platform_data for a dma-pl330 device. config PCH_DMA - tristate "Intel EG20T PCH / LAPIS Semi IOH(ML7213/ML7223) DMA support" + tristate "Intel EG20T PCH / LAPIS Semicon IOH(ML7213/ML7223/ML7831) DMA" depends on PCI && X86 select DMA_ENGINE help Enable support for Intel EG20T PCH DMA engine. This driver also can be used for LAPIS Semiconductor IOH(Input/ - Output Hub), ML7213 and ML7223. - ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is - for MP(Media Phone) use. - ML7213/ML7223 is companion chip for Intel Atom E6xx series. - ML7213/ML7223 is completely compatible for Intel EG20T PCH. + Output Hub), ML7213, ML7223 and ML7831. + ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is + for MP(Media Phone) use and ML7831 IOH is for general purpose use. + ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. + ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. config IMX_SDMA tristate "i.MX SDMA support" diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a9b8a79..60aca37 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -1018,6 +1018,8 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev) #define PCI_DEVICE_ID_ML7223_DMA2_4CH 0x800E #define PCI_DEVICE_ID_ML7223_DMA3_4CH 0x8017 #define PCI_DEVICE_ID_ML7223_DMA4_4CH 0x803B +#define PCI_DEVICE_ID_ML7831_DMA1_8CH 0x8810 +#define PCI_DEVICE_ID_ML7831_DMA2_4CH 0x8815 DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 }, @@ -1030,6 +1032,8 @@ DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = { { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */ + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA1_8CH), 8}, /* UART */ + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA2_4CH), 4}, /* SPI */ { 0, }, }; @@ -1057,7 +1061,7 @@ static void __exit pch_dma_exit(void) module_init(pch_dma_init); module_exit(pch_dma_exit); -MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semiconductor ML7213/ML7223 IOH " +MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH " "DMA controller driver"); MODULE_AUTHOR("Yong Wang "); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8341544c9d95610f86b560333c7b22dd1096ca4f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 21:50:31 +0530 Subject: USB-musb: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves usb/musb driver to use new enum Signed-off-by: Vinod Koul Cc: Felipe Balbi Cc: Greg Kroah-Hartman Acked-by: Felipe Balbi Acked-by: Mian Yousaf Kaukab diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index ef4333f..f8fd0dd 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -112,7 +112,7 @@ static bool ux500_configure_channel(struct dma_channel *channel, struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; struct dma_chan *dma_chan = ux500_channel->dma_chan; struct dma_async_tx_descriptor *dma_desc; - enum dma_data_direction direction; + enum dma_transfer_direction direction; struct scatterlist sg; struct dma_slave_config slave_conf; enum dma_slave_buswidth addr_width; @@ -132,7 +132,7 @@ static bool ux500_configure_channel(struct dma_channel *channel, sg_dma_address(&sg) = dma_addr; sg_dma_len(&sg) = len; - direction = ux500_channel->is_tx ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + direction = ux500_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; addr_width = (len & 0x3) ? DMA_SLAVE_BUSWIDTH_1_BYTE : DMA_SLAVE_BUSWIDTH_4_BYTES; -- cgit v0.10.2 From 55ba4e5ed4ac57b60fe56acfd324f6a87123cc34 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 21:57:58 +0530 Subject: USB-renesas: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves usb/renesas driver to use new enum Signed-off-by: Vinod Koul Cc: Felipe Balbi Cc: Greg Kroah-Hartman Acked-by: Felipe Balbi Acked-by: Kuninori Morimoto diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index a34430f..051c9a9 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -591,10 +591,10 @@ static void usbhsf_dma_prepare_tasklet(unsigned long data) struct dma_async_tx_descriptor *desc; struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); struct device *dev = usbhs_priv_to_dev(priv); - enum dma_data_direction dir; + enum dma_transfer_direction dir; dma_cookie_t cookie; - dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; sg_init_table(&sg, 1); sg_set_page(&sg, virt_to_page(pkt->dma), -- cgit v0.10.2 From b14dab792dee3245b628e046d80a7fad5573fea6 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 13 Oct 2011 12:33:30 +0530 Subject: DMAEngine: Define interleaved transfer request api Define a new api that could be used for doing fancy data transfers like interleaved to contiguous copy and vice-versa. Traditional SG_list based transfers tend to be very inefficient in such cases as where the interleave and chunk are only a few bytes, which call for a very condensed api to convey pattern of the transfer. This api supports all 4 variants of scatter-gather and contiguous transfer. Of course, neither can this api help transfers that don't lend to DMA by nature, i.e, scattered tiny read/writes with no periodic pattern. Also since now we support SLAVE channels that might not provide device_prep_slave_sg callback but device_prep_interleaved_dma, remove the BUG_ON check. Signed-off-by: Jassi Brar Acked-by: Barry Song [renamed dmaxfer_template to dma_interleaved_template did fixup after the enum dma_transfer_merge] Signed-off-by: Vinod Koul diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt index 94b7e0f..bbe6cb3 100644 --- a/Documentation/dmaengine.txt +++ b/Documentation/dmaengine.txt @@ -75,6 +75,10 @@ The slave DMA usage consists of following steps: slave_sg - DMA a list of scatter gather buffers from/to a peripheral dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. + interleaved_dma - This is common to Slave as well as M2M clients. For slave + address of devices' fifo could be already known to the driver. + Various types of operations could be expressed by setting + appropriate values to the 'dma_interleaved_template' members. A non-NULL return of this transfer API represents a "descriptor" for the given transaction. @@ -89,6 +93,10 @@ The slave DMA usage consists of following steps: struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); + The peripheral driver is expected to have mapped the scatterlist for the DMA operation prior to calling device_prep_slave_sg, and must keep the scatterlist mapped until the DMA operation has completed. diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index b48967b..a6c6051 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -693,12 +693,12 @@ int dma_async_device_register(struct dma_device *device) !device->device_prep_dma_interrupt); BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) && !device->device_prep_dma_sg); - BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && - !device->device_prep_slave_sg); BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) && !device->device_prep_dma_cyclic); BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->device_control); + BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) && + !device->device_prep_interleaved_dma); BUG_ON(!device->device_alloc_chan_resources); BUG_ON(!device->device_free_chan_resources); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index a865b3a..5532bb8 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -71,10 +71,10 @@ enum dma_transaction_type { DMA_ASYNC_TX, DMA_SLAVE, DMA_CYCLIC, -}; - + DMA_INTERLEAVE, /* last transaction type for creation of the capabilities mask */ -#define DMA_TX_TYPE_END (DMA_CYCLIC + 1) + DMA_TX_TYPE_END, +}; /** * enum dma_transfer_direction - dma transfer mode and direction indicator @@ -91,6 +91,74 @@ enum dma_transfer_direction { }; /** + * Interleaved Transfer Request + * ---------------------------- + * A chunk is collection of contiguous bytes to be transfered. + * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). + * ICGs may or maynot change between chunks. + * A FRAME is the smallest series of contiguous {chunk,icg} pairs, + * that when repeated an integral number of times, specifies the transfer. + * A transfer template is specification of a Frame, the number of times + * it is to be repeated and other per-transfer attributes. + * + * Practically, a client driver would have ready a template for each + * type of transfer it is going to need during its lifetime and + * set only 'src_start' and 'dst_start' before submitting the requests. + * + * + * | Frame-1 | Frame-2 | ~ | Frame-'numf' | + * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| + * + * == Chunk size + * ... ICG + */ + +/** + * struct data_chunk - Element of scatter-gather list that makes a frame. + * @size: Number of bytes to read from source. + * size_dst := fn(op, size_src), so doesn't mean much for destination. + * @icg: Number of bytes to jump after last src/dst address of this + * chunk and before first src/dst address for next chunk. + * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. + * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. + */ +struct data_chunk { + size_t size; + size_t icg; +}; + +/** + * struct dma_interleaved_template - Template to convey DMAC the transfer pattern + * and attributes. + * @src_start: Bus address of source for the first chunk. + * @dst_start: Bus address of destination for the first chunk. + * @dir: Specifies the type of Source and Destination. + * @src_inc: If the source address increments after reading from it. + * @dst_inc: If the destination address increments after writing to it. + * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). + * Otherwise, source is read contiguously (icg ignored). + * Ignored if src_inc is false. + * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). + * Otherwise, destination is filled contiguously (icg ignored). + * Ignored if dst_inc is false. + * @numf: Number of frames in this template. + * @frame_size: Number of chunks in a frame i.e, size of sgl[]. + * @sgl: Array of {chunk,icg} pairs that make up a frame. + */ +struct dma_interleaved_template { + dma_addr_t src_start; + dma_addr_t dst_start; + enum dma_transfer_direction dir; + bool src_inc; + bool dst_inc; + bool src_sgl; + bool dst_sgl; + size_t numf; + size_t frame_size; + struct data_chunk sgl[0]; +}; + +/** * enum dma_ctrl_flags - DMA flags to augment operation preparation, * control completion, and communicate status. * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of @@ -445,6 +513,7 @@ struct dma_tx_state { * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. * The function takes a buffer of size buf_len. The callback function will * be called after period_len bytes have been transferred. + * @device_prep_interleaved_dma: Transfer expression in a generic way. * @device_control: manipulate all pending operations on a channel, returns * zero or error code * @device_tx_status: poll for transaction completion, the optional @@ -509,6 +578,9 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); -- cgit v0.10.2 From ca21a146a45a179a2a7bc86d938a2fbf571a7510 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Thu, 27 Oct 2011 19:22:39 -0700 Subject: dmaengine: add CSR SiRFprimaII DMAC driver Cc: Jassi Brar Cc: Arnd Bergmann Cc: Linus Walleij Signed-off-by: Rongjun Ying Signed-off-by: Barry Song [fixed direction enums and cyclic api based on changes already merged] Signed-off-by: Vinod Koul diff --git a/MAINTAINERS b/MAINTAINERS index 4808256..1b141d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -749,6 +749,7 @@ M: Barry Song L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-prima2/ +F: drivers/dma/sirf-dma* ARM/EBSA110 MACHINE SUPPORT M: Russell King diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 7ec0d6c..f1a2749 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -187,6 +187,13 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. +config SIRF_DMA + tristate "CSR SiRFprimaII DMA support" + depends on ARCH_PRIMA2 + select DMA_ENGINE + help + Enable support for the CSR SiRFprimaII DMA engine. + config ARCH_HAS_ASYNC_TX_FIND_CHANNEL bool diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 30cf3b1..009a222 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o obj-$(CONFIG_IMX_DMA) += imx-dma.o obj-$(CONFIG_MXS_DMA) += mxs-dma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o +obj-$(CONFIG_SIRF_DMA) += sirf-dma.o obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o obj-$(CONFIG_PL330_DMA) += pl330.o obj-$(CONFIG_PCH_DMA) += pch_dma.o diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c new file mode 100644 index 0000000..55ec679 --- /dev/null +++ b/drivers/dma/sirf-dma.c @@ -0,0 +1,717 @@ +/* + * DMA controller driver for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_DMA_DESCRIPTORS 16 +#define SIRFSOC_DMA_CHANNELS 16 + +#define SIRFSOC_DMA_CH_ADDR 0x00 +#define SIRFSOC_DMA_CH_XLEN 0x04 +#define SIRFSOC_DMA_CH_YLEN 0x08 +#define SIRFSOC_DMA_CH_CTRL 0x0C + +#define SIRFSOC_DMA_WIDTH_0 0x100 +#define SIRFSOC_DMA_CH_VALID 0x140 +#define SIRFSOC_DMA_CH_INT 0x144 +#define SIRFSOC_DMA_INT_EN 0x148 +#define SIRFSOC_DMA_CH_LOOP_CTRL 0x150 + +#define SIRFSOC_DMA_MODE_CTRL_BIT 4 +#define SIRFSOC_DMA_DIR_CTRL_BIT 5 + +/* xlen and dma_width register is in 4 bytes boundary */ +#define SIRFSOC_DMA_WORD_LEN 4 + +struct sirfsoc_dma_desc { + struct dma_async_tx_descriptor desc; + struct list_head node; + + /* SiRFprimaII 2D-DMA parameters */ + + int xlen; /* DMA xlen */ + int ylen; /* DMA ylen */ + int width; /* DMA width */ + int dir; + bool cyclic; /* is loop DMA? */ + u32 addr; /* DMA buffer address */ +}; + +struct sirfsoc_dma_chan { + struct dma_chan chan; + struct list_head free; + struct list_head prepared; + struct list_head queued; + struct list_head active; + struct list_head completed; + dma_cookie_t completed_cookie; + unsigned long happened_cyclic; + unsigned long completed_cyclic; + + /* Lock for this structure */ + spinlock_t lock; + + int mode; +}; + +struct sirfsoc_dma { + struct dma_device dma; + struct tasklet_struct tasklet; + struct sirfsoc_dma_chan channels[SIRFSOC_DMA_CHANNELS]; + void __iomem *base; + int irq; +}; + +#define DRV_NAME "sirfsoc_dma" + +/* Convert struct dma_chan to struct sirfsoc_dma_chan */ +static inline +struct sirfsoc_dma_chan *dma_chan_to_sirfsoc_dma_chan(struct dma_chan *c) +{ + return container_of(c, struct sirfsoc_dma_chan, chan); +} + +/* Convert struct dma_chan to struct sirfsoc_dma */ +static inline struct sirfsoc_dma *dma_chan_to_sirfsoc_dma(struct dma_chan *c) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(c); + return container_of(schan, struct sirfsoc_dma, channels[c->chan_id]); +} + +/* Execute all queued DMA descriptors */ +static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); + int cid = schan->chan.chan_id; + struct sirfsoc_dma_desc *sdesc = NULL; + + /* + * lock has been held by functions calling this, so we don't hold + * lock again + */ + + sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, + node); + /* Move the first queued descriptor to active list */ + list_move_tail(&schan->queued, &schan->active); + + /* Start the DMA transfer */ + writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + + cid * 4); + writel_relaxed(cid | (schan->mode << SIRFSOC_DMA_MODE_CTRL_BIT) | + (sdesc->dir << SIRFSOC_DMA_DIR_CTRL_BIT), + sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_CTRL); + writel_relaxed(sdesc->xlen, sdma->base + cid * 0x10 + + SIRFSOC_DMA_CH_XLEN); + writel_relaxed(sdesc->ylen, sdma->base + cid * 0x10 + + SIRFSOC_DMA_CH_YLEN); + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) | + (1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); + + /* + * writel has an implict memory write barrier to make sure data is + * flushed into memory before starting DMA + */ + writel(sdesc->addr >> 2, sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_ADDR); + + if (sdesc->cyclic) { + writel((1 << cid) | 1 << (cid + 16) | + readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL), + sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); + schan->happened_cyclic = schan->completed_cyclic = 0; + } +} + +/* Interrupt handler */ +static irqreturn_t sirfsoc_dma_irq(int irq, void *data) +{ + struct sirfsoc_dma *sdma = data; + struct sirfsoc_dma_chan *schan; + struct sirfsoc_dma_desc *sdesc = NULL; + u32 is; + int ch; + + is = readl(sdma->base + SIRFSOC_DMA_CH_INT); + while ((ch = fls(is) - 1) >= 0) { + is &= ~(1 << ch); + writel_relaxed(1 << ch, sdma->base + SIRFSOC_DMA_CH_INT); + schan = &sdma->channels[ch]; + + spin_lock(&schan->lock); + + sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc, + node); + if (!sdesc->cyclic) { + /* Execute queued descriptors */ + list_splice_tail_init(&schan->active, &schan->completed); + if (!list_empty(&schan->queued)) + sirfsoc_dma_execute(schan); + } else + schan->happened_cyclic++; + + spin_unlock(&schan->lock); + } + + /* Schedule tasklet */ + tasklet_schedule(&sdma->tasklet); + + return IRQ_HANDLED; +} + +/* process completed descriptors */ +static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma) +{ + dma_cookie_t last_cookie = 0; + struct sirfsoc_dma_chan *schan; + struct sirfsoc_dma_desc *sdesc; + struct dma_async_tx_descriptor *desc; + unsigned long flags; + unsigned long happened_cyclic; + LIST_HEAD(list); + int i; + + for (i = 0; i < sdma->dma.chancnt; i++) { + schan = &sdma->channels[i]; + + /* Get all completed descriptors */ + spin_lock_irqsave(&schan->lock, flags); + if (!list_empty(&schan->completed)) { + list_splice_tail_init(&schan->completed, &list); + spin_unlock_irqrestore(&schan->lock, flags); + + /* Execute callbacks and run dependencies */ + list_for_each_entry(sdesc, &list, node) { + desc = &sdesc->desc; + + if (desc->callback) + desc->callback(desc->callback_param); + + last_cookie = desc->cookie; + dma_run_dependencies(desc); + } + + /* Free descriptors */ + spin_lock_irqsave(&schan->lock, flags); + list_splice_tail_init(&list, &schan->free); + schan->completed_cookie = last_cookie; + spin_unlock_irqrestore(&schan->lock, flags); + } else { + /* for cyclic channel, desc is always in active list */ + sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc, + node); + + if (!sdesc || (sdesc && !sdesc->cyclic)) { + /* without active cyclic DMA */ + spin_unlock_irqrestore(&schan->lock, flags); + continue; + } + + /* cyclic DMA */ + happened_cyclic = schan->happened_cyclic; + spin_unlock_irqrestore(&schan->lock, flags); + + desc = &sdesc->desc; + while (happened_cyclic != schan->completed_cyclic) { + if (desc->callback) + desc->callback(desc->callback_param); + schan->completed_cyclic++; + } + } + } +} + +/* DMA Tasklet */ +static void sirfsoc_dma_tasklet(unsigned long data) +{ + struct sirfsoc_dma *sdma = (void *)data; + + sirfsoc_dma_process_completed(sdma); +} + +/* Submit descriptor to hardware */ +static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(txd->chan); + struct sirfsoc_dma_desc *sdesc; + unsigned long flags; + dma_cookie_t cookie; + + sdesc = container_of(txd, struct sirfsoc_dma_desc, desc); + + spin_lock_irqsave(&schan->lock, flags); + + /* Move descriptor to queue */ + list_move_tail(&sdesc->node, &schan->queued); + + /* Update cookie */ + cookie = schan->chan.cookie + 1; + if (cookie <= 0) + cookie = 1; + + schan->chan.cookie = cookie; + sdesc->desc.cookie = cookie; + + spin_unlock_irqrestore(&schan->lock, flags); + + return cookie; +} + +static int sirfsoc_dma_slave_config(struct sirfsoc_dma_chan *schan, + struct dma_slave_config *config) +{ + unsigned long flags; + + if ((config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || + (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)) + return -EINVAL; + + spin_lock_irqsave(&schan->lock, flags); + schan->mode = (config->src_maxburst == 4 ? 1 : 0); + spin_unlock_irqrestore(&schan->lock, flags); + + return 0; +} + +static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); + int cid = schan->chan.chan_id; + unsigned long flags; + + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) & + ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); + writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_CH_VALID); + + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) + & ~((1 << cid) | 1 << (cid + 16)), + sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); + + spin_lock_irqsave(&schan->lock, flags); + list_splice_tail_init(&schan->active, &schan->free); + list_splice_tail_init(&schan->queued, &schan->free); + spin_unlock_irqrestore(&schan->lock, flags); + + return 0; +} + +static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + struct dma_slave_config *config; + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + + switch (cmd) { + case DMA_TERMINATE_ALL: + return sirfsoc_dma_terminate_all(schan); + case DMA_SLAVE_CONFIG: + config = (struct dma_slave_config *)arg; + return sirfsoc_dma_slave_config(schan, config); + + default: + break; + } + + return -ENOSYS; +} + +/* Alloc channel resources */ +static int sirfsoc_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan); + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc; + unsigned long flags; + LIST_HEAD(descs); + int i; + + /* Alloc descriptors for this channel */ + for (i = 0; i < SIRFSOC_DMA_DESCRIPTORS; i++) { + sdesc = kzalloc(sizeof(*sdesc), GFP_KERNEL); + if (!sdesc) { + dev_notice(sdma->dma.dev, "Memory allocation error. " + "Allocated only %u descriptors\n", i); + break; + } + + dma_async_tx_descriptor_init(&sdesc->desc, chan); + sdesc->desc.flags = DMA_CTRL_ACK; + sdesc->desc.tx_submit = sirfsoc_dma_tx_submit; + + list_add_tail(&sdesc->node, &descs); + } + + /* Return error only if no descriptors were allocated */ + if (i == 0) + return -ENOMEM; + + spin_lock_irqsave(&schan->lock, flags); + + list_splice_tail_init(&descs, &schan->free); + spin_unlock_irqrestore(&schan->lock, flags); + + return i; +} + +/* Free channel resources */ +static void sirfsoc_dma_free_chan_resources(struct dma_chan *chan) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc, *tmp; + unsigned long flags; + LIST_HEAD(descs); + + spin_lock_irqsave(&schan->lock, flags); + + /* Channel must be idle */ + BUG_ON(!list_empty(&schan->prepared)); + BUG_ON(!list_empty(&schan->queued)); + BUG_ON(!list_empty(&schan->active)); + BUG_ON(!list_empty(&schan->completed)); + + /* Move data */ + list_splice_tail_init(&schan->free, &descs); + + spin_unlock_irqrestore(&schan->lock, flags); + + /* Free descriptors */ + list_for_each_entry_safe(sdesc, tmp, &descs, node) + kfree(sdesc); +} + +/* Send pending descriptor to hardware */ +static void sirfsoc_dma_issue_pending(struct dma_chan *chan) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&schan->lock, flags); + + if (list_empty(&schan->active) && !list_empty(&schan->queued)) + sirfsoc_dma_execute(schan); + + spin_unlock_irqrestore(&schan->lock, flags); +} + +/* Check request completion status */ +static enum dma_status +sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + unsigned long flags; + dma_cookie_t last_used; + dma_cookie_t last_complete; + + spin_lock_irqsave(&schan->lock, flags); + last_used = schan->chan.cookie; + last_complete = schan->completed_cookie; + spin_unlock_irqrestore(&schan->lock, flags); + + dma_set_tx_state(txstate, last_complete, last_used, 0); + return dma_async_is_complete(cookie, last_complete, last_used); +} + +static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan); + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc = NULL; + unsigned long iflags; + int ret; + + if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + ret = -EINVAL; + goto err_dir; + } + + /* Get free descriptor */ + spin_lock_irqsave(&schan->lock, iflags); + if (!list_empty(&schan->free)) { + sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc, + node); + list_del(&sdesc->node); + } + spin_unlock_irqrestore(&schan->lock, iflags); + + if (!sdesc) { + /* try to free completed descriptors */ + sirfsoc_dma_process_completed(sdma); + ret = 0; + goto no_desc; + } + + /* Place descriptor in prepared list */ + spin_lock_irqsave(&schan->lock, iflags); + + /* + * Number of chunks in a frame can only be 1 for prima2 + * and ylen (number of frame - 1) must be at least 0 + */ + if ((xt->frame_size == 1) && (xt->numf > 0)) { + sdesc->cyclic = 0; + sdesc->xlen = xt->sgl[0].size / SIRFSOC_DMA_WORD_LEN; + sdesc->width = (xt->sgl[0].size + xt->sgl[0].icg) / + SIRFSOC_DMA_WORD_LEN; + sdesc->ylen = xt->numf - 1; + if (xt->dir == DMA_MEM_TO_DEV) { + sdesc->addr = xt->src_start; + sdesc->dir = 1; + } else { + sdesc->addr = xt->dst_start; + sdesc->dir = 0; + } + + list_add_tail(&sdesc->node, &schan->prepared); + } else { + pr_err("sirfsoc DMA Invalid xfer\n"); + ret = -EINVAL; + goto err_xfer; + } + spin_unlock_irqrestore(&schan->lock, iflags); + + return &sdesc->desc; +err_xfer: + spin_unlock_irqrestore(&schan->lock, iflags); +no_desc: +err_dir: + return ERR_PTR(ret); +} + +static struct dma_async_tx_descriptor * +sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr, + size_t buf_len, size_t period_len, + enum dma_transfer_direction direction) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc = NULL; + unsigned long iflags; + + /* + * we only support cycle transfer with 2 period + * If the X-length is set to 0, it would be the loop mode. + * The DMA address keeps increasing until reaching the end of a loop + * area whose size is defined by (DMA_WIDTH x (Y_LENGTH + 1)). Then + * the DMA address goes back to the beginning of this area. + * In loop mode, the DMA data region is divided into two parts, BUFA + * and BUFB. DMA controller generates interrupts twice in each loop: + * when the DMA address reaches the end of BUFA or the end of the + * BUFB + */ + if (buf_len != 2 * period_len) + return ERR_PTR(-EINVAL); + + /* Get free descriptor */ + spin_lock_irqsave(&schan->lock, iflags); + if (!list_empty(&schan->free)) { + sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc, + node); + list_del(&sdesc->node); + } + spin_unlock_irqrestore(&schan->lock, iflags); + + if (!sdesc) + return 0; + + /* Place descriptor in prepared list */ + spin_lock_irqsave(&schan->lock, iflags); + sdesc->addr = addr; + sdesc->cyclic = 1; + sdesc->xlen = 0; + sdesc->ylen = buf_len / SIRFSOC_DMA_WORD_LEN - 1; + sdesc->width = 1; + list_add_tail(&sdesc->node, &schan->prepared); + spin_unlock_irqrestore(&schan->lock, iflags); + + return &sdesc->desc; +} + +/* + * The DMA controller consists of 16 independent DMA channels. + * Each channel is allocated to a different function + */ +bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id) +{ + unsigned int ch_nr = (unsigned int) chan_id; + + if (ch_nr == chan->chan_id + + chan->device->dev_id * SIRFSOC_DMA_CHANNELS) + return true; + + return false; +} +EXPORT_SYMBOL(sirfsoc_dma_filter_id); + +static int __devinit sirfsoc_dma_probe(struct platform_device *op) +{ + struct device_node *dn = op->dev.of_node; + struct device *dev = &op->dev; + struct dma_device *dma; + struct sirfsoc_dma *sdma; + struct sirfsoc_dma_chan *schan; + struct resource res; + ulong regs_start, regs_size; + u32 id; + int ret, i; + + sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL); + if (!sdma) { + dev_err(dev, "Memory exhausted!\n"); + return -ENOMEM; + } + + if (of_property_read_u32(dn, "cell-index", &id)) { + dev_err(dev, "Fail to get DMAC index\n"); + ret = -ENODEV; + goto free_mem; + } + + sdma->irq = irq_of_parse_and_map(dn, 0); + if (sdma->irq == NO_IRQ) { + dev_err(dev, "Error mapping IRQ!\n"); + ret = -EINVAL; + goto free_mem; + } + + ret = of_address_to_resource(dn, 0, &res); + if (ret) { + dev_err(dev, "Error parsing memory region!\n"); + goto free_mem; + } + + regs_start = res.start; + regs_size = resource_size(&res); + + sdma->base = devm_ioremap(dev, regs_start, regs_size); + if (!sdma->base) { + dev_err(dev, "Error mapping memory region!\n"); + ret = -ENOMEM; + goto irq_dispose; + } + + ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME, + sdma); + if (ret) { + dev_err(dev, "Error requesting IRQ!\n"); + ret = -EINVAL; + goto unmap_mem; + } + + dma = &sdma->dma; + dma->dev = dev; + dma->chancnt = SIRFSOC_DMA_CHANNELS; + + dma->device_alloc_chan_resources = sirfsoc_dma_alloc_chan_resources; + dma->device_free_chan_resources = sirfsoc_dma_free_chan_resources; + dma->device_issue_pending = sirfsoc_dma_issue_pending; + dma->device_control = sirfsoc_dma_control; + dma->device_tx_status = sirfsoc_dma_tx_status; + dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved; + dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic; + + INIT_LIST_HEAD(&dma->channels); + dma_cap_set(DMA_SLAVE, dma->cap_mask); + dma_cap_set(DMA_CYCLIC, dma->cap_mask); + dma_cap_set(DMA_INTERLEAVE, dma->cap_mask); + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + + for (i = 0; i < dma->chancnt; i++) { + schan = &sdma->channels[i]; + + schan->chan.device = dma; + schan->chan.cookie = 1; + schan->completed_cookie = schan->chan.cookie; + + INIT_LIST_HEAD(&schan->free); + INIT_LIST_HEAD(&schan->prepared); + INIT_LIST_HEAD(&schan->queued); + INIT_LIST_HEAD(&schan->active); + INIT_LIST_HEAD(&schan->completed); + + spin_lock_init(&schan->lock); + list_add_tail(&schan->chan.device_node, &dma->channels); + } + + tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma); + + /* Register DMA engine */ + dev_set_drvdata(dev, sdma); + ret = dma_async_device_register(dma); + if (ret) + goto free_irq; + + dev_info(dev, "initialized SIRFSOC DMAC driver\n"); + + return 0; + +free_irq: + devm_free_irq(dev, sdma->irq, sdma); +irq_dispose: + irq_dispose_mapping(sdma->irq); +unmap_mem: + iounmap(sdma->base); +free_mem: + devm_kfree(dev, sdma); + return ret; +} + +static int __devexit sirfsoc_dma_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct sirfsoc_dma *sdma = dev_get_drvdata(dev); + + dma_async_device_unregister(&sdma->dma); + devm_free_irq(dev, sdma->irq, sdma); + irq_dispose_mapping(sdma->irq); + iounmap(sdma->base); + devm_kfree(dev, sdma); + return 0; +} + +static struct of_device_id sirfsoc_dma_match[] = { + { .compatible = "sirf,prima2-dmac", }, + {}, +}; + +static struct platform_driver sirfsoc_dma_driver = { + .probe = sirfsoc_dma_probe, + .remove = __devexit_p(sirfsoc_dma_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = sirfsoc_dma_match, + }, +}; + +static int __init sirfsoc_dma_init(void) +{ + return platform_driver_register(&sirfsoc_dma_driver); +} +module_init(sirfsoc_dma_init); + +static void __exit sirfsoc_dma_exit(void) +{ + platform_driver_unregister(&sirfsoc_dma_driver); +} +module_exit(sirfsoc_dma_exit); + +MODULE_AUTHOR("Rongjun Ying , " + "Barry Song "); +MODULE_DESCRIPTION("SIRFSOC DMA control driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/sirfsoc_dma.h b/include/linux/sirfsoc_dma.h new file mode 100644 index 0000000..29d9593 --- /dev/null +++ b/include/linux/sirfsoc_dma.h @@ -0,0 +1,6 @@ +#ifndef _SIRFSOC_DMA_H_ +#define _SIRFSOC_DMA_H_ + +bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id); + +#endif -- cgit v0.10.2 From 7fb3e75e1833743d5faf3adbae46b63f503c6fdf Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Thu, 17 Nov 2011 17:26:41 +0530 Subject: dmaengine/ste_dma40: support pm in dma40 This patch adds power management support to the dma40 driver. The DMA registers are backed up and restored, during suspend/resume. Also flags to track the dma usage have been introduced to facilitate this. Patch also includes few other minor changes, related to formatting, comments. Signed-off-by: Narayanan G Acked-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 15b311d5..c2cf8cf 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -32,6 +34,9 @@ /* Maximum iterations taken before giving up suspending a channel */ #define D40_SUSPEND_MAX_IT 500 +/* Milliseconds */ +#define DMA40_AUTOSUSPEND_DELAY 100 + /* Hardware requirement on LCLA alignment */ #define LCLA_ALIGNMENT 0x40000 @@ -62,6 +67,55 @@ enum d40_command { D40_DMA_SUSPENDED = 3 }; +/* + * These are the registers that has to be saved and later restored + * when the DMA hw is powered off. + * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works. + */ +static u32 d40_backup_regs[] = { + D40_DREG_LCPA, + D40_DREG_LCLA, + D40_DREG_PRMSE, + D40_DREG_PRMSO, + D40_DREG_PRMOE, + D40_DREG_PRMOO, +}; + +#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs) + +/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */ +static u32 d40_backup_regs_v3[] = { + D40_DREG_PSEG1, + D40_DREG_PSEG2, + D40_DREG_PSEG3, + D40_DREG_PSEG4, + D40_DREG_PCEG1, + D40_DREG_PCEG2, + D40_DREG_PCEG3, + D40_DREG_PCEG4, + D40_DREG_RSEG1, + D40_DREG_RSEG2, + D40_DREG_RSEG3, + D40_DREG_RSEG4, + D40_DREG_RCEG1, + D40_DREG_RCEG2, + D40_DREG_RCEG3, + D40_DREG_RCEG4, +}; + +#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3) + +static u32 d40_backup_regs_chan[] = { + D40_CHAN_REG_SSCFG, + D40_CHAN_REG_SSELT, + D40_CHAN_REG_SSPTR, + D40_CHAN_REG_SSLNK, + D40_CHAN_REG_SDCFG, + D40_CHAN_REG_SDELT, + D40_CHAN_REG_SDPTR, + D40_CHAN_REG_SDLNK, +}; + /** * struct d40_lli_pool - Structure for keeping LLIs in memory * @@ -96,7 +150,7 @@ struct d40_lli_pool { * during a transfer. * @node: List entry. * @is_in_client_list: true if the client owns this descriptor. - * the previous one. + * @cyclic: true if this is a cyclic job * * This descriptor is used for both logical and physical transfers. */ @@ -143,6 +197,7 @@ struct d40_lcla_pool { * channels. * * @lock: A lock protection this entity. + * @reserved: True if used by secure world or otherwise. * @num: The physical channel number of this entity. * @allocated_src: Bit mapped to show which src event line's are mapped to * this physical channel. Can also be free or physically allocated. @@ -152,6 +207,7 @@ struct d40_lcla_pool { */ struct d40_phy_res { spinlock_t lock; + bool reserved; int num; u32 allocated_src; u32 allocated_dst; @@ -185,7 +241,6 @@ struct d40_base; * @src_def_cfg: Default cfg register setting for src. * @dst_def_cfg: Default cfg register setting for dst. * @log_def: Default logical channel settings. - * @lcla: Space for one dst src pair for logical channel transfers. * @lcpa: Pointer to dst and src lcpa settings. * @runtime_addr: runtime configured address. * @runtime_direction: runtime configured direction. @@ -241,6 +296,7 @@ struct d40_chan { * @dma_both: dma_device channels that can do both memcpy and slave transfers. * @dma_slave: dma_device channels that can do only do slave transfers. * @dma_memcpy: dma_device channels that can do only do memcpy transfers. + * @phy_chans: Room for all possible physical channels in system. * @log_chans: Room for all possible logical channels in system. * @lookup_log_chans: Used to map interrupt number to logical channel. Points * to log_chans entries. @@ -254,6 +310,13 @@ struct d40_chan { * @phy_lcpa: The physical address of the LCPA. * @lcpa_size: The size of the LCPA area. * @desc_slab: cache for descriptors. + * @reg_val_backup: Here the values of some hardware registers are stored + * before the DMA is powered off. They are restored when the power is back on. + * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and + * later. + * @reg_val_backup_chan: Backup data for standard channel parameter registers. + * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off. + * @initialized: true if the dma has been initialized */ struct d40_base { spinlock_t interrupt_lock; @@ -282,6 +345,11 @@ struct d40_base { dma_addr_t phy_lcpa; resource_size_t lcpa_size; struct kmem_cache *desc_slab; + u32 reg_val_backup[BACKUP_REGS_SZ]; + u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3]; + u32 *reg_val_backup_chan; + u16 gcc_pwr_off_mask; + bool initialized; }; /** @@ -479,13 +547,14 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c) struct d40_desc *d; struct d40_desc *_d; - list_for_each_entry_safe(d, _d, &d40c->client, node) + list_for_each_entry_safe(d, _d, &d40c->client, node) { if (async_tx_test_ack(&d->txd)) { d40_desc_remove(d); desc = d; memset(desc, 0, sizeof(*desc)); break; } + } } if (!desc) @@ -740,7 +809,61 @@ static int d40_sg_2_dmalen(struct scatterlist *sgl, int sg_len, return len; } -/* Support functions for logical channels */ + +#ifdef CONFIG_PM +static void dma40_backup(void __iomem *baseaddr, u32 *backup, + u32 *regaddr, int num, bool save) +{ + int i; + + for (i = 0; i < num; i++) { + void __iomem *addr = baseaddr + regaddr[i]; + + if (save) + backup[i] = readl_relaxed(addr); + else + writel_relaxed(backup[i], addr); + } +} + +static void d40_save_restore_registers(struct d40_base *base, bool save) +{ + int i; + + /* Save/Restore channel specific registers */ + for (i = 0; i < base->num_phy_chans; i++) { + void __iomem *addr; + int idx; + + if (base->phy_res[i].reserved) + continue; + + addr = base->virtbase + D40_DREG_PCBASE + i * D40_DREG_PCDELTA; + idx = i * ARRAY_SIZE(d40_backup_regs_chan); + + dma40_backup(addr, &base->reg_val_backup_chan[idx], + d40_backup_regs_chan, + ARRAY_SIZE(d40_backup_regs_chan), + save); + } + + /* Save/Restore global registers */ + dma40_backup(base->virtbase, base->reg_val_backup, + d40_backup_regs, ARRAY_SIZE(d40_backup_regs), + save); + + /* Save/Restore registers only existing on dma40 v3 and later */ + if (base->rev >= 3) + dma40_backup(base->virtbase, base->reg_val_backup_v3, + d40_backup_regs_v3, + ARRAY_SIZE(d40_backup_regs_v3), + save); +} +#else +static void d40_save_restore_registers(struct d40_base *base, bool save) +{ +} +#endif static int d40_channel_execute_command(struct d40_chan *d40c, enum d40_command command) @@ -1013,6 +1136,7 @@ static int d40_pause(struct d40_chan *d40c) if (!d40c->busy) return 0; + pm_runtime_get_sync(d40c->base->dev); spin_lock_irqsave(&d40c->lock, flags); res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); @@ -1025,7 +1149,8 @@ static int d40_pause(struct d40_chan *d40c) D40_DMA_RUN); } } - + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return res; } @@ -1039,7 +1164,7 @@ static int d40_resume(struct d40_chan *d40c) return 0; spin_lock_irqsave(&d40c->lock, flags); - + pm_runtime_get_sync(d40c->base->dev); if (d40c->base->rev == 0) if (chan_is_logical(d40c)) { res = d40_channel_execute_command(d40c, @@ -1057,6 +1182,8 @@ static int d40_resume(struct d40_chan *d40c) } no_suspend: + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return res; } @@ -1129,7 +1256,10 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c) d40d = d40_first_queued(d40c); if (d40d != NULL) { - d40c->busy = true; + if (!d40c->busy) + d40c->busy = true; + + pm_runtime_get_sync(d40c->base->dev); /* Remove from queue */ d40_desc_remove(d40d); @@ -1190,6 +1320,8 @@ static void dma_tc_handle(struct d40_chan *d40c) if (d40_queue_start(d40c) == NULL) d40c->busy = false; + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); } d40c->pending_tx++; @@ -1643,10 +1775,11 @@ static int d40_free_dma(struct d40_chan *d40c) return -EINVAL; } + pm_runtime_get_sync(d40c->base->dev); res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); if (res) { chan_err(d40c, "suspend failed\n"); - return res; + goto out; } if (chan_is_logical(d40c)) { @@ -1664,13 +1797,11 @@ static int d40_free_dma(struct d40_chan *d40c) if (d40_chan_has_events(d40c)) { res = d40_channel_execute_command(d40c, D40_DMA_RUN); - if (res) { + if (res) chan_err(d40c, "Executing RUN command\n"); - return res; - } } - return 0; + goto out; } } else { (void) d40_alloc_mask_free(phy, is_src, 0); @@ -1680,13 +1811,23 @@ static int d40_free_dma(struct d40_chan *d40c) res = d40_channel_execute_command(d40c, D40_DMA_STOP); if (res) { chan_err(d40c, "Failed to stop channel\n"); - return res; + goto out; } + + if (d40c->busy) { + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); + } + + d40c->busy = false; d40c->phy_chan = NULL; d40c->configured = false; d40c->base->lookup_phy_chans[phy->num] = NULL; +out: - return 0; + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); + return res; } static bool d40_is_paused(struct d40_chan *d40c) @@ -2016,9 +2157,11 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) err = d40_allocate_channel(d40c); if (err) { chan_err(d40c, "Failed to allocate channel\n"); + d40c->configured = false; goto fail; } + pm_runtime_get_sync(d40c->base->dev); /* Fill in basic CFG register values */ d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg, chan_is_logical(d40c)); @@ -2046,6 +2189,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) if (is_free_phy) d40_config_write(d40c); fail: + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return err; } @@ -2519,6 +2664,55 @@ failure1: return err; } +/* Suspend resume functionality */ +#ifdef CONFIG_PM +static int dma40_pm_suspend(struct device *dev) +{ + if (!pm_runtime_suspended(dev)) + return -EBUSY; + + return 0; +} + +static int dma40_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + + d40_save_restore_registers(base, true); + + /* Don't disable/enable clocks for v1 due to HW bugs */ + if (base->rev != 1) + writel_relaxed(base->gcc_pwr_off_mask, + base->virtbase + D40_DREG_GCC); + + return 0; +} + +static int dma40_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + + if (base->initialized) + d40_save_restore_registers(base, false); + + writel_relaxed(D40_DREG_GCC_ENABLE_ALL, + base->virtbase + D40_DREG_GCC); + return 0; +} + + +static const struct dev_pm_ops dma40_pm_ops = { + .suspend = dma40_pm_suspend, + .runtime_suspend = dma40_runtime_suspend, + .runtime_resume = dma40_runtime_resume, +}; +#define DMA40_PM_OPS (&dma40_pm_ops) +#else +#define DMA40_PM_OPS NULL +#endif + /* Initialization functions. */ static int __init d40_phy_res_init(struct d40_base *base) @@ -2527,6 +2721,7 @@ static int __init d40_phy_res_init(struct d40_base *base) int num_phy_chans_avail = 0; u32 val[2]; int odd_even_bit = -2; + int gcc = D40_DREG_GCC_ENA; val[0] = readl(base->virtbase + D40_DREG_PRSME); val[1] = readl(base->virtbase + D40_DREG_PRSMO); @@ -2538,9 +2733,17 @@ static int __init d40_phy_res_init(struct d40_base *base) /* Mark security only channels as occupied */ base->phy_res[i].allocated_src = D40_ALLOC_PHY; base->phy_res[i].allocated_dst = D40_ALLOC_PHY; + base->phy_res[i].reserved = true; + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i), + D40_DREG_GCC_SRC); + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i), + D40_DREG_GCC_DST); + + } else { base->phy_res[i].allocated_src = D40_ALLOC_FREE; base->phy_res[i].allocated_dst = D40_ALLOC_FREE; + base->phy_res[i].reserved = false; num_phy_chans_avail++; } spin_lock_init(&base->phy_res[i].lock); @@ -2552,6 +2755,11 @@ static int __init d40_phy_res_init(struct d40_base *base) base->phy_res[chan].allocated_src = D40_ALLOC_PHY; base->phy_res[chan].allocated_dst = D40_ALLOC_PHY; + base->phy_res[chan].reserved = true; + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan), + D40_DREG_GCC_SRC); + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan), + D40_DREG_GCC_DST); num_phy_chans_avail--; } @@ -2572,6 +2780,15 @@ static int __init d40_phy_res_init(struct d40_base *base) val[0] = val[0] >> 2; } + /* + * To keep things simple, Enable all clocks initially. + * The clocks will get managed later post channel allocation. + * The clocks for the event lines on which reserved channels exists + * are not managed here. + */ + writel(D40_DREG_GCC_ENABLE_ALL, base->virtbase + D40_DREG_GCC); + base->gcc_pwr_off_mask = gcc; + return num_phy_chans_avail; } @@ -2699,10 +2916,15 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) goto failure; } - base->lcla_pool.alloc_map = kzalloc(num_phy_chans * - sizeof(struct d40_desc *) * - D40_LCLA_LINK_PER_EVENT_GRP, + base->reg_val_backup_chan = kmalloc(base->num_phy_chans * + sizeof(d40_backup_regs_chan), GFP_KERNEL); + if (!base->reg_val_backup_chan) + goto failure; + + base->lcla_pool.alloc_map = + kzalloc(num_phy_chans * sizeof(struct d40_desc *) + * D40_LCLA_LINK_PER_EVENT_GRP, GFP_KERNEL); if (!base->lcla_pool.alloc_map) goto failure; @@ -2741,9 +2963,9 @@ failure: static void __init d40_hw_init(struct d40_base *base) { - static const struct d40_reg_val dma_init_reg[] = { + static struct d40_reg_val dma_init_reg[] = { /* Clock every part of the DMA block from start */ - { .reg = D40_DREG_GCC, .val = 0x0000ff01}, + { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL}, /* Interrupts on all logical channels */ { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF}, @@ -2960,6 +3182,12 @@ static int __init d40_probe(struct platform_device *pdev) goto failure; } + pm_runtime_irq_safe(base->dev); + pm_runtime_set_autosuspend_delay(base->dev, DMA40_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(base->dev); + pm_runtime_enable(base->dev); + pm_runtime_resume(base->dev); + base->initialized = true; err = d40_dmaengine_init(base, num_reserved_chans); if (err) goto failure; @@ -3013,6 +3241,7 @@ static struct platform_driver d40_driver = { .driver = { .owner = THIS_MODULE, .name = D40_NAME, + .pm = DMA40_PM_OPS, }, }; diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index b44c4551..8d3d490 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -16,6 +16,8 @@ #define D40_TYPE_TO_GROUP(type) (type / 16) #define D40_TYPE_TO_EVENT(type) (type % 16) +#define D40_GROUP_SIZE 8 +#define D40_PHYS_TO_GROUP(phys) ((phys & (D40_GROUP_SIZE - 1)) / 2) /* Most bits of the CFG register are the same in log as in phy mode */ #define D40_SREG_CFG_MST_POS 15 @@ -123,6 +125,15 @@ /* DMA Register Offsets */ #define D40_DREG_GCC 0x000 +#define D40_DREG_GCC_ENA 0x1 +/* This assumes that there are only 4 event groups */ +#define D40_DREG_GCC_ENABLE_ALL 0xff01 +#define D40_DREG_GCC_EVTGRP_POS 8 +#define D40_DREG_GCC_SRC 0 +#define D40_DREG_GCC_DST 1 +#define D40_DREG_GCC_EVTGRP_ENA(x, y) \ + (1 << (D40_DREG_GCC_EVTGRP_POS + 2 * x + y)) + #define D40_DREG_PRTYP 0x004 #define D40_DREG_PRSME 0x008 #define D40_DREG_PRSMO 0x00C -- cgit v0.10.2 From e69664336d6400cc1685716ee5f04ef74e85703e Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 18 Nov 2011 16:38:02 +0800 Subject: IMX/DMA : set the DMA direction in the sdma_control() Set the right DMA direction in the sdma_control(), else we will get the wrong log when enable the DYNAMIC_DEBUG. Signed-off-by: Huang Shijie Signed-off-by: Vinod Koul diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 2e03571..d9e5933 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1102,6 +1102,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, sdmac->watermark_level = dmaengine_cfg->dst_maxburst; sdmac->word_size = dmaengine_cfg->dst_addr_width; } + sdmac->direction = dmaengine_cfg->direction; return sdma_config_channel(sdmac); default: return -ENOSYS; -- cgit v0.10.2 From 61e183f8306934a9f66557f69f1f0f56f18dca06 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 17 Nov 2011 16:01:29 +0530 Subject: dmaengine/dw_dmac: Reconfigure interrupt and chan_cfg register on resume In S2R all DMA registers are reset by hardware and thus they are required to be reprogrammed. The channels which aren't reprogrammed are channel configuration and interrupt enable registers, which are currently programmed at chan_alloc time. This patch creates another routine to initialize a channel. It will try to initialize channel on every dwc_dostart() call. If channel is already initialised then it simply returns, otherwise it configures registers. This routine will also initialize registers on wakeup from S2R, as we mark channels as uninitialized on suspend. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index decca1c..9b592b0 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -166,6 +166,38 @@ dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc) return cookie; } +static void dwc_initialize(struct dw_dma_chan *dwc) +{ + struct dw_dma *dw = to_dw_dma(dwc->chan.device); + struct dw_dma_slave *dws = dwc->chan.private; + u32 cfghi = DWC_CFGH_FIFO_MODE; + u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); + + if (dwc->initialized == true) + return; + + if (dws) { + /* + * We need controller-specific data to set up slave + * transfers. + */ + BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); + + cfghi = dws->cfg_hi; + cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; + } + + channel_writel(dwc, CFG_LO, cfglo); + channel_writel(dwc, CFG_HI, cfghi); + + /* Enable interrupts */ + channel_set_bit(dw, MASK.XFER, dwc->mask); + channel_set_bit(dw, MASK.BLOCK, dwc->mask); + channel_set_bit(dw, MASK.ERROR, dwc->mask); + + dwc->initialized = true; +} + /*----------------------------------------------------------------------*/ /* Called with dwc->lock held and bh disabled */ @@ -189,6 +221,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) return; } + dwc_initialize(dwc); + channel_writel(dwc, LLP, first->txd.phys); channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); @@ -959,10 +993,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); struct dw_desc *desc; - struct dw_dma_slave *dws; int i; - u32 cfghi; - u32 cfglo; unsigned long flags; dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); @@ -975,26 +1006,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) dwc->completed = chan->cookie = 1; - cfghi = DWC_CFGH_FIFO_MODE; - cfglo = 0; - - dws = chan->private; - if (dws) { - /* - * We need controller-specific data to set up slave - * transfers. - */ - BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); - - cfghi = dws->cfg_hi; - cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; - } - - cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority); - - channel_writel(dwc, CFG_LO, cfglo); - channel_writel(dwc, CFG_HI, cfghi); - /* * NOTE: some controllers may have additional features that we * need to initialize here, like "scatter-gather" (which @@ -1026,11 +1037,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) i = ++dwc->descs_allocated; } - /* Enable interrupts */ - channel_set_bit(dw, MASK.XFER, dwc->mask); - channel_set_bit(dw, MASK.BLOCK, dwc->mask); - channel_set_bit(dw, MASK.ERROR, dwc->mask); - spin_unlock_irqrestore(&dwc->lock, flags); dev_dbg(chan2dev(chan), @@ -1058,6 +1064,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) spin_lock_irqsave(&dwc->lock, flags); list_splice_init(&dwc->free_list, &list); dwc->descs_allocated = 0; + dwc->initialized = false; /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); @@ -1335,6 +1342,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free); static void dw_dma_off(struct dw_dma *dw) { + int i; + dma_writel(dw, CFG, 0); channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); @@ -1345,6 +1354,9 @@ static void dw_dma_off(struct dw_dma *dw) while (dma_readl(dw, CFG) & DW_CFG_DMA_EN) cpu_relax(); + + for (i = 0; i < dw->dma.chancnt; i++) + dw->chan[i].initialized = false; } static int __init dw_probe(struct platform_device *pdev) @@ -1533,6 +1545,7 @@ static int dw_suspend_noirq(struct device *dev) dw_dma_off(platform_get_drvdata(pdev)); clk_disable(dw->clk); + return 0; } diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index c341951..5eef694 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -140,6 +140,7 @@ struct dw_dma_chan { u8 mask; u8 priority; bool paused; + bool initialized; spinlock_t lock; -- cgit v0.10.2 From d5613947addb1e1096a3be29dfe817905e385469 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 28 Nov 2011 08:51:16 +0530 Subject: dmaengine: timb_dma: fix the spare warinings Sparse warns: drivers/dma/timb_dma.c:168:17: warning: mixing different enum types drivers/dma/timb_dma.c:168:17: int enum dma_transfer_direction versus drivers/dma/timb_dma.c:168:17: int enum dma_data_direction drivers/dma/timb_dma.c:172:32: warning: mixing different enum types drivers/dma/timb_dma.c:172:32: int enum dma_transfer_direction versus drivers/dma/timb_dma.c:172:32: int enum dma_data_direction Reported-by: Dan Carpenter Signed-off-by: Vinod Koul diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 8c88072..d142ae1 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -166,10 +166,10 @@ static void __td_unmap_desc(struct timb_dma_chan *td_chan, const u8 *dma_desc, if (single) dma_unmap_single(chan2dev(&td_chan->chan), addr, len, - td_chan->direction); + DMA_TO_DEVICE); else dma_unmap_page(chan2dev(&td_chan->chan), addr, len, - td_chan->direction); + DMA_TO_DEVICE); } static void __td_unmap_descs(struct timb_dma_desc *td_desc, bool single) @@ -398,7 +398,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) td_desc->txd.flags = DMA_CTRL_ACK; td_desc->txd.phys = dma_map_single(chan2dmadev(chan), - td_desc->desc_list, td_desc->desc_list_len, DMA_MEM_TO_DEV); + td_desc->desc_list, td_desc->desc_list_len, DMA_TO_DEVICE); err = dma_mapping_error(chan2dmadev(chan), td_desc->txd.phys); if (err) { @@ -419,7 +419,7 @@ static void td_free_desc(struct timb_dma_desc *td_desc) { dev_dbg(chan2dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); dma_unmap_single(chan2dmadev(td_desc->txd.chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_MEM_TO_DEV); + td_desc->desc_list_len, DMA_TO_DEVICE); kfree(td_desc->desc_list); kfree(td_desc); -- cgit v0.10.2 From 28c7a19d230228ab9ae61c300c5003a2400fadd3 Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Tue, 22 Nov 2011 13:56:55 +0530 Subject: dmaengine/ste_dma40: Add support to use lcla area from esram This patch provides an option of having the lcla (link address) in ESRAM instead of allocating it. The bool value (use_esram_lcla) in the stedma40_platform_data if set to true, then the lcla address would be taken from platform resources. Also, the corresponding esram regulator is managed in the suspend/resume functions. Signed-off-by: Narayanan G Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 38b041a..3177bed 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -153,6 +153,7 @@ struct stedma40_platform_data { struct stedma40_chan_cfg *memcpy_conf_phy; struct stedma40_chan_cfg *memcpy_conf_log; int disabled_channels[STEDMA40_MAX_PHYS]; + bool use_esram_lcla; }; #ifdef CONFIG_STE_DMA40 diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index c2cf8cf..aff128a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -304,6 +304,7 @@ struct d40_chan { * to phy_chans entries. * @plat_data: Pointer to provided platform_data which is the driver * configuration. + * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla. * @phy_res: Vector containing all physical channels. * @lcla_pool: lcla pool settings and data. * @lcpa_base: The virtual mapped address of LCPA. @@ -338,6 +339,7 @@ struct d40_base { struct d40_chan **lookup_log_chans; struct d40_chan **lookup_phy_chans; struct stedma40_platform_data *plat_data; + struct regulator *lcpa_regulator; /* Physical half channels */ struct d40_phy_res *phy_res; struct d40_lcla_pool lcla_pool; @@ -605,6 +607,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) bool cyclic = desc->cyclic; int curr_lcla = -EINVAL; int first_lcla = 0; + bool use_esram_lcla = chan->base->plat_data->use_esram_lcla; bool linkback; /* @@ -677,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) &lli->src[lli_current], next_lcla, flags); - dma_sync_single_range_for_device(chan->base->dev, - pool->dma_addr, lcla_offset, - 2 * sizeof(struct d40_log_lli), - DMA_TO_DEVICE); - + /* + * Cache maintenance is not needed if lcla is + * mapped in esram + */ + if (!use_esram_lcla) { + dma_sync_single_range_for_device(chan->base->dev, + pool->dma_addr, lcla_offset, + 2 * sizeof(struct d40_log_lli), + DMA_TO_DEVICE); + } curr_lcla = next_lcla; if (curr_lcla == -EINVAL || curr_lcla == first_lcla) { @@ -2668,10 +2676,15 @@ failure1: #ifdef CONFIG_PM static int dma40_pm_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + int ret = 0; if (!pm_runtime_suspended(dev)) return -EBUSY; - return 0; + if (base->lcpa_regulator) + ret = regulator_disable(base->lcpa_regulator); + return ret; } static int dma40_runtime_suspend(struct device *dev) @@ -2702,11 +2715,23 @@ static int dma40_runtime_resume(struct device *dev) return 0; } +static int dma40_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + int ret = 0; + + if (base->lcpa_regulator) + ret = regulator_enable(base->lcpa_regulator); + + return ret; +} static const struct dev_pm_ops dma40_pm_ops = { .suspend = dma40_pm_suspend, .runtime_suspend = dma40_runtime_suspend, .runtime_resume = dma40_runtime_resume, + .resume = dma40_resume, }; #define DMA40_PM_OPS (&dma40_pm_ops) #else @@ -3165,11 +3190,31 @@ static int __init d40_probe(struct platform_device *pdev) d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); goto failure; } + /* If lcla has to be located in ESRAM we don't need to allocate */ + if (base->plat_data->use_esram_lcla) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "lcla_esram"); + if (!res) { + ret = -ENOENT; + d40_err(&pdev->dev, + "No \"lcla_esram\" memory resource\n"); + goto failure; + } + base->lcla_pool.base = ioremap(res->start, + resource_size(res)); + if (!base->lcla_pool.base) { + ret = -ENOMEM; + d40_err(&pdev->dev, "Failed to ioremap LCLA region\n"); + goto failure; + } + writel(res->start, base->virtbase + D40_DREG_LCLA); - ret = d40_lcla_allocate(base); - if (ret) { - d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); - goto failure; + } else { + ret = d40_lcla_allocate(base); + if (ret) { + d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); + goto failure; + } } spin_lock_init(&base->lcla_pool.lock); @@ -3187,6 +3232,26 @@ static int __init d40_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(base->dev); pm_runtime_enable(base->dev); pm_runtime_resume(base->dev); + + if (base->plat_data->use_esram_lcla) { + + base->lcpa_regulator = regulator_get(base->dev, "lcla_esram"); + if (IS_ERR(base->lcpa_regulator)) { + d40_err(&pdev->dev, "Failed to get lcpa_regulator\n"); + base->lcpa_regulator = NULL; + goto failure; + } + + ret = regulator_enable(base->lcpa_regulator); + if (ret) { + d40_err(&pdev->dev, + "Failed to enable lcpa_regulator\n"); + regulator_put(base->lcpa_regulator); + base->lcpa_regulator = NULL; + goto failure; + } + } + base->initialized = true; err = d40_dmaengine_init(base, num_reserved_chans); if (err) @@ -3204,6 +3269,11 @@ failure: if (base->virtbase) iounmap(base->virtbase); + if (base->lcla_pool.base && base->plat_data->use_esram_lcla) { + iounmap(base->lcla_pool.base); + base->lcla_pool.base = NULL; + } + if (base->lcla_pool.dma_addr) dma_unmap_single(base->dev, base->lcla_pool.dma_addr, SZ_1K * base->num_phy_chans, @@ -3226,6 +3296,11 @@ failure: clk_put(base->clk); } + if (base->lcpa_regulator) { + regulator_disable(base->lcpa_regulator); + regulator_put(base->lcpa_regulator); + } + kfree(base->lcla_pool.alloc_map); kfree(base->lookup_log_chans); kfree(base->lookup_phy_chans); -- cgit v0.10.2 From 0ab88a01832d529c48e2a51f3d24662c143df39a Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:52 +0100 Subject: dmaengine: at_hdmac: add const to struct platform_device_id definition Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3b0c28f..3b44f24 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1191,7 +1191,7 @@ static const struct of_device_id atmel_dma_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); #endif -static struct platform_device_id atdma_devtypes[] = { +static const struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", .driver_data = ATDMA_DEVTYPE_SAM9RL, -- cgit v0.10.2 From dcc817346d311bbd9dac6fc9d6bddb552134851c Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:53 +0100 Subject: dmaengine: at_hdmac: empty entry shape modification Trivial form modification to unify structure look. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3b44f24..30ec030 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1185,7 +1185,9 @@ static const struct of_device_id atmel_dma_dt_ids[] = { }, { .compatible = "atmel,at91sam9g45-dma", .data = (void *)ATDMA_DEVTYPE_SAM9G45 - }, { /* sentinel */ } + }, { + /* sentinel */ + } }; MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); -- cgit v0.10.2 From 02f88be9488a3d831f073c1161b1e5feacb9d3ec Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:54 +0100 Subject: dmaengine: at_hdmac: simplify device selection from platform data or DT Using a configuration structure simplify the finding of SoC dependent parameters. Both platform data and device tree ids are using these structures. This will separate data from code and remove the need for an enum. Idea from Grant Likely. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 30ec030..97f87b2 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1177,14 +1177,22 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +/* cap_mask is a multi-u32 bitfield, fill it with proper C code. */ +static struct at_dma_platform_data at91sam9rl_config = { + .nr_channels = 2, +}; +static struct at_dma_platform_data at91sam9g45_config = { + .nr_channels = 8, +}; + #if defined(CONFIG_OF) static const struct of_device_id atmel_dma_dt_ids[] = { { .compatible = "atmel,at91sam9rl-dma", - .data = (void *)ATDMA_DEVTYPE_SAM9RL + .data = &at91sam9rl_config, }, { .compatible = "atmel,at91sam9g45-dma", - .data = (void *)ATDMA_DEVTYPE_SAM9G45 + .data = &at91sam9g45_config, }, { /* sentinel */ } @@ -1196,26 +1204,27 @@ MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); static const struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", - .driver_data = ATDMA_DEVTYPE_SAM9RL, + .driver_data = (unsigned long) &at91sam9rl_config, }, { .name = "at91sam9g45_dma", - .driver_data = ATDMA_DEVTYPE_SAM9G45, + .driver_data = (unsigned long) &at91sam9g45_config, }, { /* sentinel */ } }; -static inline enum atdma_devtype __init at_dma_get_driver_data( - struct platform_device *pdev) +static inline struct at_dma_platform_data * __init at_dma_get_driver_data( + struct platform_device *pdev) { if (pdev->dev.of_node) { const struct of_device_id *match; match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node); if (match == NULL) - return ATDMA_DEVTYPE_UNDEFINED; - return (enum atdma_devtype)match->data; + return NULL; + return match->data; } - return platform_get_device_id(pdev)->driver_data; + return (struct at_dma_platform_data *) + platform_get_device_id(pdev)->driver_data; } /** @@ -1242,26 +1251,17 @@ static int __init at_dma_probe(struct platform_device *pdev) int irq; int err; int i; - u32 nr_channels; - dma_cap_mask_t cap_mask = {}; - enum atdma_devtype atdmatype; + struct at_dma_platform_data *plat_dat; - dma_cap_set(DMA_MEMCPY, cap_mask); + /* setup platform data for each SoC */ + dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask); + dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask); + dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask); /* get DMA parameters from controller type */ - atdmatype = at_dma_get_driver_data(pdev); - - switch (atdmatype) { - case ATDMA_DEVTYPE_SAM9RL: - nr_channels = 2; - break; - case ATDMA_DEVTYPE_SAM9G45: - nr_channels = 8; - dma_cap_set(DMA_SLAVE, cap_mask); - break; - default: - return -EINVAL; - } + plat_dat = at_dma_get_driver_data(pdev); + if (!plat_dat) + return -ENODEV; io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) @@ -1272,15 +1272,14 @@ static int __init at_dma_probe(struct platform_device *pdev) return irq; size = sizeof(struct at_dma); - size += nr_channels * sizeof(struct at_dma_chan); + size += plat_dat->nr_channels * sizeof(struct at_dma_chan); atdma = kzalloc(size, GFP_KERNEL); if (!atdma) return -ENOMEM; /* discover transaction capabilities */ - atdma->dma_common.cap_mask = cap_mask; - atdma->all_chan_mask = (1 << nr_channels) - 1; - atdma->devtype = atdmatype; + atdma->dma_common.cap_mask = plat_dat->cap_mask; + atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1; size = resource_size(io); if (!request_mem_region(io->start, size, pdev->dev.driver->name)) { @@ -1326,7 +1325,7 @@ static int __init at_dma_probe(struct platform_device *pdev) /* initialize channels related values */ INIT_LIST_HEAD(&atdma->dma_common.channels); - for (i = 0; i < nr_channels; i++) { + for (i = 0; i < plat_dat->nr_channels; i++) { struct at_dma_chan *atchan = &atdma->chan[i]; atchan->chan_common.device = &atdma->dma_common; @@ -1371,7 +1370,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "", dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", - nr_channels); + plat_dat->nr_channels); dma_async_device_register(&atdma->dma_common); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index d7d6737..dcaedfc 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -248,12 +248,6 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) /*-- Controller ------------------------------------------------------*/ -enum atdma_devtype { - ATDMA_DEVTYPE_UNDEFINED = 0, - ATDMA_DEVTYPE_SAM9RL, /* compatible with SAM9RL DMA controller */ - ATDMA_DEVTYPE_SAM9G45, /* compatible with SAM9G45 DMA controller */ -}; - /** * struct at_dma - internal representation of an Atmel HDMA Controller * @chan_common: common dmaengine dma_device object members @@ -267,7 +261,6 @@ enum atdma_devtype { */ struct at_dma { struct dma_device dma_common; - enum atdma_devtype devtype; void __iomem *regs; struct clk *clk; u32 save_imr; -- cgit v0.10.2 From b62cfc5e0e59d1e0192105144b724b0c332720a0 Mon Sep 17 00:00:00 2001 From: Rafal Prylowski Date: Sat, 26 Nov 2011 12:54:07 +0200 Subject: dma/ep93xx_dma: fix initialization of M2M control register Setting the flags in case of IDE didn't have any effect since the control register is overwritten few lines below. So move these to be after the control register is initialized. Signed-off-by: Rafal Prylowski Signed-off-by: Mika Westerberg Acked-by: H Hartley Sweeten Signed-off-by: Vinod Koul diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 009851b..526a742 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -459,10 +459,6 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) * This IDE part is totally untested. Values below are taken * from the EP93xx Users's Guide and might not be correct. */ - control |= M2M_CONTROL_NO_HDSK; - control |= M2M_CONTROL_RSS_IDE; - control |= M2M_CONTROL_PW_16; - if (data->direction == DMA_MEM_TO_DEV) { /* Worst case from the UG */ control = (3 << M2M_CONTROL_PWSC_SHIFT); @@ -473,6 +469,10 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control |= M2M_CONTROL_SAH; control |= M2M_CONTROL_TM_RX; } + + control |= M2M_CONTROL_NO_HDSK; + control |= M2M_CONTROL_RSS_IDE; + control |= M2M_CONTROL_PW_16; break; default: -- cgit v0.10.2 From 6d0709d2000ae7dbead759715f57ba381b7057bb Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 26 Nov 2011 12:54:08 +0200 Subject: dma/ep93xx_dma: prevent ep93xx_dma_tasklet() to reference an empty list If dma_terminate_all() is called before the ep93xx_dma_tasklet() gets to run, it tries to access an empty ->active list which results following OOPS: Internal error: Oops - undefined instruction: 0 [#1] CPU: 0 Not tainted (3.2.0-rc1EP-1+ #1008) PC is at 0xc184c868 LR is at ep93xx_dma_tasklet+0xec/0x164 pc : [] lr : [] psr: 00000013 sp : c02b7e70 ip : ffffffff fp : c02b7ea4 r10: 00000100 r9 : 80000013 r8 : c02b7e50 r7 : c02b7e70 r6 : c02b7ea4 r5 : 000000a4 r4 : c02b7e70 r3 : c02b751d r2 : 8ae34598 r1 : c184c6e0 r0 : c02b7ea4 Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: c000717f Table: c0004000 DAC: 00000017 Process swapper (pid: 0, stack limit = 0xc02b6270) Stack: (0xc02b7e70 to 0xc02b8000) 7e60: c02b7ea4 c02b7e70 c0008b64 c02bd5c4 7e80: c02d60e0 00000000 00000000 c02bd44c c02d60e0 00000100 c02b7ec4 c02b7ea8 7ea0: c001c49c c012b44c 00000018 00000001 c02d60e0 c02b6000 c02b7f04 c02b7ec8 7ec0: c001cbc0 c001c3e4 c02b7eec c02b7ed8 00000006 0000000a c02bf674 c02c458c 7ee0: 00000011 00000000 c02b7f7c c0004000 41129200 c02b0c80 c02b7f14 c02b7f08 7f00: c001cdd0 c001cb38 c02b7f34 c02b7f18 c000983c c001cd98 c0009a60 60000013 7f20: fefb0001 c02b7f7c c02b7f44 c02b7f38 c0008190 c0009810 c02b7f9c c02b7f48 7f40: c0008b64 c0008190 c02c2bf8 00000002 c02b7f90 60000013 c02b6000 c02d1504 7f60: c02baa88 c02baa80 c0004000 41129200 c02b0c80 c02b7f9c c02b7fa0 c02b7f90 7f80: c0009a54 c0009a60 60000013 ffffffff c02b7fbc c02b7fa0 c000a03c c0009a40 7fa0: c02b80b0 c02b19dc c02b19d8 c02baa80 c02b7fcc c02b7fc0 c02384e4 c0009fd4 7fc0: c02b7ff4 c02b7fd0 c029d924 c0238494 c029d49c 00000000 00000000 c02b19dc 7fe0: c0007175 c02b803c 00000000 c02b7ff8 c000803c c029d700 00000000 00000000 Backtrace: [] (ep93xx_dma_tasklet+0x0/0x164) from [] (tasklet_action+0xc8/0xdc) [] (tasklet_action+0x0/0xdc) from [] (__do_softirq+0x98/0x154) r7:c02b6000 r6:c02d60e0 r5:00000001 r4:00000018 [] (__do_softirq+0x0/0x154) from [] (irq_exit+0x48/0x50) [] (irq_exit+0x0/0x50) from [] (handle_IRQ+0x3c/0x8c) [] (handle_IRQ+0x0/0x8c) from [] (asm_do_IRQ+0x10/0x14) r7:c02b7f7c r6:fefb0001 r5:60000013 r4:c0009a60 [] (asm_do_IRQ+0x0/0x14) from [] (__irq_svc+0x24/0xc0) Exception stack(0xc02b7f48 to 0xc02b7f90) 7f40: c02c2bf8 00000002 c02b7f90 60000013 c02b6000 c02d1504 7f60: c02baa88 c02baa80 c0004000 41129200 c02b0c80 c02b7f9c c02b7fa0 c02b7f90 7f80: c0009a54 c0009a60 60000013 ffffffff [] (default_idle+0x0/0x34) from [] (cpu_idle+0x78/0xb0) [] (cpu_idle+0x0/0xb0) from [] (rest_init+0x60/0x78) r7:c02baa80 r6:c02b19d8 r5:c02b19dc r4:c02b80b0 [] (rest_init+0x0/0x78) from [] (start_kernel+0x234/0x278) [] (start_kernel+0x0/0x278) from [] (0xc000803c) r5:c02b803c r4:c0007175 Code: 42555300 54535953 643d4d45 65766972 (53007372) To make the code a bit more robust against things like these, we modify ep93xx_dma_get_active() to return NULL in case of empty ->active list and make sure that callers handle this correctly. Reported-by: Rafal Prylowski Signed-off-by: Mika Westerberg Acked-by: H Hartley Sweeten Signed-off-by: Vinod Koul diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 526a742..59e7a96 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -246,6 +246,9 @@ static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac, static struct ep93xx_dma_desc * ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac) { + if (list_empty(&edmac->active)) + return NULL; + return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node); } @@ -263,16 +266,22 @@ ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac) */ static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac) { + struct ep93xx_dma_desc *desc; + list_rotate_left(&edmac->active); if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) return true; + desc = ep93xx_dma_get_active(edmac); + if (!desc) + return false; + /* * If txd.cookie is set it means that we are back in the first * descriptor in the chain and hence done with it. */ - return !ep93xx_dma_get_active(edmac)->txd.cookie; + return !desc->txd.cookie; } /* @@ -327,9 +336,15 @@ static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac) static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) { - struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac); + struct ep93xx_dma_desc *desc; u32 bus_addr; + desc = ep93xx_dma_get_active(edmac); + if (!desc) { + dev_warn(chan2dev(edmac), "M2P: empty descriptor list\n"); + return; + } + if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV) bus_addr = desc->src_addr; else @@ -491,7 +506,13 @@ static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac) static void m2m_fill_desc(struct ep93xx_dma_chan *edmac) { - struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac); + struct ep93xx_dma_desc *desc; + + desc = ep93xx_dma_get_active(edmac); + if (!desc) { + dev_warn(chan2dev(edmac), "M2M: empty descriptor list\n"); + return; + } if (edmac->buffer == 0) { writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0); @@ -669,24 +690,30 @@ static void ep93xx_dma_tasklet(unsigned long data) { struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data; struct ep93xx_dma_desc *desc, *d; - dma_async_tx_callback callback; - void *callback_param; + dma_async_tx_callback callback = NULL; + void *callback_param = NULL; LIST_HEAD(list); spin_lock_irq(&edmac->lock); + /* + * If dma_terminate_all() was called before we get to run, the active + * list has become empty. If that happens we aren't supposed to do + * anything more than call ep93xx_dma_advance_work(). + */ desc = ep93xx_dma_get_active(edmac); - if (desc->complete) { - edmac->last_completed = desc->txd.cookie; - list_splice_init(&edmac->active, &list); + if (desc) { + if (desc->complete) { + edmac->last_completed = desc->txd.cookie; + list_splice_init(&edmac->active, &list); + } + callback = desc->txd.callback; + callback_param = desc->txd.callback_param; } spin_unlock_irq(&edmac->lock); /* Pick up the next descriptor from the queue */ ep93xx_dma_advance_work(edmac); - callback = desc->txd.callback; - callback_param = desc->txd.callback_param; - /* Now we can release all the chained descriptors */ list_for_each_entry_safe(desc, d, &list, node) { /* @@ -706,13 +733,22 @@ static void ep93xx_dma_tasklet(unsigned long data) static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id) { struct ep93xx_dma_chan *edmac = dev_id; + struct ep93xx_dma_desc *desc; irqreturn_t ret = IRQ_HANDLED; spin_lock(&edmac->lock); + desc = ep93xx_dma_get_active(edmac); + if (!desc) { + dev_warn(chan2dev(edmac), + "got interrupt while active list is empty\n"); + spin_unlock(&edmac->lock); + return IRQ_NONE; + } + switch (edmac->edma->hw_interrupt(edmac)) { case INTERRUPT_DONE: - ep93xx_dma_get_active(edmac)->complete = true; + desc->complete = true; tasklet_schedule(&edmac->tasklet); break; -- cgit v0.10.2 From ab59a510c6ad6b3add5125df64843be754782de6 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 2 Dec 2011 10:16:25 +0800 Subject: IMX/SDMA : save the real count for one DMA transaction. When we use the SDMA in the UART driver(such as imx6q), we will meet one situation: Assume we set 64 bytes for the RX DMA buffer. The RX DMA buffer has received some data, but not full. An Aging DMA request will be received by the SDMA controller if we enable the IDDMAEN(UCR4[6]) in this case. So the UART driver needs to know the count of the real received bytes, and push them to upper layer. Add two new fields to sdmac, and update the `residue` in sdma_tx_status(). Signed-off-by: Huang Shijie Signed-off-by: Vinod Koul diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d9e5933..f59fd8f 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -268,6 +268,8 @@ struct sdma_channel { struct dma_async_tx_descriptor desc; dma_cookie_t last_completed; enum dma_status status; + unsigned int chn_count; + unsigned int chn_real_count; }; #define IMX_DMA_SG_LOOP (1 << 0) @@ -503,6 +505,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) struct sdma_buffer_descriptor *bd; int i, error = 0; + sdmac->chn_real_count = 0; /* * non loop mode. Iterate over all descriptors, collect * errors and call callback function @@ -512,6 +515,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) if (bd->mode.status & (BD_DONE | BD_RROR)) error = -EIO; + sdmac->chn_real_count += bd->mode.count; } if (error) @@ -519,9 +523,9 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) else sdmac->status = DMA_SUCCESS; + sdmac->last_completed = sdmac->desc.cookie; if (sdmac->desc.callback) sdmac->desc.callback(sdmac->desc.callback_param); - sdmac->last_completed = sdmac->desc.cookie; } static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) @@ -941,6 +945,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( goto err_out; } + sdmac->chn_count = 0; for_each_sg(sgl, sg, sg_len, i) { struct sdma_buffer_descriptor *bd = &sdmac->bd[i]; int param; @@ -957,6 +962,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( } bd->mode.count = count; + sdmac->chn_count += count; if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) { ret = -EINVAL; @@ -1120,7 +1126,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, last_used = chan->cookie; - dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0); + dma_set_tx_state(txstate, sdmac->last_completed, last_used, + sdmac->chn_count - sdmac->chn_real_count); return sdmac->status; } -- cgit v0.10.2 From c94e910535be72f0c6ac0c69e6acd8d44414e80d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 15:11:12 +0800 Subject: dmaengine: convert drivers/dma/* to use module_platform_driver() This patch converts the drivers in drivers/dma/* to use the module_platform_driver() macro which makes the code smaller and a bit simpler. Cc: Dan Williams Cc: Piotr Ziecik Cc: Rongjun Ying Cc: Barry Song <21cnbao@gmail.com> Cc: Pelagicore AB Signed-off-by: Axel Lin Signed-off-by: Vinod Koul diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 686dc76..04be90b 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -1735,8 +1735,6 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan) spin_unlock_bh(&iop_chan->lock); } -MODULE_ALIAS("platform:iop-adma"); - static struct platform_driver iop_adma_driver = { .probe = iop_adma_probe, .remove = __devexit_p(iop_adma_remove), @@ -1746,19 +1744,9 @@ static struct platform_driver iop_adma_driver = { }, }; -static int __init iop_adma_init(void) -{ - return platform_driver_register(&iop_adma_driver); -} - -static void __exit iop_adma_exit(void) -{ - platform_driver_unregister(&iop_adma_driver); - return; -} -module_exit(iop_adma_exit); -module_init(iop_adma_init); +module_platform_driver(iop_adma_driver); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("IOP ADMA Engine Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:iop-adma"); diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 8ba4edc..4d6d4cf 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -835,17 +835,7 @@ static struct platform_driver mpc_dma_driver = { }, }; -static int __init mpc_dma_init(void) -{ - return platform_driver_register(&mpc_dma_driver); -} -module_init(mpc_dma_init); - -static void __exit mpc_dma_exit(void) -{ - platform_driver_unregister(&mpc_dma_driver); -} -module_exit(mpc_dma_exit); +module_platform_driver(mpc_dma_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Piotr Ziecik "); diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 55ec679..2333810 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -699,17 +699,7 @@ static struct platform_driver sirfsoc_dma_driver = { }, }; -static int __init sirfsoc_dma_init(void) -{ - return platform_driver_register(&sirfsoc_dma_driver); -} -module_init(sirfsoc_dma_init); - -static void __exit sirfsoc_dma_exit(void) -{ - platform_driver_unregister(&sirfsoc_dma_driver); -} -module_exit(sirfsoc_dma_exit); +module_platform_driver(sirfsoc_dma_driver); MODULE_AUTHOR("Rongjun Ying , " "Barry Song "); diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index d142ae1..a6f9c16 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -841,17 +841,7 @@ static struct platform_driver td_driver = { .remove = __exit_p(td_remove), }; -static int __init td_init(void) -{ - return platform_driver_register(&td_driver); -} -module_init(td_init); - -static void __exit td_exit(void) -{ - platform_driver_unregister(&td_driver); -} -module_exit(td_exit); +module_platform_driver(td_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Timberdale DMA controller driver"); -- cgit v0.10.2 From 8f0d30f9ee333f4fb3458a9a33f7ead5269ea8f3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 29 Nov 2011 12:56:50 +0530 Subject: dmaengine/amba-pl08x: Config ccfg and increment phychan_hold if phychan is true Currently, if plchan->phychan is true, we return immediately from prep_phy_chan(). We must configure txd->ccfg and increment phychan_hold before returning. Otherwise, request line number wouldn't be configured in this txd. Reported-by: Rajeev Kumar Signed-off-by: Viresh Kumar Acked-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 41c62fd..9ebceca 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -854,8 +854,10 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan, int ret; /* Check if we already have a channel */ - if (plchan->phychan) - return 0; + if (plchan->phychan) { + ch = plchan->phychan; + goto got_channel; + } ch = pl08x_get_phy_channel(pl08x, plchan); if (!ch) { @@ -880,21 +882,22 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan, return -EBUSY; } ch->signal = ret; - - /* Assign the flow control signal to this channel */ - if (txd->direction == DMA_MEM_TO_DEV) - txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT; - else if (txd->direction == DMA_DEV_TO_MEM) - txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT; } + plchan->phychan = ch; dev_dbg(&pl08x->adev->dev, "allocated physical channel %d and signal %d for xfer on %s\n", ch->id, ch->signal, plchan->name); +got_channel: + /* Assign the flow control signal to this channel */ + if (txd->direction == DMA_MEM_TO_DEV) + txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT; + else if (txd->direction == DMA_DEV_TO_MEM) + txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT; + plchan->phychan_hold++; - plchan->phychan = ch; return 0; } -- cgit v0.10.2 From 5cd326fd27da347925019fcc041b79bad8dd55ed Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Wed, 30 Nov 2011 19:20:42 +0530 Subject: dmaengine/ste_dma40: allow fixed physical channel Allow logical channels to specify the physical channel they want to use. This is needed to avoid two peripherals operating on the same physical channel during some special use-cases. (like mmc and usb during a usb mass storage case). Signed-off-by: Rabin Vincent Signed-off-by: Narayanan G Reviewed-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 3177bed..fd0ee84 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -113,7 +113,8 @@ struct stedma40_half_channel_info { * @dst_dev_type: Dst device type * @src_info: Parameters for dst half channel * @dst_info: Parameters for dst half channel - * + * @use_fixed_channel: if true, use physical channel specified by phy_channel + * @phy_channel: physical channel to use, only if use_fixed_channel is true * * This structure has to be filled by the client drivers. * It is recommended to do all dma configurations for clients in the machine. @@ -129,6 +130,9 @@ struct stedma40_chan_cfg { int dst_dev_type; struct stedma40_half_channel_info src_info; struct stedma40_half_channel_info dst_info; + + bool use_fixed_channel; + int phy_channel; }; /** diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index aff128a..972dc35 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1545,11 +1545,16 @@ static int d40_validate_conf(struct d40_chan *d40c, return res; } -static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src, - int log_event_line, bool is_log) +static bool d40_alloc_mask_set(struct d40_phy_res *phy, + bool is_src, int log_event_line, bool is_log, + bool *first_user) { unsigned long flags; spin_lock_irqsave(&phy->lock, flags); + + *first_user = ((phy->allocated_src | phy->allocated_dst) + == D40_ALLOC_FREE); + if (!is_log) { /* Physical interrupts are masked per physical full channel */ if (phy->allocated_src == D40_ALLOC_FREE && @@ -1630,7 +1635,7 @@ out: return is_free; } -static int d40_allocate_channel(struct d40_chan *d40c) +static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) { int dev_type; int event_group; @@ -1666,7 +1671,8 @@ static int d40_allocate_channel(struct d40_chan *d40c) for (i = 0; i < d40c->base->num_phy_chans; i++) { if (d40_alloc_mask_set(&phys[i], is_src, - 0, is_log)) + 0, is_log, + first_phy_user)) goto found_phy; } } else @@ -1676,7 +1682,8 @@ static int d40_allocate_channel(struct d40_chan *d40c) if (d40_alloc_mask_set(&phys[i], is_src, 0, - is_log)) + is_log, + first_phy_user)) goto found_phy; } } @@ -1692,6 +1699,25 @@ found_phy: /* Find logical channel */ for (j = 0; j < d40c->base->num_phy_chans; j += 8) { int phy_num = j + event_group * 2; + + if (d40c->dma_cfg.use_fixed_channel) { + i = d40c->dma_cfg.phy_channel; + + if ((i != phy_num) && (i != phy_num + 1)) { + dev_err(chan2dev(d40c), + "invalid fixed phy channel %d\n", i); + return -EINVAL; + } + + if (d40_alloc_mask_set(&phys[i], is_src, event_line, + is_log, first_phy_user)) + goto found_log; + + dev_err(chan2dev(d40c), + "could not allocate fixed phy channel %d\n", i); + return -EINVAL; + } + /* * Spread logical channels across all available physical rather * than pack every logical channel at the first available phy @@ -1700,13 +1726,15 @@ found_phy: if (is_src) { for (i = phy_num; i < phy_num + 2; i++) { if (d40_alloc_mask_set(&phys[i], is_src, - event_line, is_log)) + event_line, is_log, + first_phy_user)) goto found_log; } } else { for (i = phy_num + 1; i >= phy_num; i--) { if (d40_alloc_mask_set(&phys[i], is_src, - event_line, is_log)) + event_line, is_log, + first_phy_user)) goto found_log; } } @@ -2160,9 +2188,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) goto fail; } } - is_free_phy = (d40c->phy_chan == NULL); - err = d40_allocate_channel(d40c); + err = d40_allocate_channel(d40c, &is_free_phy); if (err) { chan_err(d40c, "Failed to allocate channel\n"); d40c->configured = false; @@ -2189,6 +2216,12 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; } + dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", + chan_is_logical(d40c) ? "logical" : "physical", + d40c->phy_chan->num, + d40c->dma_cfg.use_fixed_channel ? ", fixed" : ""); + + /* * Only write channel configuration to the DMA if the physical * resource is free. In case of multiple logical channels -- cgit v0.10.2 From c99e78435342a65a6a0bf9b86f87fd05831858d2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 14:58:51 +0100 Subject: i.MX IPU DMA: Fix wrong burstsize settings The burstsize (npb in struct chan_param_mem) is set in ipu_ch_param_set_size() once. The number of allowed pixels in a burst depend on the pixel format and the rotation mode. For 16bit formats 16 pixels are allowed whereas for 32bit formats only 8 pixels are allowed. Set these values correctly in ipu_ch_param_set_size() and do not overwrite them afterwards. We do not support rotation right now, so ignore this case. This patch fixes the wrong burstsize setting of 16 pixels for 32bpp. Signed-off-by: Sascha Hauer Signed-off-by: Vinod Koul diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index e16e280..6212b16 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -312,7 +312,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, case IPU_PIX_FMT_RGB565: params->ip.bpp = 2; params->ip.pfs = 4; - params->ip.npb = 7; + params->ip.npb = 15; params->ip.sat = 2; /* SAT = 32-bit access */ params->ip.ofs0 = 0; /* Red bit offset */ params->ip.ofs1 = 5; /* Green bit offset */ @@ -422,12 +422,6 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->pp.nsb = 1; } -static void ipu_ch_param_set_burst_size(union chan_param_mem *params, - uint16_t burst_pixels) -{ - params->pp.npb = burst_pixels - 1; -} - static void ipu_ch_param_set_buffer(union chan_param_mem *params, dma_addr_t buf0, dma_addr_t buf1) { @@ -690,23 +684,6 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan, ipu_ch_param_set_size(¶ms, pixel_fmt, width, height, stride_bytes); ipu_ch_param_set_buffer(¶ms, phyaddr_0, phyaddr_1); ipu_ch_param_set_rotation(¶ms, rot_mode); - /* Some channels (rotation) have restriction on burst length */ - switch (channel) { - case IDMAC_IC_7: /* Hangs with burst 8, 16, other values - invalid - Table 44-30 */ -/* - ipu_ch_param_set_burst_size(¶ms, 8); - */ - break; - case IDMAC_SDC_0: - case IDMAC_SDC_1: - /* In original code only IPU_PIX_FMT_RGB565 was setting burst */ - ipu_ch_param_set_burst_size(¶ms, 16); - break; - case IDMAC_IC_0: - default: - break; - } spin_lock_irqsave(&ipu->lock, flags); -- cgit v0.10.2 From f910fb8fcd1c97788f2291c8646597bcd87ee061 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 1 Dec 2011 14:58:52 +0100 Subject: video i.MX IPU: Fix display connections The IPU internally works on 32bit colors. It can arbitrarily map between pixel formats and internal representation and also between internal representation and the physical connection to the display. The driver used to change the mapping between internal representation and display connection depending on the user selected bpp which is wrong. Instead, the mapping is specified by the hardware, so an additional field in platform data is added to describe the connection between i.MX and the display. The default for this field is RGB666 which seems to be the only configuration which works without this patch, so I assumed that all in Kernel boards are connected this way. This patch has been tested on a RGB666 connected display and a RGB888 connected display in both 16bpp and 32bpp modes. Signed-off-by: Sascha Hauer Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-mxc/include/mach/mx3fb.h b/arch/arm/plat-mxc/include/mach/mx3fb.h index ac24c5c..fdbe600 100644 --- a/arch/arm/plat-mxc/include/mach/mx3fb.h +++ b/arch/arm/plat-mxc/include/mach/mx3fb.h @@ -22,6 +22,20 @@ #define FB_SYNC_SWAP_RGB 0x04000000 #define FB_SYNC_CLK_SEL_EN 0x02000000 +/* + * Specify the way your display is connected. The IPU can arbitrarily + * map the internal colors to the external data lines. We only support + * the following mappings at the moment. + */ +enum disp_data_mapping { + /* blue -> d[0..5], green -> d[6..11], red -> d[12..17] */ + IPU_DISP_DATA_MAPPING_RGB666, + /* blue -> d[0..4], green -> d[5..10], red -> d[11..15] */ + IPU_DISP_DATA_MAPPING_RGB565, + /* blue -> d[0..7], green -> d[8..15], red -> d[16..23] */ + IPU_DISP_DATA_MAPPING_RGB888, +}; + /** * struct mx3fb_platform_data - mx3fb platform data * @@ -33,6 +47,7 @@ struct mx3fb_platform_data { const char *name; const struct fb_videomode *mode; int num_modes; + enum disp_data_mapping disp_data_fmt; }; #endif diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 1981e36..727a514 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -245,6 +245,7 @@ struct mx3fb_data { uint32_t h_start_width; uint32_t v_start_width; + enum disp_data_mapping disp_data_fmt; }; struct dma_chan_request { @@ -287,11 +288,14 @@ static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long r __raw_writel(value, mx3fb->reg_base + reg); } -static const uint32_t di_mappings[] = { - 0x1600AAAA, 0x00E05555, 0x00070000, 3, /* RGB888 */ - 0x0005000F, 0x000B000F, 0x0011000F, 1, /* RGB666 */ - 0x0011000F, 0x000B000F, 0x0005000F, 1, /* BGR666 */ - 0x0004003F, 0x000A000F, 0x000F003F, 1 /* RGB565 */ +struct di_mapping { + uint32_t b0, b1, b2; +}; + +static const struct di_mapping di_mappings[] = { + [IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f }, + [IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f }, + [IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 }, }; static void sdc_fb_init(struct mx3fb_info *fbi) @@ -425,7 +429,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel * @pixel_clk: desired pixel clock frequency in Hz. * @width: width of panel in pixels. * @height: height of panel in pixels. - * @pixel_fmt: pixel format of buffer as FOURCC ASCII code. * @h_start_width: number of pixel clocks between the HSYNC signal pulse * and the start of valid data. * @h_sync_width: width of the HSYNC signal in units of pixel clocks. @@ -442,7 +445,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, uint32_t pixel_clk, uint16_t width, uint16_t height, - enum pixel_fmt pixel_fmt, uint16_t h_start_width, uint16_t h_sync_width, uint16_t h_end_width, uint16_t v_start_width, uint16_t v_sync_width, uint16_t v_end_width, @@ -453,6 +455,7 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, uint32_t old_conf; uint32_t div; struct clk *ipu_clk; + const struct di_mapping *map; dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height); @@ -540,36 +543,10 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT; mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL); - switch (pixel_fmt) { - case IPU_PIX_FMT_RGB24: - mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP); - mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP); - mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP); - mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | - ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC); - break; - case IPU_PIX_FMT_RGB666: - mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP); - mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP); - mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP); - mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | - ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC); - break; - case IPU_PIX_FMT_BGR666: - mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP); - mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP); - mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP); - mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | - ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC); - break; - default: - mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP); - mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP); - mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP); - mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | - ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC); - break; - } + map = &di_mappings[mx3fb->disp_data_fmt]; + mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP); + mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP); + mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP); spin_unlock_irqrestore(&mx3fb->lock, lock_flags); @@ -780,8 +757,6 @@ static int __set_par(struct fb_info *fbi, bool lock) if (sdc_init_panel(mx3fb, mode, (PICOS2KHZ(fbi->var.pixclock)) * 1000UL, fbi->var.xres, fbi->var.yres, - (fbi->var.sync & FB_SYNC_SWAP_RGB) ? - IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666, fbi->var.left_margin, fbi->var.hsync_len, fbi->var.right_margin + @@ -1349,6 +1324,12 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) const struct fb_videomode *mode; int ret, num_modes; + if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) { + dev_err(dev, "Illegal display data format %d\n", + mx3fb_pdata->disp_data_fmt); + return -EINVAL; + } + ichan->client = mx3fb; irq = ichan->eof_irq; @@ -1402,6 +1383,8 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) mx3fbi->mx3fb = mx3fb; mx3fbi->blank = FB_BLANK_NORMAL; + mx3fb->disp_data_fmt = mx3fb_pdata->disp_data_fmt; + init_completion(&mx3fbi->flip_cmpl); disable_irq(ichan->eof_irq); dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); -- cgit v0.10.2 From 3506c0d507144d9b0f19efd5a56d289f70611179 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Tue, 6 Dec 2011 16:15:54 +0530 Subject: DMA: PL330: Remove pm_runtime_xxx calls from pl330 probe/remove amba_probe() now calls pm_runtime_get_noresume() and pm_runtime_enable() for the devices before the device probe is called. Hence we don't need to call pm_runtime_get_xxx and pm_runtime_enable() in device probe again. In the same way, since amba_remove() calls the respective pm_runtime functions, those functions need not be called from device remove. This patch fixes following run time error with pl330 driver. dma-pl330 dma-pl330.0: Unbalanced pm_runtime_enable! dma-pl330 dma-pl330.0: failed to get runtime pm Signed-off-by: Giridhar Maruthy Signed-off-by: Tushar Behera Signed-off-by: Vinod Koul diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index e0da795..a573757 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -820,17 +820,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) amba_set_drvdata(adev, pdmac); -#ifdef CONFIG_PM_RUNTIME - /* to use the runtime PM helper functions */ - pm_runtime_enable(&adev->dev); - - /* enable the power domain */ - if (pm_runtime_get_sync(&adev->dev)) { - dev_err(&adev->dev, "failed to get runtime pm\n"); - ret = -ENODEV; - goto probe_err1; - } -#else +#ifndef CONFIG_PM_RUNTIME /* enable dma clk */ clk_enable(pdmac->clk); #endif @@ -971,10 +961,7 @@ static int __devexit pl330_remove(struct amba_device *adev) res = &adev->res; release_mem_region(res->start, resource_size(res)); -#ifdef CONFIG_PM_RUNTIME - pm_runtime_put(&adev->dev); - pm_runtime_disable(&adev->dev); -#else +#ifndef CONFIG_PM_RUNTIME clk_disable(pdmac->clk); #endif -- cgit v0.10.2 From 400312201b0cf4e4deaf75842f5e95212b382e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 8 Dec 2011 09:15:41 +0100 Subject: dma: mxs-dma: fix a typo in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lothar Waßmann Signed-off-by: Vinod Koul diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index bdf4672..d04662e 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -268,7 +268,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id) /* * When both completion and error of termination bits set at the * same time, we do not take it as an error. IOW, it only becomes - * an error we need to handler here in case of ether it's (1) an bus + * an error we need to handle here in case of either it's (1) a bus * error or (2) a termination error with no completion. */ stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */ -- cgit v0.10.2 From feb397de65c3f76e40ef70e264f2cdf688c850c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 8 Dec 2011 09:15:42 +0100 Subject: dma: mxs-dma: Always leave mxs_dma_init() with the clock disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to have the clock enabled all the time the driver is loaded. It will be enabled anyway in mxs_dma_alloc_chan_resources() when a channel is actually going to be used. Signed-off-by: Lothar Waßmann Signed-off-by: Vinod Koul diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index d04662e..b0e6ac3 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -580,7 +580,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) ret = clk_enable(mxs_dma->clk); if (ret) - goto err_out; + return ret; ret = mxs_reset_block(mxs_dma->base); if (ret) @@ -604,11 +604,8 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS, mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR); - clk_disable(mxs_dma->clk); - - return 0; - err_out: + clk_disable(mxs_dma->clk); return ret; } -- cgit v0.10.2 From 6d23ea4b1906f28f5d99ad6aeef7207c48be6bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 8 Dec 2011 09:15:43 +0100 Subject: dma: mxs-dma: make mxs_dma_prep_slave_sg() multi user safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a static variable for counting the number of CCWs attached to a DMA channel when appending a new descriptor is not multi user safe. Signed-off-by: Lothar Waßmann Signed-off-by: Vinod Koul diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b0e6ac3..1b4c6be 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -111,6 +111,7 @@ struct mxs_dma_chan { int chan_irq; struct mxs_dma_ccw *ccw; dma_addr_t ccw_phys; + int desc_count; dma_cookie_t last_completed; enum dma_status status; unsigned int flags; @@ -386,7 +387,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct scatterlist *sg; int i, j; u32 *pio; - static int idx; + int idx = append ? mxs_chan->desc_count : 0; if (mxs_chan->status == DMA_IN_PROGRESS && !append) return NULL; @@ -462,6 +463,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( } } } + mxs_chan->desc_count = idx; return &mxs_chan->desc; @@ -523,6 +525,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( i++; } + mxs_chan->desc_count = i; return &mxs_chan->desc; -- cgit v0.10.2 From 7ad7a345a4f17c08a1bb9bfdbb62f7793d84aa36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 8 Dec 2011 09:15:44 +0100 Subject: dma: mxs-dma: Don't use CLKGATE bits in CTRL0 to disable DMA channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is how the original Freescale code (unintentionally) worked, because the code path which would have asserted the CLKGATE bit was never actually reached in their code. This fixes the nefarious "DMA timout" bug when multiple DMA channels (e.g. GPMI NAND and MMC) are used at the same time. If a better fix for this problem should be found, the clkgate handling could be reinstated. See http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/065228.html Also reverse the order of mxs_dma_disable_chan() and mxs_dma_reset_chan() in mxs_dma_control() because mxs_dma_reset_chan() can only work when the DMA channel is enabled. Signed-off-by: Lothar Waßmann Signed-off-by: Vinod Koul diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 1b4c6be..6548595 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -44,7 +44,6 @@ #define HW_APBHX_CTRL0 0x000 #define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) #define BM_APBH_CTRL0_APB_BURST_EN (1 << 28) -#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8 #define BP_APBH_CTRL0_RESET_CHANNEL 16 #define HW_APBHX_CTRL1 0x010 #define HW_APBHX_CTRL2 0x020 @@ -131,23 +130,6 @@ struct mxs_dma_engine { struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; }; -static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable) -{ - struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; - int chan_id = mxs_chan->chan.chan_id; - int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR; - - /* enable apbh channel clock */ - if (dma_is_apbh()) { - if (apbh_is_old()) - writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL), - mxs_dma->base + HW_APBHX_CTRL0 + set_clr); - else - writel(1 << chan_id, - mxs_dma->base + HW_APBHX_CTRL0 + set_clr); - } -} - static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) { struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; @@ -166,9 +148,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; int chan_id = mxs_chan->chan.chan_id; - /* clkgate needs to be enabled before writing other registers */ - mxs_dma_clkgate(mxs_chan, 1); - /* set cmd_addr up */ writel(mxs_chan->ccw_phys, mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); @@ -179,9 +158,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) { - /* disable apbh channel clock */ - mxs_dma_clkgate(mxs_chan, 0); - mxs_chan->status = DMA_SUCCESS; } @@ -339,10 +315,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) if (ret) goto err_clk; - /* clkgate needs to be enabled for reset to finish */ - mxs_dma_clkgate(mxs_chan, 1); mxs_dma_reset_chan(mxs_chan); - mxs_dma_clkgate(mxs_chan, 0); dma_async_tx_descriptor_init(&mxs_chan->desc, chan); mxs_chan->desc.tx_submit = mxs_dma_tx_submit; @@ -542,8 +515,8 @@ static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, switch (cmd) { case DMA_TERMINATE_ALL: - mxs_dma_disable_chan(mxs_chan); mxs_dma_reset_chan(mxs_chan); + mxs_dma_disable_chan(mxs_chan); break; case DMA_PAUSE: mxs_dma_pause_chan(mxs_chan); -- cgit v0.10.2 From 62268ce9170c5466332c046ff6ddafcb67751502 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 13 Dec 2011 23:48:03 +0800 Subject: dmaengine: add DMA_TRANS_NONE to dma_transfer_direction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before dma_transfer_direction was introduced to replace dma_data_direction, some dmaengine device uses DMA_NONE of dma_data_direction for some talk with its client drivers. The mxs-dma and its clients mxs-mmc and gpmi-nand are such case. This patch adds DMA_TRANS_NONE to dma_transfer_direction and migrate the DMA_NONE use in mxs-dma to it. It also fixes the compile warning below. CC drivers/dma/mxs-dma.o drivers/dma/mxs-dma.c: In function ‘mxs_dma_prep_slave_sg’: drivers/dma/mxs-dma.c:420:16: warning: comparison between ‘enum dma_transfer_direction’ and ‘enum dma_data_direction’ Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 6548595..493af2f 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -391,7 +391,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( idx = 0; } - if (direction == DMA_NONE) { + if (direction == DMA_TRANS_NONE) { ccw = &mxs_chan->ccw[idx++]; pio = (u32 *) sgl; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 5532bb8..679b349 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -88,6 +88,7 @@ enum dma_transfer_direction { DMA_MEM_TO_DEV, DMA_DEV_TO_MEM, DMA_DEV_TO_DEV, + DMA_TRANS_NONE, }; /** -- cgit v0.10.2 From a4e3e86d66ffc640ac54acffa29450e327a80ae2 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 13 Dec 2011 23:48:04 +0800 Subject: mmc: mxs-mmc: fix the dma_transfer_direction migration The commit 05f5799 (mmc-host: move to dma_transfer_direction) left out the DMA_NONE, in turn breaks the driver as below. [ 0.650000] mxs-mmc mxs-mmc.0: initialized [ 0.650000] mxs-mmc mxs-mmc.1: initialized [ 0.690000] mxs-dma mxs-dma-apbh: maximum bytes for sg entry exceeded: -55906 7475 > 65280 [ 0.690000] mxs-mmc mxs-mmc.0: mxs_mmc_ac: failed to prep dma Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 0a878b1..94d7358 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -357,6 +357,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host) host->ssp_pio_words[1] = cmd0; host->ssp_pio_words[2] = cmd1; host->dma_dir = DMA_NONE; + host->slave_dirn = DMA_TRANS_NONE; desc = mxs_mmc_prep_dma(host, 0); if (!desc) goto out; @@ -396,6 +397,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host) host->ssp_pio_words[1] = cmd0; host->ssp_pio_words[2] = cmd1; host->dma_dir = DMA_NONE; + host->slave_dirn = DMA_TRANS_NONE; desc = mxs_mmc_prep_dma(host, 0); if (!desc) goto out; @@ -514,6 +516,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) host->ssp_pio_words[1] = cmd0; host->ssp_pio_words[2] = cmd1; host->dma_dir = DMA_NONE; + host->slave_dirn = DMA_TRANS_NONE; desc = mxs_mmc_prep_dma(host, 0); if (!desc) goto out; -- cgit v0.10.2 From 4e82786f7039cb707c031dcf0dc84c025e149487 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Tue, 13 Dec 2011 23:48:05 +0800 Subject: mtd: fix compile error for gpmi-nand The driver gpmi-nand should compile at least. This patch adds the missing gpmi-nand.h to fix the compile error below. CC drivers/mtd/nand/gpmi-nand/gpmi-nand.o CC drivers/mtd/nand/gpmi-nand/gpmi-lib.o drivers/mtd/nand/gpmi-nand/gpmi-nand.c:25:33: fatal error: linux/mtd/gpmi-nand.h: No such file or directory drivers/mtd/nand/gpmi-nand/gpmi-lib.c:21:33: fatal error: linux/mtd/gpmi-nand.h: No such file or directory This header is grabbed from patch below, which has not been postponed for merging. [PATCH v8 1/4] ARM: mxs: add GPMI-NAND support for imx23/imx28 http://permalink.gmane.org/gmane.linux.drivers.mtd/37338 Signed-off-by: Huang Shijie Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h new file mode 100644 index 0000000..69b6dbf --- /dev/null +++ b/include/linux/mtd/gpmi-nand.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __MACH_MXS_GPMI_NAND_H__ +#define __MACH_MXS_GPMI_NAND_H__ + +/* The size of the resources is fixed. */ +#define GPMI_NAND_RES_SIZE 6 + +/* Resource names for the GPMI NAND driver. */ +#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "GPMI NAND GPMI Registers" +#define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" +#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "GPMI NAND BCH Registers" +#define GPMI_NAND_BCH_INTERRUPT_RES_NAME "GPMI NAND BCH Interrupt" +#define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" +#define GPMI_NAND_DMA_INTERRUPT_RES_NAME "GPMI NAND DMA Interrupt" + +/** + * struct gpmi_nand_platform_data - GPMI NAND driver platform data. + * + * This structure communicates platform-specific information to the GPMI NAND + * driver that can't be expressed as resources. + * + * @platform_init: A pointer to a function the driver will call to + * initialize the platform (e.g., set up the pin mux). + * @min_prop_delay_in_ns: Minimum propagation delay of GPMI signals to and + * from the NAND Flash device, in nanoseconds. + * @max_prop_delay_in_ns: Maximum propagation delay of GPMI signals to and + * from the NAND Flash device, in nanoseconds. + * @max_chip_count: The maximum number of chips for which the driver + * should configure the hardware. This value most + * likely reflects the number of pins that are + * connected to a NAND Flash device. If this is + * greater than the SoC hardware can support, the + * driver will print a message and fail to initialize. + * @partitions: An optional pointer to an array of partition + * descriptions. + * @partition_count: The number of elements in the partitions array. + */ +struct gpmi_nand_platform_data { + /* SoC hardware information. */ + int (*platform_init)(void); + + /* NAND Flash information. */ + unsigned int min_prop_delay_in_ns; + unsigned int max_prop_delay_in_ns; + unsigned int max_chip_count; + + /* Medium information. */ + struct mtd_partition *partitions; + unsigned partition_count; +}; +#endif -- cgit v0.10.2 From 0ef7e206d6a5a5de0cd84ed4925a4f688c62e732 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 13 Dec 2011 23:48:06 +0800 Subject: mtd: gpmi-nand: move to dma_transfer_direction This patch fixes usage of dma direction to adopt dma_transfer_direction. Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index de4db76..c4c4d6d 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -827,7 +827,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) pio[1] = pio[2] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -839,7 +839,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) sg_init_one(sgl, this->cmd_buffer, this->command_length); dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, - sgl, 1, DMA_TO_DEVICE, 1); + sgl, 1, DMA_MEM_TO_DEV, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -872,7 +872,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -881,7 +881,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) /* [2] send DMA request */ prepare_data_dma(this, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_TO_DEVICE, 1); + 1, DMA_MEM_TO_DEV, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -908,7 +908,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -917,7 +917,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) /* [2] : send DMA request */ prepare_data_dma(this, DMA_FROM_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_FROM_DEVICE, 1); + 1, DMA_DEV_TO_MEM, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -964,7 +964,7 @@ int gpmi_send_page(struct gpmi_nand_data *this, desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -998,7 +998,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, | BF_GPMI_CTRL0_XFER_COUNT(0); pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, - (struct scatterlist *)pio, 2, DMA_NONE, 0); + (struct scatterlist *)pio, 2, + DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -1027,7 +1028,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, pio[5] = auxiliary; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 1); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -1045,7 +1046,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, - (struct scatterlist *)pio, 2, DMA_NONE, 1); + (struct scatterlist *)pio, 2, + DMA_TRANS_NONE, 1); if (!desc) { pr_err("step 3 error\n"); return -1; -- cgit v0.10.2 From 1fded07513ea57b5ee128958ff119e05588b7227 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 16 Dec 2011 11:01:38 +0200 Subject: dmaengine: intel_mid_dma: locking and freeing fixes Two issues are fixed: 1. DMA descriptors are reused so when freeing lli structures that are linked to them, the pointer must be nulled. 2. midc_scan_descriptors() must be called with the channel lock held. Signed-off-by: Adrian Hunter Signed-off-by: Vinod Koul diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 01929ed..d4b9616 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -280,7 +280,8 @@ static void midc_dostart(struct intel_mid_dma_chan *midc, * callbacks but must be called with the lock held. */ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc, - struct intel_mid_dma_desc *desc) + struct intel_mid_dma_desc *desc) + __releases(&midc->lock) __acquires(&midc->lock) { struct dma_async_tx_descriptor *txd = &desc->txd; dma_async_tx_callback callback_txd = NULL; @@ -311,6 +312,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc, pci_pool_free(desc->lli_pool, desc->lli, desc->lli_phys); pci_pool_destroy(desc->lli_pool); + desc->lli = NULL; } list_move(&desc->desc_node, &midc->free_list); midc->busy = false; @@ -490,7 +492,9 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan, ret = dma_async_is_complete(cookie, last_complete, last_used); if (ret != DMA_SUCCESS) { + spin_lock_bh(&midc->lock); midc_scan_descriptors(to_middma_device(chan->device), midc); + spin_unlock_bh(&midc->lock); last_complete = midc->completed; last_used = chan->cookie; @@ -566,6 +570,7 @@ static int intel_mid_dma_device_control(struct dma_chan *chan, pci_pool_free(desc->lli_pool, desc->lli, desc->lli_phys); pci_pool_destroy(desc->lli_pool); + desc->lli = NULL; } list_move(&desc->desc_node, &midc->free_list); } -- cgit v0.10.2 From 2a0ff7a602714990b10a8749e908dad48401138e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 16 Dec 2011 11:01:39 +0200 Subject: dmaengine: intel_mid_dma: error path fix Add missing iounmap in error path. Signed-off-by: Adrian Hunter Signed-off-by: Vinod Koul diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index d4b9616..bbcd470 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -1104,7 +1104,8 @@ static int mid_setup_dma(struct pci_dev *pdev) LNW_PERIPHRAL_MASK_SIZE); if (dma->mask_reg == NULL) { pr_err("ERR_MDMA:Can't map periphral intr space !!\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_ioremap; } } else dma->mask_reg = NULL; @@ -1201,6 +1202,9 @@ static int mid_setup_dma(struct pci_dev *pdev) err_engine: free_irq(pdev->irq, dma); err_irq: + if (dma->mask_reg) + iounmap(dma->mask_reg); +err_ioremap: pci_pool_destroy(dma->dma_pool); err_dma_pool: pr_err("ERR_MDMA:setup_dma failed: %d\n", err); -- cgit v0.10.2 From d6077c92b6c51299eac7c2673631d6394ee2191a Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 14 Dec 2011 15:47:46 +0800 Subject: ASoC: mxs: correct 'direction' of device_prep_dma_cyclic The commit 49920bc (dmaengine: add new enum dma_transfer_direction) changes the type of parameter 'direction' of device_prep_dma_cyclic from dma_data_direction to dma_transfer_direction. Signed-off-by: Shawn Guo Signed-off-by: Vinod Koul diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index dea5aa4..4b48a16 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -136,7 +136,7 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, iprtd->period_bytes * iprtd->periods, iprtd->period_bytes, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); + DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); if (!iprtd->desc) { dev_err(&chan->dev->device, "cannot prepare slave dma\n"); return -EINVAL; -- cgit v0.10.2 From 8730790b971d747dd4508d22fbc1a4f9422c2803 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Fri, 16 Dec 2011 11:01:40 +0200 Subject: dmaengine: intel_mid_dma: remove legacy pm interface Drivers should not support both legacy pm and new framework. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Vinod Koul diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index bbcd470..74f70aa 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -873,7 +873,7 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan) pm_runtime_get_sync(&mid->pdev->dev); if (mid->state == SUSPENDED) { - if (dma_resume(mid->pdev)) { + if (dma_resume(&mid->pdev->dev)) { pr_err("ERR_MDMA: resume failed"); return -EFAULT; } @@ -1346,8 +1346,9 @@ static void __devexit intel_mid_dma_remove(struct pci_dev *pdev) * * This function is called by OS when a power event occurs */ -int dma_suspend(struct pci_dev *pci, pm_message_t state) +static int dma_suspend(struct device *dev) { + struct pci_dev *pci = to_pci_dev(dev); int i; struct middma_device *device = pci_get_drvdata(pci); pr_debug("MDMA: dma_suspend called\n"); @@ -1371,8 +1372,9 @@ int dma_suspend(struct pci_dev *pci, pm_message_t state) * * This function is called by OS when a power event occurs */ -int dma_resume(struct pci_dev *pci) +int dma_resume(struct device *dev) { + struct pci_dev *pci = to_pci_dev(dev); int ret; struct middma_device *device = pci_get_drvdata(pci); @@ -1438,6 +1440,8 @@ static const struct dev_pm_ops intel_mid_dma_pm = { .runtime_suspend = dma_runtime_suspend, .runtime_resume = dma_runtime_resume, .runtime_idle = dma_runtime_idle, + .suspend = dma_suspend, + .resume = dma_resume, }; static struct pci_driver intel_mid_dma_pci_driver = { @@ -1446,8 +1450,6 @@ static struct pci_driver intel_mid_dma_pci_driver = { .probe = intel_mid_dma_probe, .remove = __devexit_p(intel_mid_dma_remove), #ifdef CONFIG_PM - .suspend = dma_suspend, - .resume = dma_resume, .driver = { .pm = &intel_mid_dma_pm, }, diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h index c6de919..c83d35b 100644 --- a/drivers/dma/intel_mid_dma_regs.h +++ b/drivers/dma/intel_mid_dma_regs.h @@ -296,6 +296,6 @@ static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave } -int dma_resume(struct pci_dev *pci); +int dma_resume(struct device *dev); #endif /*__INTEL_MID_DMAC_REGS_H__*/ -- cgit v0.10.2 From e9f3a49c9698da6f6b606d5e048ddce308438763 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 28 Dec 2011 11:27:40 +0530 Subject: dmaengine/ste_dma40: clear LNK on channel startup Otherwise if a previously physical channel is used as a logical channel, the LNK may have old values which affect the operation of the logical channel since the LNK register has different semantics between physical and logical channels. Signed-off-by: Rabin Vincent Reviewed-by: Jonas ABERG Signed-off-by: Narayanan G Acked-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 972dc35..cc5ecbc 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1104,6 +1104,10 @@ static void d40_config_write(struct d40_chan *d40c) /* Set LIDX for lcla */ writel(lidx, chanbase + D40_CHAN_REG_SSELT); writel(lidx, chanbase + D40_CHAN_REG_SDELT); + + /* Clear LNK which will be used by d40_chan_has_events() */ + writel(0, chanbase + D40_CHAN_REG_SSLNK); + writel(0, chanbase + D40_CHAN_REG_SDLNK); } } -- cgit v0.10.2 From f69f2e264f6388df6d3cae45dd67ddfd52aaa14b Mon Sep 17 00:00:00 2001 From: Haitao Zhang Date: Sun, 1 Jan 2012 11:30:06 +0800 Subject: dma/imx-sdma: save irq flags when use spin_lock in sdma_tx_submit mx53_loco: fix deadlock report from sdma_tx_submit() during boot BugLink: http://bugs.launchpad.net/bugs/878701 Adjust to use spin_lock_irqsave()/spin_unlock_irqresotre(), so to make it safe when called from interrupt context. Signed-off-by: Haitao Zhang Signed-off-by: Eric Miao Signed-off-by: Richard Zhao Acked-by: Sascha Hauer Signed-off-by: Vinod Koul diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index f59fd8f..a8af379 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -836,17 +836,18 @@ static struct sdma_channel *to_sdma_chan(struct dma_chan *chan) static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx) { + unsigned long flags; struct sdma_channel *sdmac = to_sdma_chan(tx->chan); struct sdma_engine *sdma = sdmac->sdma; dma_cookie_t cookie; - spin_lock_irq(&sdmac->lock); + spin_lock_irqsave(&sdmac->lock, flags); cookie = sdma_assign_cookie(sdmac); sdma_enable_channel(sdma, sdmac->channel); - spin_unlock_irq(&sdmac->lock); + spin_unlock_irqrestore(&sdmac->lock, flags); return cookie; } -- cgit v0.10.2 From c11b46c32c8a9bf05fdb76d70d8dc74fcbfd02d1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 4 Jan 2012 15:34:17 +0100 Subject: dma: shdma: fix runtime PM: clear channel buffers on reset On platforms, supporting power domains, if the domain, containing a DMAC instance is powered down, the driver fails to resume correctly. On those platforms DMAC channels have an additional CHCLR register for clearing channel buffers. Using this register during runtime resume fixes the problem. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 592304f..54043cd 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -56,6 +56,15 @@ static LIST_HEAD(sh_dmae_devices); static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); +static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan); + +static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data) +{ + struct sh_dmae_device *shdev = to_sh_dev(sh_dc); + + __raw_writel(data, shdev->chan_reg + + shdev->pdata->channel[sh_dc->id].chclr_offset); +} static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg) { @@ -128,6 +137,15 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME); + if (shdev->pdata->chclr_present) { + int i; + for (i = 0; i < shdev->pdata->channel_num; i++) { + struct sh_dmae_chan *sh_chan = shdev->chan[i]; + if (sh_chan) + chclr_write(sh_chan, 0); + } + } + dmaor_write(shdev, dmaor | shdev->pdata->dmaor_init); dmaor = dmaor_read(shdev); @@ -138,6 +156,10 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n"); return -EIO; } + if (shdev->pdata->dmaor_init & ~dmaor) + dev_warn(shdev->common.dev, + "DMAOR=0x%x hasn't latched the initial value 0x%x.\n", + dmaor, shdev->pdata->dmaor_init); return 0; } @@ -258,8 +280,6 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) return 0; } -static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan); - static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) { struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c; @@ -339,6 +359,8 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) sh_chan_xfer_ld_queue(sh_chan); sh_chan->pm_state = DMAE_PM_ESTABLISHED; } + } else { + sh_chan->pm_state = DMAE_PM_PENDING; } spin_unlock_irq(&sh_chan->desc_lock); @@ -1224,6 +1246,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) platform_set_drvdata(pdev, shdev); + shdev->common.dev = &pdev->dev; + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -1253,7 +1277,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev) shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg; shdev->common.device_control = sh_dmae_control; - shdev->common.dev = &pdev->dev; /* Default transfer size of 32 bytes requires 32-byte alignment */ shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; @@ -1434,22 +1457,17 @@ static int sh_dmae_runtime_resume(struct device *dev) #ifdef CONFIG_PM static int sh_dmae_suspend(struct device *dev) { - struct sh_dmae_device *shdev = dev_get_drvdata(dev); - int i; - - for (i = 0; i < shdev->pdata->channel_num; i++) { - struct sh_dmae_chan *sh_chan = shdev->chan[i]; - if (sh_chan->descs_allocated) - sh_chan->pm_error = pm_runtime_put_sync(dev); - } - return 0; } static int sh_dmae_resume(struct device *dev) { struct sh_dmae_device *shdev = dev_get_drvdata(dev); - int i; + int i, ret; + + ret = sh_dmae_rst(shdev); + if (ret < 0) + dev_err(dev, "Failed to reset!\n"); for (i = 0; i < shdev->pdata->channel_num; i++) { struct sh_dmae_chan *sh_chan = shdev->chan[i]; @@ -1458,9 +1476,6 @@ static int sh_dmae_resume(struct device *dev) if (!sh_chan->descs_allocated) continue; - if (!sh_chan->pm_error) - pm_runtime_get_sync(dev); - if (param) { const struct sh_dmae_slave_config *cfg = param->config; dmae_set_dmars(sh_chan, cfg->mid_rid); diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 62ef693..8cd7fe5 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -48,6 +48,7 @@ struct sh_dmae_channel { unsigned int offset; unsigned int dmars; unsigned int dmars_bit; + unsigned int chclr_offset; }; struct sh_dmae_pdata { @@ -68,6 +69,7 @@ struct sh_dmae_pdata { unsigned int dmaor_is_32bit:1; unsigned int needs_tend_set:1; unsigned int no_dmars:1; + unsigned int chclr_present:1; }; /* DMA register */ -- cgit v0.10.2 From e08b881a69d638175bfa99b5af4d72b731633ea7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 4 Jan 2012 15:34:21 +0100 Subject: ARM: mach-shmobile: specify CHCLR registers on SH7372 Signed-off-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 2380389..83dc940 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -445,31 +445,39 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { }, }; +#define SH7372_CHCLR 0x220 + static const struct sh_dmae_channel sh7372_dmae_channels[] = { { .offset = 0, .dmars = 0, .dmars_bit = 0, + .chclr_offset = SH7372_CHCLR + 0, }, { .offset = 0x10, .dmars = 0, .dmars_bit = 8, + .chclr_offset = SH7372_CHCLR + 0x10, }, { .offset = 0x20, .dmars = 4, .dmars_bit = 0, + .chclr_offset = SH7372_CHCLR + 0x20, }, { .offset = 0x30, .dmars = 4, .dmars_bit = 8, + .chclr_offset = SH7372_CHCLR + 0x30, }, { .offset = 0x50, .dmars = 8, .dmars_bit = 0, + .chclr_offset = SH7372_CHCLR + 0x50, }, { .offset = 0x60, .dmars = 8, .dmars_bit = 8, + .chclr_offset = SH7372_CHCLR + 0x60, } }; @@ -487,6 +495,7 @@ static struct sh_dmae_pdata dma_platform_data = { .ts_shift = ts_shift, .ts_shift_num = ARRAY_SIZE(ts_shift), .dmaor_init = DMAOR_DME, + .chclr_present = 1, }; /* Resource order important! */ @@ -494,7 +503,7 @@ static struct resource sh7372_dmae0_resources[] = { { /* Channel registers and DMAOR */ .start = 0xfe008020, - .end = 0xfe00808f, + .end = 0xfe00828f, .flags = IORESOURCE_MEM, }, { @@ -522,7 +531,7 @@ static struct resource sh7372_dmae1_resources[] = { { /* Channel registers and DMAOR */ .start = 0xfe018020, - .end = 0xfe01808f, + .end = 0xfe01828f, .flags = IORESOURCE_MEM, }, { @@ -550,7 +559,7 @@ static struct resource sh7372_dmae2_resources[] = { { /* Channel registers and DMAOR */ .start = 0xfe028020, - .end = 0xfe02808f, + .end = 0xfe02828f, .flags = IORESOURCE_MEM, }, { -- cgit v0.10.2