Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c11371d authored by Dan Williams's avatar Dan Williams
Browse files

Merge branch 'for_dan' of git://git.infradead.org/users/vkoul/slave-dma into dmaengine

* 'for_dan' of git://git.infradead.org/users/vkoul/slave-dma:
  drivers, pch_dma: Fix warning when CONFIG_PM=n.
  dmaengine/dw_dmac fix: use readl & writel instead of __raw_readl & __raw_writel
  avr32: at32ap700x: Specify DMA Flow Controller, Src and Dst msize
  dw_dmac: Setting Default Burst length for transfers as 16.
  dw_dmac: Allow src/dst msize & flow controller to be configured at runtime
  dw_dmac: Changing type of src_master and dest_master to u8.
  dw_dmac: Pass Channel Priority from platform_data
  dw_dmac: Pass Channel Allocation Order from platform_data
  dw_dmac: Mark all tx_descriptors with DMA_CRTL_ACK after xfer finish
  dw_dmac: Change value of DWC_MAX_COUNT to 4095.
  dw_dmac: Adding support for 64 bit access width for memcpy xfers
  dw_dmac: Calling dwc_scan_descriptors from dwc_tx_status() after taking lock
  dw_dmac: Move single descriptor from dwc->queue to dwc->active_list in dwc_complete_all
  dw_dmac: Replace module_init() with subsys_initcall()
  dw_dmac: Remove compilation dependency from AVR32 and put on HAVE_CLK
  dmaengine: mxs-dma: add dma support for i.MX23/28
  pch_dma: set the number of array correctly
  pch_dma: fix kernel error issue
parents f5539af5 0b863b33
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright 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 version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __MACH_MXS_DMA_H__
#define __MACH_MXS_DMA_H__

struct mxs_dma_data {
	int chan_irq;
};

static inline int mxs_dma_is_apbh(struct dma_chan *chan)
{
	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh");
}

static inline int mxs_dma_is_apbx(struct dma_chan *chan)
{
	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx");
}

#endif /* __MACH_MXS_DMA_H__ */
+9 −0
Original line number Diff line number Diff line
@@ -2050,6 +2050,9 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
		rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
		rx_dws->src_master = 0;
		rx_dws->dst_master = 1;
		rx_dws->src_msize = DW_DMA_MSIZE_1;
		rx_dws->dst_msize = DW_DMA_MSIZE_1;
		rx_dws->fc = DW_DMA_FC_D_P2M;
	}

	/* Check if DMA slave interface for playback should be configured. */
@@ -2060,6 +2063,9 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
		tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
		rx_dws->src_master = 0;
		rx_dws->dst_master = 1;
		tx_dws->src_msize = DW_DMA_MSIZE_1;
		tx_dws->dst_msize = DW_DMA_MSIZE_1;
		tx_dws->fc = DW_DMA_FC_D_M2P;
	}

	if (platform_device_add_data(pdev, data,
@@ -2134,6 +2140,9 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data)
	dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
	dws->src_master = 0;
	dws->dst_master = 1;
	dws->src_msize = DW_DMA_MSIZE_1;
	dws->dst_msize = DW_DMA_MSIZE_1;
	dws->fc = DW_DMA_FC_D_M2P;

	if (platform_device_add_data(pdev, data,
				sizeof(struct atmel_abdac_pdata)))
+9 −1
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ config INTEL_IOP_ADMA

config DW_DMAC
	tristate "Synopsys DesignWare AHB DMA support"
	depends on AVR32
	depends on HAVE_CLK
	select DMA_ENGINE
	default y if CPU_AT32AP7000
	help
@@ -227,6 +227,14 @@ config IMX_DMA
	  Support the i.MX DMA engine. This engine is integrated into
	  Freescale i.MX1/21/27 chips.

config MXS_DMA
	bool "MXS DMA support"
	depends on SOC_IMX23 || SOC_IMX28
	select DMA_ENGINE
	help
	  Support the MXS DMA engine. This engine including APBH-DMA
	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.

config DMA_ENGINE
	bool

+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
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_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_PL330_DMA) += pl330.o
+46 −25
Original line number Diff line number Diff line
@@ -36,9 +36,11 @@
		struct dw_dma_slave *__slave = (private);	\
		int dms = __slave ? __slave->dst_master : 0;	\
		int sms = __slave ? __slave->src_master : 1;	\
		u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \
		u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \
								\
		(DWC_CTLL_DST_MSIZE(0)				\
		 | DWC_CTLL_SRC_MSIZE(0)			\
		(DWC_CTLL_DST_MSIZE(dmsize)			\
		 | DWC_CTLL_SRC_MSIZE(smsize)			\
		 | DWC_CTLL_LLP_D_EN				\
		 | DWC_CTLL_LLP_S_EN				\
		 | DWC_CTLL_DMS(dms)				\
@@ -47,14 +49,13 @@

/*
 * This is configuration-dependent and usually a funny size like 4095.
 * Let's round it down to the nearest power of two.
 *
 * Note that this is a transfer count, i.e. if we transfer 32-bit
 * words, we can do 8192 bytes per descriptor.
 * words, we can do 16380 bytes per descriptor.
 *
 * This parameter is also system-specific.
 */
#define DWC_MAX_COUNT	2048U
#define DWC_MAX_COUNT	4095U

/*
 * Number of descriptors to allocate for each channel. This should be
@@ -87,11 +88,6 @@ static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
	return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
}

static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
{
	return list_entry(dwc->queue.next, struct dw_desc, desc_node);
}

static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
{
	struct dw_desc *desc, *_desc;
@@ -204,6 +200,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
	dma_async_tx_callback		callback;
	void				*param;
	struct dma_async_tx_descriptor	*txd = &desc->txd;
	struct dw_desc			*child;

	dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);

@@ -212,6 +209,12 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
	param = txd->callback_param;

	dwc_sync_desc_for_cpu(dwc, desc);

	/* async_tx_ack */
	list_for_each_entry(child, &desc->tx_list, desc_node)
		async_tx_ack(&child->txd);
	async_tx_ack(&desc->txd);

	list_splice_init(&desc->tx_list, &dwc->free_list);
	list_move(&desc->desc_node, &dwc->free_list);

@@ -262,10 +265,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
	 * Submit queued descriptors ASAP, i.e. before we go through
	 * the completed ones.
	 */
	if (!list_empty(&dwc->queue))
		dwc_dostart(dwc, dwc_first_queued(dwc));
	list_splice_init(&dwc->active_list, &list);
	list_splice_init(&dwc->queue, &dwc->active_list);
	if (!list_empty(&dwc->queue)) {
		list_move(dwc->queue.next, &dwc->active_list);
		dwc_dostart(dwc, dwc_first_active(dwc));
	}

	list_for_each_entry_safe(desc, _desc, &list, desc_node)
		dwc_descriptor_complete(dwc, desc);
@@ -325,8 +329,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
		cpu_relax();

	if (!list_empty(&dwc->queue)) {
		dwc_dostart(dwc, dwc_first_queued(dwc));
		list_splice_init(&dwc->queue, &dwc->active_list);
		list_move(dwc->queue.next, &dwc->active_list);
		dwc_dostart(dwc, dwc_first_active(dwc));
	}
}

@@ -352,7 +356,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
	 */
	bad_desc = dwc_first_active(dwc);
	list_del_init(&bad_desc->desc_node);
	list_splice_init(&dwc->queue, dwc->active_list.prev);
	list_move(dwc->queue.next, dwc->active_list.prev);

	/* Clear the error flag and try to restart the controller */
	dma_writel(dw, CLEAR.ERROR, dwc->mask);
@@ -547,8 +551,8 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
	if (list_empty(&dwc->active_list)) {
		dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
				desc->txd.cookie);
		dwc_dostart(dwc, desc);
		list_add_tail(&desc->desc_node, &dwc->active_list);
		dwc_dostart(dwc, dwc_first_active(dwc));
	} else {
		dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
				desc->txd.cookie);
@@ -587,7 +591,9 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
	 * We can be a lot more clever here, but this should take care
	 * of the most common optimization.
	 */
	if (!((src | dest  | len) & 3))
	if (!((src | dest  | len) & 7))
		src_width = dst_width = 3;
	else if (!((src | dest  | len) & 3))
		src_width = dst_width = 2;
	else if (!((src | dest | len) & 1))
		src_width = dst_width = 1;
@@ -679,7 +685,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
				| DWC_CTLL_DST_WIDTH(reg_width)
				| DWC_CTLL_DST_FIX
				| DWC_CTLL_SRC_INC
				| DWC_CTLL_FC_M2P);
				| DWC_CTLL_FC(dws->fc));
		reg = dws->tx_reg;
		for_each_sg(sgl, sg, sg_len, i) {
			struct dw_desc	*desc;
@@ -724,7 +730,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
				| DWC_CTLL_SRC_WIDTH(reg_width)
				| DWC_CTLL_DST_INC
				| DWC_CTLL_SRC_FIX
				| DWC_CTLL_FC_P2M);
				| DWC_CTLL_FC(dws->fc));

		reg = dws->rx_reg;
		for_each_sg(sgl, sg, sg_len, i) {
@@ -840,7 +846,9 @@ dwc_tx_status(struct dma_chan *chan,

	ret = dma_async_is_complete(cookie, last_complete, last_used);
	if (ret != DMA_SUCCESS) {
		spin_lock_bh(&dwc->lock);
		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
		spin_unlock_bh(&dwc->lock);

		last_complete = dwc->completed;
		last_used = chan->cookie;
@@ -895,8 +903,11 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
		BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);

		cfghi = dws->cfg_hi;
		cfglo = dws->cfg_lo;
		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);

@@ -1137,7 +1148,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
					| DWC_CTLL_SRC_WIDTH(reg_width)
					| DWC_CTLL_DST_FIX
					| DWC_CTLL_SRC_INC
					| DWC_CTLL_FC_M2P
					| DWC_CTLL_FC(dws->fc)
					| DWC_CTLL_INT_EN);
			break;
		case DMA_FROM_DEVICE:
@@ -1148,7 +1159,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
					| DWC_CTLL_DST_WIDTH(reg_width)
					| DWC_CTLL_DST_INC
					| DWC_CTLL_SRC_FIX
					| DWC_CTLL_FC_P2M
					| DWC_CTLL_FC(dws->fc)
					| DWC_CTLL_INT_EN);
			break;
		default:
@@ -1313,7 +1324,17 @@ static int __init dw_probe(struct platform_device *pdev)
		dwc->chan.device = &dw->dma;
		dwc->chan.cookie = dwc->completed = 1;
		dwc->chan.chan_id = i;
		list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
		if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
			list_add_tail(&dwc->chan.device_node,
					&dw->dma.channels);
		else
			list_add(&dwc->chan.device_node, &dw->dma.channels);

		/* 7 is highest priority & 0 is lowest. */
		if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
			dwc->priority = 7 - i;
		else
			dwc->priority = i;

		dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
		spin_lock_init(&dwc->lock);
@@ -1455,7 +1476,7 @@ static int __init dw_init(void)
{
	return platform_driver_probe(&dw_driver, dw_probe);
}
module_init(dw_init);
subsys_initcall(dw_init);

static void __exit dw_exit(void)
{
Loading