diff options
| author | Tony Lindgren <tony@atomide.com> | 2010-12-21 16:48:20 -0800 | 
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2010-12-21 16:48:20 -0800 | 
| commit | 6971071cdda79cad5f53ba390e466d696e7e9006 (patch) | |
| tree | afa3f33334ac8115caa05a53addea137bcbe9164 | |
| parent | 4584acc3ee236424b5d0b52f143d980cae3c2be5 (diff) | |
| parent | f31cc9622d75c1c6f041d786698daa425c0425c2 (diff) | |
| download | olio-linux-3.10-6971071cdda79cad5f53ba390e466d696e7e9006.tar.xz olio-linux-3.10-6971071cdda79cad5f53ba390e466d696e7e9006.zip  | |
Merge branch 'devel-dma' into omap-for-linus
| -rw-r--r-- | arch/arm/mach-omap1/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap1/dma.c | 390 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/dma.c | 297 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_2420_data.c | 86 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_2430_data.c | 86 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 97 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 102 | ||||
| -rw-r--r-- | arch/arm/plat-omap/dma.c | 695 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/dma.h | 232 | 
10 files changed, 1450 insertions, 539 deletions
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 0b1c07ffa2f..6ee19504845 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -3,7 +3,7 @@  #  # Common support -obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o +obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o  obj-y += clock.o clock_data.o opp_data.o  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c new file mode 100644 index 00000000000..d8559344c6e --- /dev/null +++ b/arch/arm/mach-omap1/dma.c @@ -0,0 +1,390 @@ +/* + * OMAP1/OMAP7xx - specific DMA driver + * + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä <juha.yrjola@nokia.com> + * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak <imre.deak@nokia.com> + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into platform driver + *                   - G, Manjunath Kondaiah <manjugk@ti.com> + * + * 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. + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> + +#include <plat/dma.h> +#include <plat/tc.h> +#include <plat/irqs.h> + +#define OMAP1_DMA_BASE			(0xfffed800) +#define OMAP1_LOGICAL_DMA_CH_COUNT	17 +#define OMAP1_DMA_STRIDE		0x40 + +static u32 errata; +static u32 enable_1510_mode; +static u8 dma_stride; +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; + +static u16 reg_map[] = { +	[GCR]		= 0x400, +	[GSCR]		= 0x404, +	[GRST1]		= 0x408, +	[HW_ID]		= 0x442, +	[PCH2_ID]	= 0x444, +	[PCH0_ID]	= 0x446, +	[PCH1_ID]	= 0x448, +	[PCHG_ID]	= 0x44a, +	[PCHD_ID]	= 0x44c, +	[CAPS_0]	= 0x44e, +	[CAPS_1]	= 0x452, +	[CAPS_2]	= 0x456, +	[CAPS_3]	= 0x458, +	[CAPS_4]	= 0x45a, +	[PCH2_SR]	= 0x460, +	[PCH0_SR]	= 0x480, +	[PCH1_SR]	= 0x482, +	[PCHD_SR]	= 0x4c0, + +	/* Common Registers */ +	[CSDP]		= 0x00, +	[CCR]		= 0x02, +	[CICR]		= 0x04, +	[CSR]		= 0x06, +	[CEN]		= 0x10, +	[CFN]		= 0x12, +	[CSFI]		= 0x14, +	[CSEI]		= 0x16, +	[CPC]		= 0x18,	/* 15xx only */ +	[CSAC]		= 0x18, +	[CDAC]		= 0x1a, +	[CDEI]		= 0x1c, +	[CDFI]		= 0x1e, +	[CLNK_CTRL]	= 0x28, + +	/* Channel specific register offsets */ +	[CSSA]		= 0x08, +	[CDSA]		= 0x0c, +	[COLOR]		= 0x20, +	[CCR2]		= 0x24, +	[LCH_CTRL]	= 0x2a, +}; + +static struct resource res[] __initdata = { +	[0] = { +		.start	= OMAP1_DMA_BASE, +		.end	= OMAP1_DMA_BASE + SZ_2K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.name   = "0", +		.start  = INT_DMA_CH0_6, +		.flags  = IORESOURCE_IRQ, +	}, +	[2] = { +		.name   = "1", +		.start  = INT_DMA_CH1_7, +		.flags  = IORESOURCE_IRQ, +	}, +	[3] = { +		.name   = "2", +		.start  = INT_DMA_CH2_8, +		.flags  = IORESOURCE_IRQ, +	}, +	[4] = { +		.name   = "3", +		.start  = INT_DMA_CH3, +		.flags  = IORESOURCE_IRQ, +	}, +	[5] = { +		.name   = "4", +		.start  = INT_DMA_CH4, +		.flags  = IORESOURCE_IRQ, +	}, +	[6] = { +		.name   = "5", +		.start  = INT_DMA_CH5, +		.flags  = IORESOURCE_IRQ, +	}, +	/* Handled in lcd_dma.c */ +	[7] = { +		.name   = "6", +		.start  = INT_1610_DMA_CH6, +		.flags  = IORESOURCE_IRQ, +	}, +	/* irq's for omap16xx and omap7xx */ +	[8] = { +		.name   = "7", +		.start  = INT_1610_DMA_CH7, +		.flags  = IORESOURCE_IRQ, +	}, +	[9] = { +		.name   = "8", +		.start  = INT_1610_DMA_CH8, +		.flags  = IORESOURCE_IRQ, +	}, +	[10] = { +		.name  = "9", +		.start = INT_1610_DMA_CH9, +		.flags = IORESOURCE_IRQ, +	}, +	[11] = { +		.name  = "10", +		.start = INT_1610_DMA_CH10, +		.flags = IORESOURCE_IRQ, +	}, +	[12] = { +		.name  = "11", +		.start = INT_1610_DMA_CH11, +		.flags = IORESOURCE_IRQ, +	}, +	[13] = { +		.name  = "12", +		.start = INT_1610_DMA_CH12, +		.flags = IORESOURCE_IRQ, +	}, +	[14] = { +		.name  = "13", +		.start = INT_1610_DMA_CH13, +		.flags = IORESOURCE_IRQ, +	}, +	[15] = { +		.name  = "14", +		.start = INT_1610_DMA_CH14, +		.flags = IORESOURCE_IRQ, +	}, +	[16] = { +		.name  = "15", +		.start = INT_1610_DMA_CH15, +		.flags = IORESOURCE_IRQ, +	}, +	[17] = { +		.name  = "16", +		.start = INT_DMA_LCD, +		.flags = IORESOURCE_IRQ, +	}, +}; + +static void __iomem *dma_base; +static inline void dma_write(u32 val, int reg, int lch) +{ +	u8  stride; +	u32 offset; + +	stride = (reg >= dma_common_ch_start) ? dma_stride : 0; +	offset = reg_map[reg] + (stride * lch); + +	__raw_writew(val, dma_base + offset); +	if ((reg > CLNK_CTRL && reg < CCEN) || +			(reg > PCHD_ID && reg < CAPS_2)) { +		u32 offset2 = reg_map[reg] + 2 + (stride * lch); +		__raw_writew(val >> 16, dma_base + offset2); +	} +} + +static inline u32 dma_read(int reg, int lch) +{ +	u8 stride; +	u32 offset, val; + +	stride = (reg >= dma_common_ch_start) ? dma_stride : 0; +	offset = reg_map[reg] + (stride * lch); + +	val = __raw_readw(dma_base + offset); +	if ((reg > CLNK_CTRL && reg < CCEN) || +			(reg > PCHD_ID && reg < CAPS_2)) { +		u16 upper; +		u32 offset2 = reg_map[reg] + 2 + (stride * lch); +		upper = __raw_readw(dma_base + offset2); +		val |= (upper << 16); +	} +	return val; +} + +static void omap1_clear_lch_regs(int lch) +{ +	int i = dma_common_ch_start; + +	for (; i <= dma_common_ch_end; i += 1) +		dma_write(0, i, lch); +} + +static void omap1_clear_dma(int lch) +{ +	u32 l; + +	l = dma_read(CCR, lch); +	l &= ~OMAP_DMA_CCR_EN; +	dma_write(l, CCR, lch); + +	/* Clear pending interrupts */ +	l = dma_read(CSR, lch); +} + +static void omap1_show_dma_caps(void) +{ +	if (enable_1510_mode) { +		printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); +	} else { +		u16 w; +		printk(KERN_INFO "OMAP DMA hardware version %d\n", +							dma_read(HW_ID, 0)); +		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", +			dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), +			dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), +			dma_read(CAPS_4, 0)); + +		/* Disable OMAP 3.0/3.1 compatibility mode. */ +		w = dma_read(GSCR, 0); +		w |= 1 << 3; +		dma_write(w, GSCR, 0); +	} +	return; +} + +static u32 configure_dma_errata(void) +{ + +	/* +	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is +	 * read before the DMA controller finished disabling the channel. +	 */ +	if (!cpu_is_omap15xx()) +		SET_DMA_ERRATA(DMA_ERRATA_3_3); + +	return errata; +} + +static int __init omap1_system_dma_init(void) +{ +	struct omap_system_dma_plat_info	*p; +	struct omap_dma_dev_attr		*d; +	struct platform_device			*pdev; +	int ret; + +	pdev = platform_device_alloc("omap_dma_system", 0); +	if (!pdev) { +		pr_err("%s: Unable to device alloc for dma\n", +			__func__); +		return -ENOMEM; +	} + +	dma_base = ioremap(res[0].start, resource_size(&res[0])); +	if (!dma_base) { +		pr_err("%s: Unable to ioremap\n", __func__); +		return -ENODEV; +	} + +	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); +	if (ret) { +		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", +			__func__, pdev->name, pdev->id); +		goto exit_device_del; +	} + +	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); +	if (!p) { +		dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", +			__func__, pdev->name); +		ret = -ENOMEM; +		goto exit_device_put; +	} + +	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); +	if (!d) { +		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", +			__func__, pdev->name); +		ret = -ENOMEM; +		goto exit_release_p; +	} + +	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT; + +	/* Valid attributes for omap1 plus processors */ +	if (cpu_is_omap15xx()) +		d->dev_caps = ENABLE_1510_MODE; +	enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; + +	d->dev_caps		|= SRC_PORT; +	d->dev_caps		|= DST_PORT; +	d->dev_caps		|= SRC_INDEX; +	d->dev_caps		|= DST_INDEX; +	d->dev_caps		|= IS_BURST_ONLY4; +	d->dev_caps		|= CLEAR_CSR_ON_READ; +	d->dev_caps		|= IS_WORD_16; + + +	d->chan = kzalloc(sizeof(struct omap_dma_lch) * +					(d->lch_count), GFP_KERNEL); +	if (!d->chan) { +		dev_err(&pdev->dev, "%s: Memory allocation failed" +					"for d->chan!!!\n", __func__); +		goto exit_release_d; +	} + +	if (cpu_is_omap15xx()) +		d->chan_count = 9; +	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { +		if (!(d->dev_caps & ENABLE_1510_MODE)) +			d->chan_count = 16; +		else +			d->chan_count = 9; +	} + +	p->dma_attr = d; + +	p->show_dma_caps	= omap1_show_dma_caps; +	p->clear_lch_regs	= omap1_clear_lch_regs; +	p->clear_dma		= omap1_clear_dma; +	p->dma_write		= dma_write; +	p->dma_read		= dma_read; +	p->disable_irq_lch	= NULL; + +	p->errata = configure_dma_errata(); + +	ret = platform_device_add_data(pdev, p, sizeof(*p)); +	if (ret) { +		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", +			__func__, pdev->name, pdev->id); +		goto exit_release_chan; +	} + +	ret = platform_device_add(pdev); +	if (ret) { +		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", +			__func__, pdev->name, pdev->id); +		goto exit_release_chan; +	} + +	dma_stride		= OMAP1_DMA_STRIDE; +	dma_common_ch_start	= CPC; +	dma_common_ch_end	= COLOR; + +	return ret; + +exit_release_chan: +	kfree(d->chan); +exit_release_d: +	kfree(d); +exit_release_p: +	kfree(p); +exit_device_put: +	platform_device_put(pdev); +exit_device_del: +	platform_device_del(pdev); + +	return ret; +} +arch_initcall(omap1_system_dma_init); diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b86b0629238..cdfb5faaec9 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@  # Common support  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \ -	 common.o gpio.o +	 common.o gpio.o dma.o  omap-2-3-common				= irq.o sdrc.o prm2xxx_3xxx.o  hwmod-common				= omap_hwmod.o \ diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c new file mode 100644 index 00000000000..d2f15f5cfd3 --- /dev/null +++ b/arch/arm/mach-omap2/dma.c @@ -0,0 +1,297 @@ +/* + * OMAP2+ DMA driver + * + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä <juha.yrjola@nokia.com> + * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak <imre.deak@nokia.com> + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into platform driver + *	- G, Manjunath Kondaiah <manjugk@ti.com> + * + * 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. + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> + +#include <plat/omap_hwmod.h> +#include <plat/omap_device.h> +#include <plat/dma.h> + +#define OMAP2_DMA_STRIDE	0x60 + +static u32 errata; +static u8 dma_stride; + +static struct omap_dma_dev_attr *d; + +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; + +static u16 reg_map[] = { +	[REVISION]		= 0x00, +	[GCR]			= 0x78, +	[IRQSTATUS_L0]		= 0x08, +	[IRQSTATUS_L1]		= 0x0c, +	[IRQSTATUS_L2]		= 0x10, +	[IRQSTATUS_L3]		= 0x14, +	[IRQENABLE_L0]		= 0x18, +	[IRQENABLE_L1]		= 0x1c, +	[IRQENABLE_L2]		= 0x20, +	[IRQENABLE_L3]		= 0x24, +	[SYSSTATUS]		= 0x28, +	[OCP_SYSCONFIG]		= 0x2c, +	[CAPS_0]		= 0x64, +	[CAPS_2]		= 0x6c, +	[CAPS_3]		= 0x70, +	[CAPS_4]		= 0x74, + +	/* Common register offsets */ +	[CCR]			= 0x80, +	[CLNK_CTRL]		= 0x84, +	[CICR]			= 0x88, +	[CSR]			= 0x8c, +	[CSDP]			= 0x90, +	[CEN]			= 0x94, +	[CFN]			= 0x98, +	[CSEI]			= 0xa4, +	[CSFI]			= 0xa8, +	[CDEI]			= 0xac, +	[CDFI]			= 0xb0, +	[CSAC]			= 0xb4, +	[CDAC]			= 0xb8, + +	/* Channel specific register offsets */ +	[CSSA]			= 0x9c, +	[CDSA]			= 0xa0, +	[CCEN]			= 0xbc, +	[CCFN]			= 0xc0, +	[COLOR]			= 0xc4, + +	/* OMAP4 specific registers */ +	[CDP]			= 0xd0, +	[CNDP]			= 0xd4, +	[CCDN]			= 0xd8, +}; + +static struct omap_device_pm_latency omap2_dma_latency[] = { +	{ +		.deactivate_func = omap_device_idle_hwmods, +		.activate_func	 = omap_device_enable_hwmods, +		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST, +	}, +}; + +static void __iomem *dma_base; +static inline void dma_write(u32 val, int reg, int lch) +{ +	u8  stride; +	u32 offset; + +	stride = (reg >= dma_common_ch_start) ? dma_stride : 0; +	offset = reg_map[reg] + (stride * lch); +	__raw_writel(val, dma_base + offset); +} + +static inline u32 dma_read(int reg, int lch) +{ +	u8 stride; +	u32 offset, val; + +	stride = (reg >= dma_common_ch_start) ? dma_stride : 0; +	offset = reg_map[reg] + (stride * lch); +	val = __raw_readl(dma_base + offset); +	return val; +} + +static inline void omap2_disable_irq_lch(int lch) +{ +	u32 val; + +	val = dma_read(IRQENABLE_L0, lch); +	val &= ~(1 << lch); +	dma_write(val, IRQENABLE_L0, lch); +} + +static void omap2_clear_dma(int lch) +{ +	int i = dma_common_ch_start; + +	for (; i <= dma_common_ch_end; i += 1) +		dma_write(0, i, lch); +} + +static void omap2_show_dma_caps(void) +{ +	u8 revision = dma_read(REVISION, 0) & 0xff; +	printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", +				revision >> 4, revision & 0xf); +	return; +} + +static u32 configure_dma_errata(void) +{ + +	/* +	 * Errata applicable for OMAP2430ES1.0 and all omap2420 +	 * +	 * I. +	 * Erratum ID: Not Available +	 * Inter Frame DMA buffering issue DMA will wrongly +	 * buffer elements if packing and bursting is enabled. This might +	 * result in data gets stalled in FIFO at the end of the block. +	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to +	 * guarantee no data will stay in the DMA FIFO in case inter frame +	 * buffering occurs +	 * +	 * II. +	 * Erratum ID: Not Available +	 * DMA may hang when several channels are used in parallel +	 * In the following configuration, DMA channel hanging can occur: +	 * a. Channel i, hardware synchronized, is enabled +	 * b. Another channel (Channel x), software synchronized, is enabled. +	 * c. Channel i is disabled before end of transfer +	 * d. Channel i is reenabled. +	 * e. Steps 1 to 4 are repeated a certain number of times. +	 * f. A third channel (Channel y), software synchronized, is enabled. +	 * Channel x and Channel y may hang immediately after step 'f'. +	 * Workaround: +	 * For any channel used - make sure NextLCH_ID is set to the value j. +	 */ +	if (cpu_is_omap2420() || (cpu_is_omap2430() && +				(omap_type() == OMAP2430_REV_ES1_0))) { + +		SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); +		SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); +	} + +	/* +	 * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled +	 * after a transaction error. +	 * Workaround: SW should explicitely disable the channel. +	 */ +	if (cpu_class_is_omap2()) +		SET_DMA_ERRATA(DMA_ERRATA_i378); + +	/* +	 * Erratum ID: i541: sDMA FIFO draining does not finish +	 * If sDMA channel is disabled on the fly, sDMA enters standby even +	 * through FIFO Drain is still in progress +	 * Workaround: Put sDMA in NoStandby more before a logical channel is +	 * disabled, then put it back to SmartStandby right after the channel +	 * finishes FIFO draining. +	 */ +	if (cpu_is_omap34xx()) +		SET_DMA_ERRATA(DMA_ERRATA_i541); + +	/* +	 * Erratum ID: i88 : Special programming model needed to disable DMA +	 * before end of block. +	 * Workaround: software must ensure that the DMA is configured in No +	 * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") +	 */ +	if (omap_type() == OMAP3430_REV_ES1_0) +		SET_DMA_ERRATA(DMA_ERRATA_i88); + +	/* +	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is +	 * read before the DMA controller finished disabling the channel. +	 */ +	SET_DMA_ERRATA(DMA_ERRATA_3_3); + +	/* +	 * Erratum ID: Not Available +	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared +	 * after secure sram context save and restore. +	 * Work around: Hence we need to manually clear those IRQs to avoid +	 * spurious interrupts. This affects only secure devices. +	 */ +	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) +		SET_DMA_ERRATA(DMA_ROMCODE_BUG); + +	return errata; +} + +/* One time initializations */ +static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) +{ +	struct omap_device			*od; +	struct omap_system_dma_plat_info	*p; +	struct resource				*mem; +	char					*name = "omap_dma_system"; + +	dma_stride		= OMAP2_DMA_STRIDE; +	dma_common_ch_start	= CSDP; +	if (cpu_is_omap3630() || cpu_is_omap4430()) +		dma_common_ch_end = CCDN; +	else +		dma_common_ch_end = CCFN; + +	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); +	if (!p) { +		pr_err("%s: Unable to allocate pdata for %s:%s\n", +			__func__, name, oh->name); +		return -ENOMEM; +	} + +	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr; +	p->disable_irq_lch	= omap2_disable_irq_lch; +	p->show_dma_caps	= omap2_show_dma_caps; +	p->clear_dma		= omap2_clear_dma; +	p->dma_write		= dma_write; +	p->dma_read		= dma_read; + +	p->clear_lch_regs	= NULL; + +	p->errata		= configure_dma_errata(); + +	od = omap_device_build(name, 0, oh, p, sizeof(*p), +			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0); +	kfree(p); +	if (IS_ERR(od)) { +		pr_err("%s: Cant build omap_device for %s:%s.\n", +			__func__, name, oh->name); +		return IS_ERR(od); +	} + +	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0); +	if (!mem) { +		dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__); +		return -EINVAL; +	} +	dma_base = ioremap(mem->start, resource_size(mem)); +	if (!dma_base) { +		dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__); +		return -ENOMEM; +	} + +	d = oh->dev_attr; +	d->chan = kzalloc(sizeof(struct omap_dma_lch) * +					(d->lch_count), GFP_KERNEL); + +	if (!d->chan) { +		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__); +		return -ENOMEM; +	} +	return 0; +} + +static int __init omap2_system_dma_init(void) +{ +	return omap_hwmod_for_each_by_class("dma", +			omap2_system_dma_init_dev, NULL); +} +arch_initcall(omap2_system_dma_init); diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index d9534259979..42606f6b0cd 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -42,6 +42,7 @@ static struct omap_hwmod omap2420_gpio1_hwmod;  static struct omap_hwmod omap2420_gpio2_hwmod;  static struct omap_hwmod omap2420_gpio3_hwmod;  static struct omap_hwmod omap2420_gpio4_hwmod; +static struct omap_hwmod omap2420_dma_system_hwmod;  /* L3 -> L4_CORE interface */  static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = { @@ -779,6 +780,88 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),  }; +/* system dma */ +static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x002c, +	.syss_offs	= 0x0028, +	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | +			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | +			   SYSC_HAS_AUTOIDLE), +	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_dma_hwmod_class = { +	.name = "dma", +	.sysc = &omap2420_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { +	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | +						IS_CSSA_32 | IS_CDSA_32, +	.lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = { +	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ +	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ +	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ +	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = { +	{ +		.pa_start	= 0x48056000, +		.pa_end		= 0x4a0560ff, +		.flags		= ADDR_TYPE_RT +	}, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = { +	.master		= &omap2420_dma_system_hwmod, +	.slave		= &omap2420_l3_main_hwmod, +	.clk		= "core_l3_ck", +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = { +	&omap2420_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = { +	.master		= &omap2420_l4_core_hwmod, +	.slave		= &omap2420_dma_system_hwmod, +	.clk		= "sdma_ick", +	.addr		= omap2420_dma_system_addrs, +	.addr_cnt	= ARRAY_SIZE(omap2420_dma_system_addrs), +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = { +	&omap2420_l4_core__dma_system, +}; + +static struct omap_hwmod omap2420_dma_system_hwmod = { +	.name		= "dma", +	.class		= &omap2420_dma_hwmod_class, +	.mpu_irqs	= omap2420_dma_system_irqs, +	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dma_system_irqs), +	.main_clk	= "core_l3_ck", +	.slaves		= omap2420_dma_system_slaves, +	.slaves_cnt	= ARRAY_SIZE(omap2420_dma_system_slaves), +	.masters	= omap2420_dma_system_masters, +	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters), +	.dev_attr	= &dma_dev_attr, +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420), +	.flags		= HWMOD_NO_IDLEST, +}; +  static __initdata struct omap_hwmod *omap2420_hwmods[] = {  	&omap2420_l3_main_hwmod,  	&omap2420_l4_core_hwmod, @@ -797,6 +880,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {  	&omap2420_gpio2_hwmod,  	&omap2420_gpio3_hwmod,  	&omap2420_gpio4_hwmod, + +	/* dma_system class*/ +	&omap2420_dma_system_hwmod,  	NULL,  }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index ab1d662cb07..3315d241fee 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -43,6 +43,7 @@ static struct omap_hwmod omap2430_gpio2_hwmod;  static struct omap_hwmod omap2430_gpio3_hwmod;  static struct omap_hwmod omap2430_gpio4_hwmod;  static struct omap_hwmod omap2430_gpio5_hwmod; +static struct omap_hwmod omap2430_dma_system_hwmod;  /* L3 -> L4_CORE interface */  static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = { @@ -838,6 +839,88 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),  }; +/* dma_system */ +static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x002c, +	.syss_offs	= 0x0028, +	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | +			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | +			   SYSC_HAS_AUTOIDLE), +	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_dma_hwmod_class = { +	.name = "dma", +	.sysc = &omap2430_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { +	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, +	.lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = { +	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ +	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ +	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ +	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = { +	{ +		.pa_start	= 0x48056000, +		.pa_end		= 0x4a0560ff, +		.flags		= ADDR_TYPE_RT +	}, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = { +	.master		= &omap2430_dma_system_hwmod, +	.slave		= &omap2430_l3_main_hwmod, +	.clk		= "core_l3_ck", +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = { +	&omap2430_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = { +	.master		= &omap2430_l4_core_hwmod, +	.slave		= &omap2430_dma_system_hwmod, +	.clk		= "sdma_ick", +	.addr		= omap2430_dma_system_addrs, +	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs), +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = { +	&omap2430_l4_core__dma_system, +}; + +static struct omap_hwmod omap2430_dma_system_hwmod = { +	.name		= "dma", +	.class		= &omap2430_dma_hwmod_class, +	.mpu_irqs	= omap2430_dma_system_irqs, +	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs), +	.main_clk	= "core_l3_ck", +	.slaves		= omap2430_dma_system_slaves, +	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves), +	.masters	= omap2430_dma_system_masters, +	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters), +	.dev_attr	= &dma_dev_attr, +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430), +	.flags		= HWMOD_NO_IDLEST, +}; +  static __initdata struct omap_hwmod *omap2430_hwmods[] = {  	&omap2430_l3_main_hwmod,  	&omap2430_l4_core_hwmod, @@ -857,6 +940,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {  	&omap2430_gpio3_hwmod,  	&omap2430_gpio4_hwmod,  	&omap2430_gpio5_hwmod, + +	/* dma_system class*/ +	&omap2430_dma_system_hwmod,  	NULL,  }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 2687be10d7a..d5acb63ba9e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -52,6 +52,8 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod;  static struct omap_hwmod omap3xxx_gpio5_hwmod;  static struct omap_hwmod omap3xxx_gpio6_hwmod; +static struct omap_hwmod omap3xxx_dma_system_hwmod; +  /* L3 -> L4_CORE interface */  static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {  	.master	= &omap3xxx_l3_main_hwmod, @@ -1090,6 +1092,98 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),  }; +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = { +	.master		= &omap3xxx_dma_system_hwmod, +	.slave		= &omap3xxx_l3_main_hwmod, +	.clk		= "core_l3_ick", +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { +	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, +	.lch_count = 32, +}; + +static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x002c, +	.syss_offs	= 0x0028, +	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | +			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | +			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE), +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | +			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_dma_hwmod_class = { +	.name = "dma", +	.sysc = &omap3xxx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = { +	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ +	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ +	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ +	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = { +	{ +		.pa_start	= 0x48056000, +		.pa_end		= 0x4a0560ff, +		.flags		= ADDR_TYPE_RT +	}, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = { +	&omap3xxx_dma_system__l3, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = { +	.master		= &omap3xxx_l4_core_hwmod, +	.slave		= &omap3xxx_dma_system_hwmod, +	.clk		= "core_l4_ick", +	.addr		= omap3xxx_dma_system_addrs, +	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs), +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = { +	&omap3xxx_l4_core__dma_system, +}; + +static struct omap_hwmod omap3xxx_dma_system_hwmod = { +	.name		= "dma", +	.class		= &omap3xxx_dma_hwmod_class, +	.mpu_irqs	= omap3xxx_dma_system_irqs, +	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs), +	.main_clk	= "core_l3_ick", +	.prcm = { +		.omap2 = { +			.module_offs		= CORE_MOD, +			.prcm_reg_id		= 1, +			.module_bit		= OMAP3430_ST_SDMA_SHIFT, +			.idlest_reg_id		= 1, +			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT, +		}, +	}, +	.slaves		= omap3xxx_dma_system_slaves, +	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves), +	.masters	= omap3xxx_dma_system_masters, +	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters), +	.dev_attr	= &dma_dev_attr, +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +	.flags		= HWMOD_NO_IDLEST, +}; +  static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {  	&omap3xxx_l3_main_hwmod,  	&omap3xxx_l4_core_hwmod, @@ -1113,6 +1207,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {  	&omap3xxx_gpio4_hwmod,  	&omap3xxx_gpio5_hwmod,  	&omap3xxx_gpio6_hwmod, + +	/* dma_system class*/ +	&omap3xxx_dma_system_hwmod,  	NULL,  }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index d258936410f..f9778fba832 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -23,6 +23,7 @@  #include <plat/omap_hwmod.h>  #include <plat/cpu.h>  #include <plat/gpio.h> +#include <plat/dma.h>  #include "omap_hwmod_common_data.h" @@ -36,6 +37,7 @@  #define OMAP44XX_DMA_REQ_START  1  /* Backward references (IPs with Bus Master capability) */ +static struct omap_hwmod omap44xx_dma_system_hwmod;  static struct omap_hwmod omap44xx_dmm_hwmod;  static struct omap_hwmod omap44xx_emif_fw_hwmod;  static struct omap_hwmod omap44xx_l3_instr_hwmod; @@ -216,6 +218,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {  	.user		= OCP_USER_MPU | OCP_USER_SDMA,  }; +/* dma_system -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = { +	.master		= &omap44xx_dma_system_hwmod, +	.slave		= &omap44xx_l3_main_2_hwmod, +	.clk		= "l3_div_ck", +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; +  /* l4_cfg -> l3_main_2 */  static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {  	.master		= &omap44xx_l4_cfg_hwmod, @@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {  /* l3_main_2 slave ports */  static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = { +	&omap44xx_dma_system__l3_main_2,  	&omap44xx_l3_main_1__l3_main_2,  	&omap44xx_l4_cfg__l3_main_2,  }; @@ -1376,6 +1387,93 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {  	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),  }; + +/* + * 'dma' class + * dma controller for data exchange between memory to memory (i.e. internal or + * external memory) and gp peripherals to memory or memory to gp peripherals + */ + +static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x002c, +	.syss_offs	= 0x0028, +	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | +			   SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE | +			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | +			   SYSS_HAS_RESET_STATUS), +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | +			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { +	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, +	.lch_count = 32, +}; + +static struct omap_hwmod_class omap44xx_dma_hwmod_class = { +	.name	= "dma", +	.sysc	= &omap44xx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = { +	{ .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START }, +	{ .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START }, +	{ .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START }, +	{ .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START }, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = { +	&omap44xx_dma_system__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = { +	{ +		.pa_start	= 0x4a056000, +		.pa_end		= 0x4a0560ff, +		.flags		= ADDR_TYPE_RT +	}, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = { +	.master		= &omap44xx_l4_cfg_hwmod, +	.slave		= &omap44xx_dma_system_hwmod, +	.clk		= "l4_div_ck", +	.addr		= omap44xx_dma_system_addrs, +	.addr_cnt	= ARRAY_SIZE(omap44xx_dma_system_addrs), +	.user		= OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = { +	&omap44xx_l4_cfg__dma_system, +}; + +static struct omap_hwmod omap44xx_dma_system_hwmod = { +	.name		= "dma_system", +	.class		= &omap44xx_dma_hwmod_class, +	.mpu_irqs	= omap44xx_dma_system_irqs, +	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dma_system_irqs), +	.main_clk	= "l3_div_ck", +	.prcm = { +		.omap4 = { +			.clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL, +		}, +	}, +	.slaves		= omap44xx_dma_system_slaves, +	.slaves_cnt	= ARRAY_SIZE(omap44xx_dma_system_slaves), +	.masters	= omap44xx_dma_system_masters, +	.masters_cnt	= ARRAY_SIZE(omap44xx_dma_system_masters), +	.dev_attr	= &dma_dev_attr, +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; +  static __initdata struct omap_hwmod *omap44xx_hwmods[] = {  	/* dmm class */  	&omap44xx_dmm_hwmod, @@ -1391,6 +1489,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {  	&omap44xx_l4_cfg_hwmod,  	&omap44xx_l4_per_hwmod,  	&omap44xx_l4_wkup_hwmod, + +	/* dma class */ +	&omap44xx_dma_system_hwmod, +  	/* i2c class */  	&omap44xx_i2c1_hwmod,  	&omap44xx_i2c2_hwmod, diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index a863f5546a6..c4b2b478b1a 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -15,6 +15,10 @@   *   * Support functions for the OMAP internal DMA channels.   * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into DMA platform driver. + *	- G, Manjunath Kondaiah <manjugk@ti.com> + *   * 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. @@ -53,7 +57,11 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };  #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec) +static struct omap_system_dma_plat_info *p; +static struct omap_dma_dev_attr *d; +  static int enable_1510_mode; +static u32 errata;  static struct omap_dma_global_context_registers {  	u32 dma_irqenable_l0; @@ -61,27 +69,6 @@ static struct omap_dma_global_context_registers {  	u32 dma_gcr;  } omap_dma_global_context; -struct omap_dma_lch { -	int next_lch; -	int dev_id; -	u16 saved_csr; -	u16 enabled_irqs; -	const char *dev_name; -	void (*callback)(int lch, u16 ch_status, void *data); -	void *data; - -#ifndef CONFIG_ARCH_OMAP1 -	/* required for Dynamic chaining */ -	int prev_linked_ch; -	int next_linked_ch; -	int state; -	int chain_id; - -	int status; -#endif -	long flags; -}; -  struct dma_link_info {  	int *linked_dmach_q;  	int no_of_lchs_linked; @@ -137,15 +124,6 @@ static int omap_dma_reserve_channels;  static spinlock_t dma_chan_lock;  static struct omap_dma_lch *dma_chan; -static void __iomem *omap_dma_base; - -static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = { -	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, -	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, -	INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, -	INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, -	INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD -};  static inline void disable_lnk(int lch);  static void omap_disable_channel_irq(int lch); @@ -154,27 +132,9 @@ static inline void omap_enable_channel_irq(int lch);  #define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx\n", \  						__func__); -#define dma_read(reg)							\ -({									\ -	u32 __val;							\ -	if (cpu_class_is_omap1())					\ -		__val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);	\ -	else								\ -		__val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);	\ -	__val;								\ -}) - -#define dma_write(val, reg)						\ -({									\ -	if (cpu_class_is_omap1())					\ -		__raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \ -	else								\ -		__raw_writel((val), omap_dma_base + OMAP_DMA4_##reg);	\ -}) -  #ifdef CONFIG_ARCH_OMAP15XX  /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ -static int omap_dma_in_1510_mode(void) +int omap_dma_in_1510_mode(void)  {  	return enable_1510_mode;  } @@ -206,16 +166,6 @@ static inline void set_gdma_dev(int req, int dev)  #define set_gdma_dev(req, dev)	do {} while (0)  #endif -/* Omap1 only */ -static void clear_lch_regs(int lch) -{ -	int i; -	void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch); - -	for (i = 0; i < 0x2c; i += 2) -		__raw_writew(0, lch_base + i); -} -  void omap_set_dma_priority(int lch, int dst_port, int priority)  {  	unsigned long reg; @@ -248,12 +198,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)  	if (cpu_class_is_omap2()) {  		u32 ccr; -		ccr = dma_read(CCR(lch)); +		ccr = p->dma_read(CCR, lch);  		if (priority)  			ccr |= (1 << 6);  		else  			ccr &= ~(1 << 6); -		dma_write(ccr, CCR(lch)); +		p->dma_write(ccr, CCR, lch);  	}  }  EXPORT_SYMBOL(omap_set_dma_priority); @@ -264,31 +214,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,  {  	u32 l; -	l = dma_read(CSDP(lch)); +	l = p->dma_read(CSDP, lch);  	l &= ~0x03;  	l |= data_type; -	dma_write(l, CSDP(lch)); +	p->dma_write(l, CSDP, lch);  	if (cpu_class_is_omap1()) {  		u16 ccr; -		ccr = dma_read(CCR(lch)); +		ccr = p->dma_read(CCR, lch);  		ccr &= ~(1 << 5);  		if (sync_mode == OMAP_DMA_SYNC_FRAME)  			ccr |= 1 << 5; -		dma_write(ccr, CCR(lch)); +		p->dma_write(ccr, CCR, lch); -		ccr = dma_read(CCR2(lch)); +		ccr = p->dma_read(CCR2, lch);  		ccr &= ~(1 << 2);  		if (sync_mode == OMAP_DMA_SYNC_BLOCK)  			ccr |= 1 << 2; -		dma_write(ccr, CCR2(lch)); +		p->dma_write(ccr, CCR2, lch);  	}  	if (cpu_class_is_omap2() && dma_trigger) {  		u32 val; -		val = dma_read(CCR(lch)); +		val = p->dma_read(CCR, lch);  		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */  		val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -313,11 +263,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,  		} else {  			val &= ~(1 << 24);	/* dest synch */  		} -		dma_write(val, CCR(lch)); +		p->dma_write(val, CCR, lch);  	} -	dma_write(elem_count, CEN(lch)); -	dma_write(frame_count, CFN(lch)); +	p->dma_write(elem_count, CEN, lch); +	p->dma_write(frame_count, CFN, lch);  }  EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -328,7 +278,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)  	if (cpu_class_is_omap1()) {  		u16 w; -		w = dma_read(CCR2(lch)); +		w = p->dma_read(CCR2, lch);  		w &= ~0x03;  		switch (mode) { @@ -343,23 +293,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)  		default:  			BUG();  		} -		dma_write(w, CCR2(lch)); +		p->dma_write(w, CCR2, lch); -		w = dma_read(LCH_CTRL(lch)); +		w = p->dma_read(LCH_CTRL, lch);  		w &= ~0x0f;  		/* Default is channel type 2D */  		if (mode) { -			dma_write((u16)color, COLOR_L(lch)); -			dma_write((u16)(color >> 16), COLOR_U(lch)); +			p->dma_write(color, COLOR, lch);  			w |= 1;		/* Channel type G */  		} -		dma_write(w, LCH_CTRL(lch)); +		p->dma_write(w, LCH_CTRL, lch);  	}  	if (cpu_class_is_omap2()) {  		u32 val; -		val = dma_read(CCR(lch)); +		val = p->dma_read(CCR, lch);  		val &= ~((1 << 17) | (1 << 16));  		switch (mode) { @@ -374,10 +323,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)  		default:  			BUG();  		} -		dma_write(val, CCR(lch)); +		p->dma_write(val, CCR, lch);  		color &= 0xffffff; -		dma_write(color, COLOR(lch)); +		p->dma_write(color, COLOR, lch);  	}  }  EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -387,10 +336,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)  	if (cpu_class_is_omap2()) {  		u32 csdp; -		csdp = dma_read(CSDP(lch)); +		csdp = p->dma_read(CSDP, lch);  		csdp &= ~(0x3 << 16);  		csdp |= (mode << 16); -		dma_write(csdp, CSDP(lch)); +		p->dma_write(csdp, CSDP, lch);  	}  }  EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -400,10 +349,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)  	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {  		u32 l; -		l = dma_read(LCH_CTRL(lch)); +		l = p->dma_read(LCH_CTRL, lch);  		l &= ~0x7;  		l |= mode; -		dma_write(l, LCH_CTRL(lch)); +		p->dma_write(l, LCH_CTRL, lch);  	}  }  EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -418,27 +367,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,  	if (cpu_class_is_omap1()) {  		u16 w; -		w = dma_read(CSDP(lch)); +		w = p->dma_read(CSDP, lch);  		w &= ~(0x1f << 2);  		w |= src_port << 2; -		dma_write(w, CSDP(lch)); +		p->dma_write(w, CSDP, lch);  	} -	l = dma_read(CCR(lch)); +	l = p->dma_read(CCR, lch);  	l &= ~(0x03 << 12);  	l |= src_amode << 12; -	dma_write(l, CCR(lch)); - -	if (cpu_class_is_omap1()) { -		dma_write(src_start >> 16, CSSA_U(lch)); -		dma_write((u16)src_start, CSSA_L(lch)); -	} +	p->dma_write(l, CCR, lch); -	if (cpu_class_is_omap2()) -		dma_write(src_start, CSSA(lch)); +	p->dma_write(src_start, CSSA, lch); -	dma_write(src_ei, CSEI(lch)); -	dma_write(src_fi, CSFI(lch)); +	p->dma_write(src_ei, CSEI, lch); +	p->dma_write(src_fi, CSFI, lch);  }  EXPORT_SYMBOL(omap_set_dma_src_params); @@ -466,8 +409,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx)  	if (cpu_class_is_omap2())  		return; -	dma_write(eidx, CSEI(lch)); -	dma_write(fidx, CSFI(lch)); +	p->dma_write(eidx, CSEI, lch); +	p->dma_write(fidx, CSFI, lch);  }  EXPORT_SYMBOL(omap_set_dma_src_index); @@ -475,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch, int enable)  {  	u32 l; -	l = dma_read(CSDP(lch)); +	l = p->dma_read(CSDP, lch);  	l &= ~(1 << 6);  	if (enable)  		l |= (1 << 6); -	dma_write(l, CSDP(lch)); +	p->dma_write(l, CSDP, lch);  }  EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -488,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)  	unsigned int burst = 0;  	u32 l; -	l = dma_read(CSDP(lch)); +	l = p->dma_read(CSDP, lch);  	l &= ~(0x03 << 7);  	switch (burst_mode) { @@ -524,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)  	}  	l |= (burst << 7); -	dma_write(l, CSDP(lch)); +	p->dma_write(l, CSDP, lch);  }  EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -536,27 +479,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,  	u32 l;  	if (cpu_class_is_omap1()) { -		l = dma_read(CSDP(lch)); +		l = p->dma_read(CSDP, lch);  		l &= ~(0x1f << 9);  		l |= dest_port << 9; -		dma_write(l, CSDP(lch)); +		p->dma_write(l, CSDP, lch);  	} -	l = dma_read(CCR(lch)); +	l = p->dma_read(CCR, lch);  	l &= ~(0x03 << 14);  	l |= dest_amode << 14; -	dma_write(l, CCR(lch)); - -	if (cpu_class_is_omap1()) { -		dma_write(dest_start >> 16, CDSA_U(lch)); -		dma_write(dest_start, CDSA_L(lch)); -	} +	p->dma_write(l, CCR, lch); -	if (cpu_class_is_omap2()) -		dma_write(dest_start, CDSA(lch)); +	p->dma_write(dest_start, CDSA, lch); -	dma_write(dst_ei, CDEI(lch)); -	dma_write(dst_fi, CDFI(lch)); +	p->dma_write(dst_ei, CDEI, lch); +	p->dma_write(dst_fi, CDFI, lch);  }  EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -565,8 +502,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx)  	if (cpu_class_is_omap2())  		return; -	dma_write(eidx, CDEI(lch)); -	dma_write(fidx, CDFI(lch)); +	p->dma_write(eidx, CDEI, lch); +	p->dma_write(fidx, CDFI, lch);  }  EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -574,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable)  {  	u32 l; -	l = dma_read(CSDP(lch)); +	l = p->dma_read(CSDP, lch);  	l &= ~(1 << 13);  	if (enable)  		l |= 1 << 13; -	dma_write(l, CSDP(lch)); +	p->dma_write(l, CSDP, lch);  }  EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -587,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)  	unsigned int burst = 0;  	u32 l; -	l = dma_read(CSDP(lch)); +	l = p->dma_read(CSDP, lch);  	l &= ~(0x03 << 14);  	switch (burst_mode) { @@ -620,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)  		return;  	}  	l |= (burst << 14); -	dma_write(l, CSDP(lch)); +	p->dma_write(l, CSDP, lch);  }  EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -630,18 +567,18 @@ static inline void omap_enable_channel_irq(int lch)  	/* Clear CSR */  	if (cpu_class_is_omap1()) -		status = dma_read(CSR(lch)); +		status = p->dma_read(CSR, lch);  	else if (cpu_class_is_omap2()) -		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); +		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);  	/* Enable some nice interrupts. */ -	dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); +	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);  }  static void omap_disable_channel_irq(int lch)  {  	if (cpu_class_is_omap2()) -		dma_write(0, CICR(lch)); +		p->dma_write(0, CICR, lch);  }  void omap_enable_dma_irq(int lch, u16 bits) @@ -660,7 +597,7 @@ static inline void enable_lnk(int lch)  {  	u32 l; -	l = dma_read(CLNK_CTRL(lch)); +	l = p->dma_read(CLNK_CTRL, lch);  	if (cpu_class_is_omap1())  		l &= ~(1 << 14); @@ -675,18 +612,18 @@ static inline void enable_lnk(int lch)  			l = dma_chan[lch].next_linked_ch | (1 << 15);  #endif -	dma_write(l, CLNK_CTRL(lch)); +	p->dma_write(l, CLNK_CTRL, lch);  }  static inline void disable_lnk(int lch)  {  	u32 l; -	l = dma_read(CLNK_CTRL(lch)); +	l = p->dma_read(CLNK_CTRL, lch);  	/* Disable interrupts */  	if (cpu_class_is_omap1()) { -		dma_write(0, CICR(lch)); +		p->dma_write(0, CICR, lch);  		/* Set the STOP_LNK bit */  		l |= 1 << 14;  	} @@ -697,7 +634,7 @@ static inline void disable_lnk(int lch)  		l &= ~(1 << 15);  	} -	dma_write(l, CLNK_CTRL(lch)); +	p->dma_write(l, CLNK_CTRL, lch);  	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;  } @@ -710,9 +647,9 @@ static inline void omap2_enable_irq_lch(int lch)  		return;  	spin_lock_irqsave(&dma_chan_lock, flags); -	val = dma_read(IRQENABLE_L0); +	val = p->dma_read(IRQENABLE_L0, lch);  	val |= 1 << lch; -	dma_write(val, IRQENABLE_L0); +	p->dma_write(val, IRQENABLE_L0, lch);  	spin_unlock_irqrestore(&dma_chan_lock, flags);  } @@ -725,9 +662,9 @@ static inline void omap2_disable_irq_lch(int lch)  		return;  	spin_lock_irqsave(&dma_chan_lock, flags); -	val = dma_read(IRQENABLE_L0); +	val = p->dma_read(IRQENABLE_L0, lch);  	val &= ~(1 << lch); -	dma_write(val, IRQENABLE_L0); +	p->dma_write(val, IRQENABLE_L0, lch);  	spin_unlock_irqrestore(&dma_chan_lock, flags);  } @@ -754,8 +691,8 @@ int omap_request_dma(int dev_id, const char *dev_name,  	chan = dma_chan + free_ch;  	chan->dev_id = dev_id; -	if (cpu_class_is_omap1()) -		clear_lch_regs(free_ch); +	if (p->clear_lch_regs) +		p->clear_lch_regs(free_ch);  	if (cpu_class_is_omap2())  		omap_clear_dma(free_ch); @@ -792,17 +729,17 @@ int omap_request_dma(int dev_id, const char *dev_name,  		 * Disable the 1510 compatibility mode and set the sync device  		 * id.  		 */ -		dma_write(dev_id | (1 << 10), CCR(free_ch)); +		p->dma_write(dev_id | (1 << 10), CCR, free_ch);  	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { -		dma_write(dev_id, CCR(free_ch)); +		p->dma_write(dev_id, CCR, free_ch);  	}  	if (cpu_class_is_omap2()) {  		omap2_enable_irq_lch(free_ch);  		omap_enable_channel_irq(free_ch);  		/* Clear the CSR register and IRQ status register */ -		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch)); -		dma_write(1 << free_ch, IRQSTATUS_L0); +		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); +		p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);  	}  	*dma_ch_out = free_ch; @@ -823,23 +760,23 @@ void omap_free_dma(int lch)  	if (cpu_class_is_omap1()) {  		/* Disable all DMA interrupts for the channel. */ -		dma_write(0, CICR(lch)); +		p->dma_write(0, CICR, lch);  		/* Make sure the DMA transfer is stopped. */ -		dma_write(0, CCR(lch)); +		p->dma_write(0, CCR, lch);  	}  	if (cpu_class_is_omap2()) {  		omap2_disable_irq_lch(lch);  		/* Clear the CSR register and IRQ status register */ -		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); -		dma_write(1 << lch, IRQSTATUS_L0); +		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); +		p->dma_write(1 << lch, IRQSTATUS_L0, lch);  		/* Disable all DMA interrupts for the channel. */ -		dma_write(0, CICR(lch)); +		p->dma_write(0, CICR, lch);  		/* Make sure the DMA transfer is stopped. */ -		dma_write(0, CCR(lch)); +		p->dma_write(0, CCR, lch);  		omap_clear_dma(lch);  	} @@ -880,7 +817,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)  	reg |= (0x3 & tparams) << 12;  	reg |= (arb_rate & 0xff) << 16; -	dma_write(reg, GCR); +	p->dma_write(reg, GCR, 0);  }  EXPORT_SYMBOL(omap_dma_set_global_params); @@ -903,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,  		printk(KERN_ERR "Invalid channel id\n");  		return -EINVAL;  	} -	l = dma_read(CCR(lch)); +	l = p->dma_read(CCR, lch);  	l &= ~((1 << 6) | (1 << 26));  	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())  		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);  	else  		l |= ((read_prio & 0x1) << 6); -	dma_write(l, CCR(lch)); +	p->dma_write(l, CCR, lch);  	return 0;  } @@ -925,25 +862,7 @@ void omap_clear_dma(int lch)  	unsigned long flags;  	local_irq_save(flags); - -	if (cpu_class_is_omap1()) { -		u32 l; - -		l = dma_read(CCR(lch)); -		l &= ~OMAP_DMA_CCR_EN; -		dma_write(l, CCR(lch)); - -		/* Clear pending interrupts */ -		l = dma_read(CSR(lch)); -	} - -	if (cpu_class_is_omap2()) { -		int i; -		void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch); -		for (i = 0; i < 0x44; i += 4) -			__raw_writel(0, lch_base + i); -	} - +	p->clear_dma(lch);  	local_irq_restore(flags);  }  EXPORT_SYMBOL(omap_clear_dma); @@ -957,13 +876,13 @@ void omap_start_dma(int lch)  	 * before starting dma transfer.  	 */  	if (cpu_is_omap15xx()) -		dma_write(0, CPC(lch)); +		p->dma_write(0, CPC, lch);  	else -		dma_write(0, CDAC(lch)); +		p->dma_write(0, CDAC, lch);  	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {  		int next_lch, cur_lch; -		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; +		char dma_chan_link_map[dma_lch_count];  		dma_chan_link_map[lch] = 1;  		/* Set the link register of the first channel */ @@ -985,32 +904,18 @@ void omap_start_dma(int lch)  			cur_lch = next_lch;  		} while (next_lch != -1); -	} else if (cpu_is_omap242x() || -		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) { - -		/* Errata: Need to write lch even if not using chaining */ -		dma_write(lch, CLNK_CTRL(lch)); -	} +	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) +		p->dma_write(lch, CLNK_CTRL, lch);  	omap_enable_channel_irq(lch); -	l = dma_read(CCR(lch)); - -	/* -	 * Errata: Inter Frame DMA buffering issue (All OMAP2420 and -	 * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and -	 * bursting is enabled. This might result in data gets stalled in -	 * FIFO at the end of the block. -	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to -	 * guarantee no data will stay in the DMA FIFO in case inter frame -	 * buffering occurs. -	 */ -	if (cpu_is_omap2420() || -	    (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) -		l |= OMAP_DMA_CCR_BUFFERING_DISABLE; +	l = p->dma_read(CCR, lch); +	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) +			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;  	l |= OMAP_DMA_CCR_EN; -	dma_write(l, CCR(lch)); + +	p->dma_write(l, CCR, lch);  	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;  } @@ -1022,46 +927,46 @@ void omap_stop_dma(int lch)  	/* Disable all interrupts on the channel */  	if (cpu_class_is_omap1()) -		dma_write(0, CICR(lch)); +		p->dma_write(0, CICR, lch); -	l = dma_read(CCR(lch)); -	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */ -	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { +	l = p->dma_read(CCR, lch); +	if (IS_DMA_ERRATA(DMA_ERRATA_i541) && +			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {  		int i = 0;  		u32 sys_cf;  		/* Configure No-Standby */ -		l = dma_read(OCP_SYSCONFIG); +		l = p->dma_read(OCP_SYSCONFIG, lch);  		sys_cf = l;  		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;  		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); -		dma_write(l , OCP_SYSCONFIG); +		p->dma_write(l , OCP_SYSCONFIG, 0); -		l = dma_read(CCR(lch)); +		l = p->dma_read(CCR, lch);  		l &= ~OMAP_DMA_CCR_EN; -		dma_write(l, CCR(lch)); +		p->dma_write(l, CCR, lch);  		/* Wait for sDMA FIFO drain */ -		l = dma_read(CCR(lch)); +		l = p->dma_read(CCR, lch);  		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |  					OMAP_DMA_CCR_WR_ACTIVE))) {  			udelay(5);  			i++; -			l = dma_read(CCR(lch)); +			l = p->dma_read(CCR, lch);  		}  		if (i >= 100)  			printk(KERN_ERR "DMA drain did not complete on "  					"lch %d\n", lch);  		/* Restore OCP_SYSCONFIG */ -		dma_write(sys_cf, OCP_SYSCONFIG); +		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);  	} else {  		l &= ~OMAP_DMA_CCR_EN; -		dma_write(l, CCR(lch)); +		p->dma_write(l, CCR, lch);  	}  	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {  		int next_lch, cur_lch = lch; -		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; +		char dma_chan_link_map[dma_lch_count];  		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));  		do { @@ -1122,19 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch)  	dma_addr_t offset = 0;  	if (cpu_is_omap15xx()) -		offset = dma_read(CPC(lch)); +		offset = p->dma_read(CPC, lch);  	else -		offset = dma_read(CSAC(lch)); +		offset = p->dma_read(CSAC, lch); -	/* -	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is -	 * read before the DMA controller finished disabling the channel. -	 */ -	if (!cpu_is_omap15xx() && offset == 0) -		offset = dma_read(CSAC(lch)); +	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) +		offset = p->dma_read(CSAC, lch);  	if (cpu_class_is_omap1()) -		offset |= (dma_read(CSSA_U(lch)) << 16); +		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);  	return offset;  } @@ -1153,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch)  	dma_addr_t offset = 0;  	if (cpu_is_omap15xx()) -		offset = dma_read(CPC(lch)); +		offset = p->dma_read(CPC, lch);  	else -		offset = dma_read(CDAC(lch)); +		offset = p->dma_read(CDAC, lch);  	/*  	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is  	 * read before the DMA controller finished disabling the channel.  	 */  	if (!cpu_is_omap15xx() && offset == 0) -		offset = dma_read(CDAC(lch)); +		offset = p->dma_read(CDAC, lch);  	if (cpu_class_is_omap1()) -		offset |= (dma_read(CDSA_U(lch)) << 16); +		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);  	return offset;  } @@ -1173,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);  int omap_get_dma_active_status(int lch)  { -	return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0; +	return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;  }  EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1186,7 +1087,7 @@ int omap_dma_running(void)  			return 1;  	for (lch = 0; lch < dma_chan_count; lch++) -		if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) +		if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)  			return 1;  	return 0; @@ -1201,8 +1102,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue)  {  	if (omap_dma_in_1510_mode()) {  		if (lch_head == lch_queue) { -			dma_write(dma_read(CCR(lch_head)) | (3 << 8), -								CCR(lch_head)); +			p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8), +								CCR, lch_head);  			return;  		}  		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1228,8 +1129,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)  {  	if (omap_dma_in_1510_mode()) {  		if (lch_head == lch_queue) { -			dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), -								CCR(lch_head)); +			p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), +								CCR, lch_head);  			return;  		}  		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1255,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)  }  EXPORT_SYMBOL(omap_dma_unlink_lch); -/*----------------------------------------------------------------------------*/ -  #ifndef CONFIG_ARCH_OMAP1  /* Create chain of DMA channesls */  static void create_dma_lch_chain(int lch_head, int lch_queue) @@ -1281,15 +1180,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)  					lch_queue;  	} -	l = dma_read(CLNK_CTRL(lch_head)); +	l = p->dma_read(CLNK_CTRL, lch_head);  	l &= ~(0x1f);  	l |= lch_queue; -	dma_write(l, CLNK_CTRL(lch_head)); +	p->dma_write(l, CLNK_CTRL, lch_head); -	l = dma_read(CLNK_CTRL(lch_queue)); +	l = p->dma_read(CLNK_CTRL, lch_queue);  	l &= ~(0x1f);  	l |= (dma_chan[lch_queue].next_linked_ch); -	dma_write(l, CLNK_CTRL(lch_queue)); +	p->dma_write(l, CLNK_CTRL, lch_queue);  }  /** @@ -1565,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,  	/* Set the params to the free channel */  	if (src_start != 0) -		dma_write(src_start, CSSA(lch)); +		p->dma_write(src_start, CSSA, lch);  	if (dest_start != 0) -		dma_write(dest_start, CDSA(lch)); +		p->dma_write(dest_start, CDSA, lch);  	/* Write the buffer size */ -	dma_write(elem_count, CEN(lch)); -	dma_write(frame_count, CFN(lch)); +	p->dma_write(elem_count, CEN, lch); +	p->dma_write(frame_count, CFN, lch);  	/*  	 * If the chain is dynamically linked, @@ -1604,8 +1503,8 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,  				enable_lnk(dma_chan[lch].prev_linked_ch);  				dma_chan[lch].state = DMA_CH_QUEUED;  				start_dma = 0; -				if (0 == ((1 << 7) & dma_read( -					CCR(dma_chan[lch].prev_linked_ch)))) { +				if (0 == ((1 << 7) & p->dma_read( +					CCR, dma_chan[lch].prev_linked_ch))) {  					disable_lnk(dma_chan[lch].  						    prev_linked_ch);  					pr_debug("\n prev ch is stopped\n"); @@ -1621,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,  			}  			omap_enable_channel_irq(lch); -			l = dma_read(CCR(lch)); +			l = p->dma_read(CCR, lch);  			if ((0 == (l & (1 << 24))))  				l &= ~(1 << 25); @@ -1632,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,  					l |= (1 << 7);  					dma_chan[lch].state = DMA_CH_STARTED;  					pr_debug("starting %d\n", lch); -					dma_write(l, CCR(lch)); +					p->dma_write(l, CCR, lch);  				} else  					start_dma = 0;  			} else {  				if (0 == (l & (1 << 7))) -					dma_write(l, CCR(lch)); +					p->dma_write(l, CCR, lch);  			}  			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;  		} @@ -1682,7 +1581,7 @@ int omap_start_dma_chain_transfers(int chain_id)  		omap_enable_channel_irq(channels[0]);  	} -	l = dma_read(CCR(channels[0])); +	l = p->dma_read(CCR, channels[0]);  	l |= (1 << 7);  	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;  	dma_chan[channels[0]].state = DMA_CH_STARTED; @@ -1691,7 +1590,7 @@ int omap_start_dma_chain_transfers(int chain_id)  		l &= ~(1 << 25);  	else  		l |= (1 << 25); -	dma_write(l, CCR(channels[0])); +	p->dma_write(l, CCR, channels[0]);  	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1711,7 +1610,7 @@ int omap_stop_dma_chain_transfers(int chain_id)  {  	int *channels;  	u32 l, i; -	u32 sys_cf; +	u32 sys_cf = 0;  	/* Check for input params */  	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1726,22 +1625,20 @@ int omap_stop_dma_chain_transfers(int chain_id)  	}  	channels = dma_linked_lch[chain_id].linked_dmach_q; -	/* -	 * DMA Errata: -	 * Special programming model needed to disable DMA before end of block -	 */ -	sys_cf = dma_read(OCP_SYSCONFIG); -	l = sys_cf; -	/* Middle mode reg set no Standby */ -	l &= ~((1 << 12)|(1 << 13)); -	dma_write(l, OCP_SYSCONFIG); +	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { +		sys_cf = p->dma_read(OCP_SYSCONFIG, 0); +		l = sys_cf; +		/* Middle mode reg set no Standby */ +		l &= ~((1 << 12)|(1 << 13)); +		p->dma_write(l, OCP_SYSCONFIG, 0); +	}  	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {  		/* Stop the Channel transmission */ -		l = dma_read(CCR(channels[i])); +		l = p->dma_read(CCR, channels[i]);  		l &= ~(1 << 7); -		dma_write(l, CCR(channels[i])); +		p->dma_write(l, CCR, channels[i]);  		/* Disable the link in all the channels */  		disable_lnk(channels[i]); @@ -1753,8 +1650,8 @@ int omap_stop_dma_chain_transfers(int chain_id)  	/* Reset the Queue pointers */  	OMAP_DMA_CHAIN_QINIT(chain_id); -	/* Errata - put in the old value */ -	dma_write(sys_cf, OCP_SYSCONFIG); +	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) +		p->dma_write(sys_cf, OCP_SYSCONFIG, 0);  	return 0;  } @@ -1796,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)  	/* Get the current channel */  	lch = channels[dma_linked_lch[chain_id].q_head]; -	*ei = dma_read(CCEN(lch)); -	*fi = dma_read(CCFN(lch)); +	*ei = p->dma_read(CCEN, lch); +	*fi = p->dma_read(CCFN, lch);  	return 0;  } @@ -1834,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain_id)  	/* Get the current channel */  	lch = channels[dma_linked_lch[chain_id].q_head]; -	return dma_read(CDAC(lch)); +	return p->dma_read(CDAC, lch);  }  EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1868,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain_id)  	/* Get the current channel */  	lch = channels[dma_linked_lch[chain_id].q_head]; -	return dma_read(CSAC(lch)); +	return p->dma_read(CSAC, lch);  }  EXPORT_SYMBOL(omap_get_dma_chain_src_pos);  #endif	/* ifndef CONFIG_ARCH_OMAP1 */ @@ -1885,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch)  		csr = dma_chan[ch].saved_csr;  		dma_chan[ch].saved_csr = 0;  	} else -		csr = dma_read(CSR(ch)); +		csr = p->dma_read(CSR, ch);  	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {  		dma_chan[ch + 6].saved_csr = csr >> 7;  		csr &= 0x7f; @@ -1938,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)  static int omap2_dma_handle_ch(int ch)  { -	u32 status = dma_read(CSR(ch)); +	u32 status = p->dma_read(CSR, ch);  	if (!status) {  		if (printk_ratelimit())  			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",  				ch); -		dma_write(1 << ch, IRQSTATUS_L0); +		p->dma_write(1 << ch, IRQSTATUS_L0, ch);  		return 0;  	}  	if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -1960,17 +1857,12 @@ static int omap2_dma_handle_ch(int ch)  	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {  		printk(KERN_INFO "DMA transaction error with device %d\n",  		       dma_chan[ch].dev_id); -		if (cpu_class_is_omap2()) { -			/* -			 * Errata: sDMA Channel is not disabled -			 * after a transaction error. So we explicitely -			 * disable the channel -			 */ +		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {  			u32 ccr; -			ccr = dma_read(CCR(ch)); +			ccr = p->dma_read(CCR, ch);  			ccr &= ~OMAP_DMA_CCR_EN; -			dma_write(ccr, CCR(ch)); +			p->dma_write(ccr, CCR, ch);  			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;  		}  	} @@ -1981,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch)  		printk(KERN_INFO "DMA misaligned error with device %d\n",  		       dma_chan[ch].dev_id); -	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch)); -	dma_write(1 << ch, IRQSTATUS_L0); +	p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); +	p->dma_write(1 << ch, IRQSTATUS_L0, ch);  	/* read back the register to flush the write */ -	dma_read(IRQSTATUS_L0); +	p->dma_read(IRQSTATUS_L0, ch);  	/* If the ch is not chained then chain_id will be -1 */  	if (dma_chan[ch].chain_id != -1) {  		int chain_id = dma_chan[ch].chain_id;  		dma_chan[ch].state = DMA_CH_NOTSTARTED; -		if (dma_read(CLNK_CTRL(ch)) & (1 << 15)) +		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))  			dma_chan[dma_chan[ch].next_linked_ch].state =  							DMA_CH_STARTED;  		if (dma_linked_lch[chain_id].chain_mode == @@ -2000,10 +1892,10 @@ static int omap2_dma_handle_ch(int ch)  		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))  			OMAP_DMA_CHAIN_INCQHEAD(chain_id); -		status = dma_read(CSR(ch)); +		status = p->dma_read(CSR, ch);  	} -	dma_write(status, CSR(ch)); +	p->dma_write(status, CSR, ch);  	if (likely(dma_chan[ch].callback != NULL))  		dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -2017,13 +1909,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)  	u32 val, enable_reg;  	int i; -	val = dma_read(IRQSTATUS_L0); +	val = p->dma_read(IRQSTATUS_L0, 0);  	if (val == 0) {  		if (printk_ratelimit())  			printk(KERN_WARNING "Spurious DMA IRQ\n");  		return IRQ_HANDLED;  	} -	enable_reg = dma_read(IRQENABLE_L0); +	enable_reg = p->dma_read(IRQENABLE_L0, 0);  	val &= enable_reg; /* Dispatch only relevant interrupts */  	for (i = 0; i < dma_lch_count && val != 0; i++) {  		if (val & 1) @@ -2049,119 +1941,66 @@ static struct irqaction omap24xx_dma_irq;  void omap_dma_global_context_save(void)  {  	omap_dma_global_context.dma_irqenable_l0 = -		dma_read(IRQENABLE_L0); +		p->dma_read(IRQENABLE_L0, 0);  	omap_dma_global_context.dma_ocp_sysconfig = -		dma_read(OCP_SYSCONFIG); -	omap_dma_global_context.dma_gcr = dma_read(GCR); +		p->dma_read(OCP_SYSCONFIG, 0); +	omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);  }  void omap_dma_global_context_restore(void)  {  	int ch; -	dma_write(omap_dma_global_context.dma_gcr, GCR); -	dma_write(omap_dma_global_context.dma_ocp_sysconfig, -		OCP_SYSCONFIG); -	dma_write(omap_dma_global_context.dma_irqenable_l0, -		IRQENABLE_L0); +	p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0); +	p->dma_write(omap_dma_global_context.dma_ocp_sysconfig, +		OCP_SYSCONFIG, 0); +	p->dma_write(omap_dma_global_context.dma_irqenable_l0, +		IRQENABLE_L0, 0); -	/* -	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared -	 * after secure sram context save and restore. Hence we need to -	 * manually clear those IRQs to avoid spurious interrupts. This -	 * affects only secure devices. -	 */ -	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) -		dma_write(0x3 , IRQSTATUS_L0); +	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) +		p->dma_write(0x3 , IRQSTATUS_L0, 0);  	for (ch = 0; ch < dma_chan_count; ch++)  		if (dma_chan[ch].dev_id != -1)  			omap_clear_dma(ch);  } -/*----------------------------------------------------------------------------*/ - -static int __init omap_init_dma(void) +static int __devinit omap_system_dma_probe(struct platform_device *pdev)  { -	unsigned long base; -	int ch, r; +	int ch, ret = 0; +	int dma_irq; +	char irq_name[4]; +	int irq_rel; -	if (cpu_class_is_omap1()) { -		base = OMAP1_DMA_BASE; -		dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; -	} else if (cpu_is_omap24xx()) { -		base = OMAP24XX_DMA4_BASE; -		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; -	} else if (cpu_is_omap34xx()) { -		base = OMAP34XX_DMA4_BASE; -		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; -	} else if (cpu_is_omap44xx()) { -		base = OMAP44XX_DMA4_BASE; -		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; -	} else { -		pr_err("DMA init failed for unsupported omap\n"); -		return -ENODEV; +	p = pdev->dev.platform_data; +	if (!p) { +		dev_err(&pdev->dev, "%s: System DMA initialized without" +			"platform data\n", __func__); +		return -EINVAL;  	} -	omap_dma_base = ioremap(base, SZ_4K); -	BUG_ON(!omap_dma_base); +	d			= p->dma_attr; +	errata			= p->errata; -	if (cpu_class_is_omap2() && omap_dma_reserve_channels +	if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels  			&& (omap_dma_reserve_channels <= dma_lch_count)) -		dma_lch_count = omap_dma_reserve_channels; +		d->lch_count	= omap_dma_reserve_channels; -	dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, -				GFP_KERNEL); -	if (!dma_chan) { -		r = -ENOMEM; -		goto out_unmap; -	} +	dma_lch_count		= d->lch_count; +	dma_chan_count		= dma_lch_count; +	dma_chan		= d->chan; +	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;  	if (cpu_class_is_omap2()) {  		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *  						dma_lch_count, GFP_KERNEL);  		if (!dma_linked_lch) { -			r = -ENOMEM; -			goto out_free; +			ret = -ENOMEM; +			goto exit_dma_lch_fail;  		}  	} -	if (cpu_is_omap15xx()) { -		printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); -		dma_chan_count = 9; -		enable_1510_mode = 1; -	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { -		printk(KERN_INFO "OMAP DMA hardware version %d\n", -		       dma_read(HW_ID)); -		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", -		       (dma_read(CAPS_0_U) << 16) | -		       dma_read(CAPS_0_L), -		       (dma_read(CAPS_1_U) << 16) | -		       dma_read(CAPS_1_L), -		       dma_read(CAPS_2), dma_read(CAPS_3), -		       dma_read(CAPS_4)); -		if (!enable_1510_mode) { -			u16 w; - -			/* Disable OMAP 3.0/3.1 compatibility mode. */ -			w = dma_read(GSCR); -			w |= 1 << 3; -			dma_write(w, GSCR); -			dma_chan_count = 16; -		} else -			dma_chan_count = 9; -	} else if (cpu_class_is_omap2()) { -		u8 revision = dma_read(REVISION) & 0xff; -		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", -		       revision >> 4, revision & 0xf); -		dma_chan_count = dma_lch_count; -	} else { -		dma_chan_count = 0; -		return 0; -	} -  	spin_lock_init(&dma_chan_lock); -  	for (ch = 0; ch < dma_chan_count; ch++) {  		omap_clear_dma(ch);  		if (cpu_class_is_omap2()) @@ -2178,20 +2017,23 @@ static int __init omap_init_dma(void)  			 * request_irq() doesn't like dev_id (ie. ch) being  			 * zero, so we have to kludge around this.  			 */ -			r = request_irq(omap1_dma_irq[ch], -					omap1_dma_irq_handler, 0, "DMA", -					(void *) (ch + 1)); -			if (r != 0) { -				int i; +			sprintf(&irq_name[0], "%d", ch); +			dma_irq = platform_get_irq_byname(pdev, irq_name); -				printk(KERN_ERR "unable to request IRQ %d " -				       "for DMA (error %d)\n", -				       omap1_dma_irq[ch], r); -				for (i = 0; i < ch; i++) -					free_irq(omap1_dma_irq[i], -						 (void *) (i + 1)); -				goto out_free; +			if (dma_irq < 0) { +				ret = dma_irq; +				goto exit_dma_irq_fail;  			} + +			/* INT_DMA_LCD is handled in lcd_dma.c */ +			if (dma_irq == INT_DMA_LCD) +				continue; + +			ret = request_irq(dma_irq, +					omap1_dma_irq_handler, 0, "DMA", +					(void *) (ch + 1)); +			if (ret != 0) +				goto exit_dma_irq_fail;  		}  	} @@ -2200,46 +2042,91 @@ static int __init omap_init_dma(void)  				DMA_DEFAULT_FIFO_DEPTH, 0);  	if (cpu_class_is_omap2()) { -		int irq; -		if (cpu_is_omap44xx()) -			irq = OMAP44XX_IRQ_SDMA_0; -		else -			irq = INT_24XX_SDMA_IRQ0; -		setup_irq(irq, &omap24xx_dma_irq); -	} - -	if (cpu_is_omap34xx() || cpu_is_omap44xx()) { -		/* Enable smartidle idlemodes and autoidle */ -		u32 v = dma_read(OCP_SYSCONFIG); -		v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | -				DMA_SYSCONFIG_SIDLEMODE_MASK | -				DMA_SYSCONFIG_AUTOIDLE); -		v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | -			DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | -			DMA_SYSCONFIG_AUTOIDLE); -		dma_write(v , OCP_SYSCONFIG); -		/* reserve dma channels 0 and 1 in high security devices */ -		if (cpu_is_omap34xx() && -			(omap_type() != OMAP2_DEVICE_TYPE_GP)) { -			printk(KERN_INFO "Reserving DMA channels 0 and 1 for " -					"HS ROM code\n"); -			dma_chan[0].dev_id = 0; -			dma_chan[1].dev_id = 1; +		strcpy(irq_name, "0"); +		dma_irq = platform_get_irq_byname(pdev, irq_name); +		if (dma_irq < 0) { +			dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq); +			goto exit_dma_lch_fail; +		} +		ret = setup_irq(dma_irq, &omap24xx_dma_irq); +		if (ret) { +			dev_err(&pdev->dev, "set_up failed for IRQ %d" +				"for DMA (error %d)\n", dma_irq, ret); +			goto exit_dma_lch_fail;  		}  	} +	/* reserve dma channels 0 and 1 in high security devices */ +	if (cpu_is_omap34xx() && +		(omap_type() != OMAP2_DEVICE_TYPE_GP)) { +		printk(KERN_INFO "Reserving DMA channels 0 and 1 for " +				"HS ROM code\n"); +		dma_chan[0].dev_id = 0; +		dma_chan[1].dev_id = 1; +	} +	p->show_dma_caps();  	return 0; -out_free: +exit_dma_irq_fail: +	dev_err(&pdev->dev, "unable to request IRQ %d" +			"for DMA (error %d)\n", dma_irq, ret); +	for (irq_rel = 0; irq_rel < ch;	irq_rel++) { +		dma_irq = platform_get_irq(pdev, irq_rel); +		free_irq(dma_irq, (void *)(irq_rel + 1)); +	} + +exit_dma_lch_fail: +	kfree(p); +	kfree(d);  	kfree(dma_chan); +	return ret; +} -out_unmap: -	iounmap(omap_dma_base); +static int __devexit omap_system_dma_remove(struct platform_device *pdev) +{ +	int dma_irq; -	return r; +	if (cpu_class_is_omap2()) { +		char irq_name[4]; +		strcpy(irq_name, "0"); +		dma_irq = platform_get_irq_byname(pdev, irq_name); +		remove_irq(dma_irq, &omap24xx_dma_irq); +	} else { +		int irq_rel = 0; +		for ( ; irq_rel < dma_chan_count; irq_rel++) { +			dma_irq = platform_get_irq(pdev, irq_rel); +			free_irq(dma_irq, (void *)(irq_rel + 1)); +		} +	} +	kfree(p); +	kfree(d); +	kfree(dma_chan); +	return 0; +} + +static struct platform_driver omap_system_dma_driver = { +	.probe		= omap_system_dma_probe, +	.remove		= omap_system_dma_remove, +	.driver		= { +		.name	= "omap_dma_system" +	}, +}; + +static int __init omap_system_dma_init(void) +{ +	return platform_driver_register(&omap_system_dma_driver); +} +arch_initcall(omap_system_dma_init); + +static void __exit omap_system_dma_exit(void) +{ +	platform_driver_unregister(&omap_system_dma_driver);  } -arch_initcall(omap_init_dma); +MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_AUTHOR("Texas Instruments Inc");  /*   * Reserve the omap SDMA channels using cmdline bootarg diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 0cce4ca83aa..d1c916fcf77 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -21,141 +21,15 @@  #ifndef __ASM_ARCH_DMA_H  #define __ASM_ARCH_DMA_H -/* Move omap4 specific defines to dma-44xx.h */ -#include "dma-44xx.h" - -/* Hardware registers for omap1 */ -#define OMAP1_DMA_BASE			(0xfffed800) - -#define OMAP1_DMA_GCR			0x400 -#define OMAP1_DMA_GSCR			0x404 -#define OMAP1_DMA_GRST			0x408 -#define OMAP1_DMA_HW_ID			0x442 -#define OMAP1_DMA_PCH2_ID		0x444 -#define OMAP1_DMA_PCH0_ID		0x446 -#define OMAP1_DMA_PCH1_ID		0x448 -#define OMAP1_DMA_PCHG_ID		0x44a -#define OMAP1_DMA_PCHD_ID		0x44c -#define OMAP1_DMA_CAPS_0_U		0x44e -#define OMAP1_DMA_CAPS_0_L		0x450 -#define OMAP1_DMA_CAPS_1_U		0x452 -#define OMAP1_DMA_CAPS_1_L		0x454 -#define OMAP1_DMA_CAPS_2		0x456 -#define OMAP1_DMA_CAPS_3		0x458 -#define OMAP1_DMA_CAPS_4		0x45a -#define OMAP1_DMA_PCH2_SR		0x460 -#define OMAP1_DMA_PCH0_SR		0x480 -#define OMAP1_DMA_PCH1_SR		0x482 -#define OMAP1_DMA_PCHD_SR		0x4c0 - -/* Hardware registers for omap2 and omap3 */ -#define OMAP24XX_DMA4_BASE		(L4_24XX_BASE + 0x56000) -#define OMAP34XX_DMA4_BASE		(L4_34XX_BASE + 0x56000) -#define OMAP44XX_DMA4_BASE		(L4_44XX_BASE + 0x56000) - -#define OMAP_DMA4_REVISION		0x00 -#define OMAP_DMA4_GCR			0x78 -#define OMAP_DMA4_IRQSTATUS_L0		0x08 -#define OMAP_DMA4_IRQSTATUS_L1		0x0c -#define OMAP_DMA4_IRQSTATUS_L2		0x10 -#define OMAP_DMA4_IRQSTATUS_L3		0x14 -#define OMAP_DMA4_IRQENABLE_L0		0x18 -#define OMAP_DMA4_IRQENABLE_L1		0x1c -#define OMAP_DMA4_IRQENABLE_L2		0x20 -#define OMAP_DMA4_IRQENABLE_L3		0x24 -#define OMAP_DMA4_SYSSTATUS		0x28 -#define OMAP_DMA4_OCP_SYSCONFIG		0x2c -#define OMAP_DMA4_CAPS_0		0x64 -#define OMAP_DMA4_CAPS_2		0x6c -#define OMAP_DMA4_CAPS_3		0x70 -#define OMAP_DMA4_CAPS_4		0x74 - -#define OMAP1_LOGICAL_DMA_CH_COUNT	17 -#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT	32	/* REVISIT: Is this 32 + 2? */ - -/* Common channel specific registers for omap1 */ -#define OMAP1_DMA_CH_BASE(n)		(0x40 * (n) + 0x00) -#define OMAP1_DMA_CSDP(n)		(0x40 * (n) + 0x00) -#define OMAP1_DMA_CCR(n)		(0x40 * (n) + 0x02) -#define OMAP1_DMA_CICR(n)		(0x40 * (n) + 0x04) -#define OMAP1_DMA_CSR(n)		(0x40 * (n) + 0x06) -#define OMAP1_DMA_CEN(n)		(0x40 * (n) + 0x10) -#define OMAP1_DMA_CFN(n)		(0x40 * (n) + 0x12) -#define OMAP1_DMA_CSFI(n)		(0x40 * (n) + 0x14) -#define OMAP1_DMA_CSEI(n)		(0x40 * (n) + 0x16) -#define OMAP1_DMA_CPC(n)		(0x40 * (n) + 0x18)	/* 15xx only */ -#define OMAP1_DMA_CSAC(n)		(0x40 * (n) + 0x18) -#define OMAP1_DMA_CDAC(n)		(0x40 * (n) + 0x1a) -#define OMAP1_DMA_CDEI(n)		(0x40 * (n) + 0x1c) -#define OMAP1_DMA_CDFI(n)		(0x40 * (n) + 0x1e) -#define OMAP1_DMA_CLNK_CTRL(n)		(0x40 * (n) + 0x28) - -/* Common channel specific registers for omap2 */ -#define OMAP_DMA4_CH_BASE(n)		(0x60 * (n) + 0x80) -#define OMAP_DMA4_CCR(n)		(0x60 * (n) + 0x80) -#define OMAP_DMA4_CLNK_CTRL(n)		(0x60 * (n) + 0x84) -#define OMAP_DMA4_CICR(n)		(0x60 * (n) + 0x88) -#define OMAP_DMA4_CSR(n)		(0x60 * (n) + 0x8c) -#define OMAP_DMA4_CSDP(n)		(0x60 * (n) + 0x90) -#define OMAP_DMA4_CEN(n)		(0x60 * (n) + 0x94) -#define OMAP_DMA4_CFN(n)		(0x60 * (n) + 0x98) -#define OMAP_DMA4_CSEI(n)		(0x60 * (n) + 0xa4) -#define OMAP_DMA4_CSFI(n)		(0x60 * (n) + 0xa8) -#define OMAP_DMA4_CDEI(n)		(0x60 * (n) + 0xac) -#define OMAP_DMA4_CDFI(n)		(0x60 * (n) + 0xb0) -#define OMAP_DMA4_CSAC(n)		(0x60 * (n) + 0xb4) -#define OMAP_DMA4_CDAC(n)		(0x60 * (n) + 0xb8) +#include <linux/platform_device.h> -/* Channel specific registers only on omap1 */ -#define OMAP1_DMA_CSSA_L(n)		(0x40 * (n) + 0x08) -#define OMAP1_DMA_CSSA_U(n)		(0x40 * (n) + 0x0a) -#define OMAP1_DMA_CDSA_L(n)		(0x40 * (n) + 0x0c) -#define OMAP1_DMA_CDSA_U(n)		(0x40 * (n) + 0x0e) -#define OMAP1_DMA_COLOR_L(n)		(0x40 * (n) + 0x20) -#define OMAP1_DMA_COLOR_U(n)		(0x40 * (n) + 0x22) -#define OMAP1_DMA_CCR2(n)		(0x40 * (n) + 0x24) -#define OMAP1_DMA_LCH_CTRL(n)		(0x40 * (n) + 0x2a)	/* not on 15xx */ -#define OMAP1_DMA_CCEN(n)		0 -#define OMAP1_DMA_CCFN(n)		0 - -/* Channel specific registers only on omap2 */ -#define OMAP_DMA4_CSSA(n)		(0x60 * (n) + 0x9c) -#define OMAP_DMA4_CDSA(n)		(0x60 * (n) + 0xa0) -#define OMAP_DMA4_CCEN(n)		(0x60 * (n) + 0xbc) -#define OMAP_DMA4_CCFN(n)		(0x60 * (n) + 0xc0) -#define OMAP_DMA4_COLOR(n)		(0x60 * (n) + 0xc4) - -/* Additional registers available on OMAP4 */ -#define OMAP_DMA4_CDP(n)		(0x60 * (n) + 0xd0) -#define OMAP_DMA4_CNDP(n)		(0x60 * (n) + 0xd4) -#define OMAP_DMA4_CCDN(n)		(0x60 * (n) + 0xd8) - -/* Dummy defines to keep multi-omap compiles happy */ -#define OMAP1_DMA_REVISION		0 -#define OMAP1_DMA_IRQSTATUS_L0		0 -#define OMAP1_DMA_IRQENABLE_L0		0 -#define OMAP1_DMA_OCP_SYSCONFIG		0 -#define OMAP_DMA4_HW_ID			0 -#define OMAP_DMA4_CAPS_0_L		0 -#define OMAP_DMA4_CAPS_0_U		0 -#define OMAP_DMA4_CAPS_1_L		0 -#define OMAP_DMA4_CAPS_1_U		0 -#define OMAP_DMA4_GSCR			0 -#define OMAP_DMA4_CPC(n)		0 - -#define OMAP_DMA4_LCH_CTRL(n)		0 -#define OMAP_DMA4_COLOR_L(n)		0 -#define OMAP_DMA4_COLOR_U(n)		0 -#define OMAP_DMA4_CCR2(n)		0 -#define OMAP1_DMA_CSSA(n)		0 -#define OMAP1_DMA_CDSA(n)		0 -#define OMAP_DMA4_CSSA_L(n)		0 -#define OMAP_DMA4_CSSA_U(n)		0 -#define OMAP_DMA4_CDSA_L(n)		0 -#define OMAP_DMA4_CDSA_U(n)		0 -#define OMAP1_DMA_COLOR(n)		0 +/* + * TODO: These dma channel defines should go away once all + * the omap drivers hwmod adapted. + */ -/*----------------------------------------------------------------------------*/ +/* Move omap4 specific defines to dma-44xx.h */ +#include "dma-44xx.h"  /* DMA channels for omap1 */  #define OMAP_DMA_NO_DEVICE		0 @@ -405,6 +279,63 @@  #define DMA_CH_PRIO_HIGH		0x1  #define DMA_CH_PRIO_LOW			0x0 /* Def */ +/* Errata handling */ +#define IS_DMA_ERRATA(id)		(errata & (id)) +#define SET_DMA_ERRATA(id)		(errata |= (id)) + +#define DMA_ERRATA_IFRAME_BUFFERING	BIT(0x0) +#define DMA_ERRATA_PARALLEL_CHANNELS	BIT(0x1) +#define DMA_ERRATA_i378			BIT(0x2) +#define DMA_ERRATA_i541			BIT(0x3) +#define DMA_ERRATA_i88			BIT(0x4) +#define DMA_ERRATA_3_3			BIT(0x5) +#define DMA_ROMCODE_BUG			BIT(0x6) + +/* Attributes for OMAP DMA Contrller */ +#define DMA_LINKED_LCH			BIT(0x0) +#define GLOBAL_PRIORITY			BIT(0x1) +#define RESERVE_CHANNEL			BIT(0x2) +#define IS_CSSA_32			BIT(0x3) +#define IS_CDSA_32			BIT(0x4) +#define IS_RW_PRIORITY			BIT(0x5) +#define ENABLE_1510_MODE		BIT(0x6) +#define SRC_PORT			BIT(0x7) +#define DST_PORT			BIT(0x8) +#define SRC_INDEX			BIT(0x9) +#define DST_INDEX			BIT(0xA) +#define IS_BURST_ONLY4			BIT(0xB) +#define CLEAR_CSR_ON_READ		BIT(0xC) +#define IS_WORD_16			BIT(0xD) + +enum omap_reg_offsets { + +GCR,		GSCR,		GRST1,		HW_ID, +PCH2_ID,	PCH0_ID,	PCH1_ID,	PCHG_ID, +PCHD_ID,	CAPS_0,		CAPS_1,		CAPS_2, +CAPS_3,		CAPS_4,		PCH2_SR,	PCH0_SR, +PCH1_SR,	PCHD_SR,	REVISION,	IRQSTATUS_L0, +IRQSTATUS_L1,	IRQSTATUS_L2,	IRQSTATUS_L3,	IRQENABLE_L0, +IRQENABLE_L1,	IRQENABLE_L2,	IRQENABLE_L3,	SYSSTATUS, +OCP_SYSCONFIG, + +/* omap1+ specific */ +CPC, CCR2, LCH_CTRL, + +/* Common registers for all omap's */ +CSDP,		CCR,		CICR,		CSR, +CEN,		CFN,		CSFI,		CSEI, +CSAC,		CDAC,		CDEI, +CDFI,		CLNK_CTRL, + +/* Channel specific registers */ +CSSA,		CDSA,		COLOR, +CCEN,		CCFN, + +/* omap3630 and omap4 specific */ +CDP,		CNDP,		CCDN, + +}; +  enum omap_dma_burst_mode {  	OMAP_DMA_DATA_BURST_DIS = 0,  	OMAP_DMA_DATA_BURST_4, @@ -470,6 +401,41 @@ struct omap_dma_channel_params {  #endif  }; +struct omap_dma_lch { +	int next_lch; +	int dev_id; +	u16 saved_csr; +	u16 enabled_irqs; +	const char *dev_name; +	void (*callback)(int lch, u16 ch_status, void *data); +	void *data; +	long flags; +	/* required for Dynamic chaining */ +	int prev_linked_ch; +	int next_linked_ch; +	int state; +	int chain_id; +	int status; +}; + +struct omap_dma_dev_attr { +	u32 dev_caps; +	u16 lch_count; +	u16 chan_count; +	struct omap_dma_lch *chan; +}; + +/* System DMA platform data structure */ +struct omap_system_dma_plat_info { +	struct omap_dma_dev_attr *dma_attr; +	u32 errata; +	void (*disable_irq_lch)(int lch); +	void (*show_dma_caps)(void); +	void (*clear_lch_regs)(int lch); +	void (*clear_dma)(int lch); +	void (*dma_write)(u32 val, int reg, int lch); +	u32 (*dma_read)(int reg, int lch); +};  extern void omap_set_dma_priority(int lch, int dst_port, int priority);  extern int omap_request_dma(int dev_id, const char *dev_name,  |