diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 20:19:14 +0100 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 20:19:14 +0100 |
commit | 0c17e4ceedd35c78b1c7413dbd16279a350be6bc (patch) | |
tree | 313b3b9ca04727f3704464e01d8dd97da1dd534b /arch/arm/plat-omap | |
parent | 19c1d6a34abf73d0baf8e325d018c920fa78dddc (diff) | |
parent | b9d2252c1e44fa83a4e65fdc9eb93db6297c55af (diff) | |
download | blackbird-op-linux-0c17e4ceedd35c78b1c7413dbd16279a350be6bc.tar.gz blackbird-op-linux-0c17e4ceedd35c78b1c7413dbd16279a350be6bc.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-rmk
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 128 | ||||
-rw-r--r-- | arch/arm/plat-omap/common.c | 59 | ||||
-rw-r--r-- | arch/arm/plat-omap/devices.c | 48 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 766 | ||||
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 212 | ||||
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 767 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram-fn.S | 57 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 211 | ||||
-rw-r--r-- | arch/arm/plat-omap/usb.c | 131 |
10 files changed, 1405 insertions, 976 deletions
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index bc639a30d6d1..2c4051cc79a1 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ +obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \ usb.o fb.o obj-m := obj-n := diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2db5580048d8..c2e741de0203 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/plat-omap/clock.c * - * Copyright (C) 2004 - 2005 Nokia corporation + * Copyright (C) 2004 - 2008 Nokia corporation * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> * * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> @@ -22,6 +22,7 @@ #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/cpufreq.h> +#include <linux/debugfs.h> #include <asm/io.h> @@ -33,41 +34,6 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -#ifdef CONFIG_PM_DEBUG - -static void print_parents(struct clk *clk) -{ - struct clk *p; - int printed = 0; - - list_for_each_entry(p, &clocks, node) { - if (p->parent == clk && p->usecount) { - if (!clk->usecount && !printed) { - printk("MISMATCH: %s\n", clk->name); - printed = 1; - } - printk("\t%-15s\n", p->name); - } - } -} - -void clk_print_usecounts(void) -{ - unsigned long flags; - struct clk *p; - - spin_lock_irqsave(&clockfw_lock, flags); - list_for_each_entry(p, &clocks, node) { - if (p->usecount) - printk("%-15s: %d\n", p->name, p->usecount); - print_parents(p); - - } - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -#endif - /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ @@ -446,3 +412,93 @@ int __init clk_init(struct clk_functions * custom_clocks) return 0; } +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static struct dentry *clk_debugfs_root; + +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child; + struct clk *pa = c->parent; + char s[255]; + char *p = s; + + p += sprintf(p, "%s", c->name); + if (c->id != 0) + sprintf(p, ":%d", c->id); + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (IS_ERR(d)) + return PTR_ERR(d); + c->dent = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + return 0; + +err_out: + d = c->dent; + list_for_each_entry(child, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (IS_ERR(d)) + return PTR_ERR(d); + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ + return err; +} +late_initcall(clk_debugfs_init); + +#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index bd1cef2c3c14..8d04929a3c75 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -26,6 +26,7 @@ #include <asm/io.h> #include <asm/setup.h> +#include <asm/arch/common.h> #include <asm/arch/board.h> #include <asm/arch/control.h> #include <asm/arch/mux.h> @@ -241,30 +242,70 @@ arch_initcall(omap_init_clocksource_32k); /* Global address base setup code */ +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) + +static struct omap_globals *omap2_globals; + +static void __init __omap2_set_globals(void) +{ + omap2_set_globals_memory(omap2_globals); + omap2_set_globals_control(omap2_globals); + omap2_set_globals_prcm(omap2_globals); +} + +#endif + #if defined(CONFIG_ARCH_OMAP2420) + +static struct omap_globals omap242x_globals = { + .tap = (__force void __iomem *)OMAP2_IO_ADDRESS(0x48014000), + .sdrc = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE), + .sms = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE), + .ctrl = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE), + .prm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE), + .cm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CM_BASE), +}; + void __init omap2_set_globals_242x(void) { - omap2_sdrc_base = OMAP2420_SDRC_BASE; - omap2_sms_base = OMAP2420_SMS_BASE; - omap_ctrl_base_set(OMAP2420_CTRL_BASE); + omap2_globals = &omap242x_globals; + __omap2_set_globals(); } #endif #if defined(CONFIG_ARCH_OMAP2430) + +static struct omap_globals omap243x_globals = { + .tap = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4900a000), + .sdrc = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE), + .sms = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE), + .ctrl = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE), + .prm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE), + .cm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_CM_BASE), +}; + void __init omap2_set_globals_243x(void) { - omap2_sdrc_base = OMAP243X_SDRC_BASE; - omap2_sms_base = OMAP243X_SMS_BASE; - omap_ctrl_base_set(OMAP243X_CTRL_BASE); + omap2_globals = &omap243x_globals; + __omap2_set_globals(); } #endif #if defined(CONFIG_ARCH_OMAP3430) + +static struct omap_globals omap343x_globals = { + .tap = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4830A000), + .sdrc = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE), + .sms = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE), + .ctrl = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE), + .prm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE), + .cm = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_CM_BASE), +}; + void __init omap2_set_globals_343x(void) { - omap2_sdrc_base = OMAP343X_SDRC_BASE; - omap2_sms_base = OMAP343X_SMS_BASE; - omap_ctrl_base_set(OMAP343X_CTRL_BASE); + omap2_globals = &omap343x_globals; + __omap2_set_globals(); } #endif diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 4a53f9ba6c43..81002b722da1 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -24,6 +24,7 @@ #include <asm/arch/mux.h> #include <asm/arch/gpio.h> #include <asm/arch/menelaus.h> +#include <asm/arch/mcbsp.h> #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) @@ -145,6 +146,53 @@ static inline void omap_init_kp(void) {} #endif /*-------------------------------------------------------------------------*/ +#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE) + +static struct platform_device **omap_mcbsp_devices; + +void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, + int size) +{ + int i; + + if (size > OMAP_MAX_MCBSP_COUNT) { + printk(KERN_WARNING "Registered too many McBSPs platform_data." + " Using maximum (%d) available.\n", + OMAP_MAX_MCBSP_COUNT); + size = OMAP_MAX_MCBSP_COUNT; + } + + omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *), + GFP_KERNEL); + if (!omap_mcbsp_devices) { + printk(KERN_ERR "Could not register McBSP devices\n"); + return; + } + + for (i = 0; i < size; i++) { + struct platform_device *new_mcbsp; + int ret; + + new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1); + if (!new_mcbsp) + continue; + new_mcbsp->dev.platform_data = &config[i]; + ret = platform_device_add(new_mcbsp); + if (ret) { + platform_device_put(new_mcbsp); + continue; + } + omap_mcbsp_devices[i] = new_mcbsp; + } +} + +#else +void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, + int size) +{ } +#endif + +/*-------------------------------------------------------------------------*/ #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index c00eda588cd8..fac8e994f588 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/plat-omap/dma.c * - * Copyright (C) 2003 Nokia Corporation + * 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 @@ -25,11 +25,11 @@ #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/io.h> #include <asm/system.h> #include <asm/hardware.h> #include <asm/dma.h> -#include <asm/io.h> #include <asm/arch/tc.h> @@ -43,13 +43,13 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #endif -#define OMAP_DMA_ACTIVE 0x01 -#define OMAP_DMA_CCR_EN (1 << 7) +#define OMAP_DMA_ACTIVE 0x01 +#define OMAP_DMA_CCR_EN (1 << 7) #define OMAP2_DMA_CSR_CLEAR_MASK 0xffe -#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) +#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) -static int enable_1510_mode = 0; +static int enable_1510_mode; struct omap_dma_lch { int next_lch; @@ -57,7 +57,7 @@ struct omap_dma_lch { u16 saved_csr; u16 enabled_irqs; const char *dev_name; - void (* callback)(int lch, u16 ch_status, void *data); + void (*callback)(int lch, u16 ch_status, void *data); void *data; #ifndef CONFIG_ARCH_OMAP1 @@ -72,7 +72,6 @@ struct omap_dma_lch { long flags; }; -#ifndef CONFIG_ARCH_OMAP1 struct dma_link_info { int *linked_dmach_q; int no_of_lchs_linked; @@ -86,7 +85,9 @@ struct dma_link_info { }; -static struct dma_link_info dma_linked_lch[OMAP_LOGICAL_DMA_CH_COUNT]; +static struct dma_link_info *dma_linked_lch; + +#ifndef CONFIG_ARCH_OMAP1 /* Chain handling macros */ #define OMAP_DMA_CHAIN_QINIT(chain_id) \ @@ -119,12 +120,15 @@ static struct dma_link_info dma_linked_lch[OMAP_LOGICAL_DMA_CH_COUNT]; dma_linked_lch[chain_id].q_count++; \ } while (0) #endif + +static int dma_lch_count; static int dma_chan_count; static spinlock_t dma_chan_lock; -static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT]; +static struct omap_dma_lch *dma_chan; +static void __iomem *omap_dma_base; -static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { +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, @@ -139,6 +143,24 @@ 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 */ int omap_dma_in_1510_mode(void) @@ -173,13 +195,14 @@ 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; - u32 lch_base = OMAP_DMA_BASE + lch * 0x40; + void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch); for (i = 0; i < 0x2c; i += 2) - omap_writew(0, lch_base + i); + __raw_writew(0, lch_base + i); } void omap_set_dma_priority(int lch, int dst_port, int priority) @@ -212,33 +235,49 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) } if (cpu_class_is_omap2()) { + u32 ccr; + + ccr = dma_read(CCR(lch)); if (priority) - OMAP_DMA_CCR_REG(lch) |= (1 << 6); + ccr |= (1 << 6); else - OMAP_DMA_CCR_REG(lch) &= ~(1 << 6); + ccr &= ~(1 << 6); + dma_write(ccr, CCR(lch)); } } +EXPORT_SYMBOL(omap_set_dma_priority); void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, int frame_count, int sync_mode, int dma_trigger, int src_or_dst_synch) { - OMAP_DMA_CSDP_REG(lch) &= ~0x03; - OMAP_DMA_CSDP_REG(lch) |= data_type; + u32 l; + + l = dma_read(CSDP(lch)); + l &= ~0x03; + l |= data_type; + dma_write(l, CSDP(lch)); if (cpu_class_is_omap1()) { - OMAP_DMA_CCR_REG(lch) &= ~(1 << 5); + u16 ccr; + + ccr = dma_read(CCR(lch)); + ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) - OMAP_DMA_CCR_REG(lch) |= 1 << 5; + ccr |= 1 << 5; + dma_write(ccr, CCR(lch)); - OMAP1_DMA_CCR2_REG(lch) &= ~(1 << 2); + ccr = dma_read(CCR2(lch)); + ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) - OMAP1_DMA_CCR2_REG(lch) |= 1 << 2; + ccr |= 1 << 2; + dma_write(ccr, CCR2(lch)); } if (cpu_class_is_omap2() && dma_trigger) { - u32 val = OMAP_DMA_CCR_REG(lch); + u32 val; + val = dma_read(CCR(lch)); val &= ~(3 << 19); if (dma_trigger > 63) val |= 1 << 20; @@ -263,12 +302,13 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, else val &= ~(1 << 24); /* dest synch */ - OMAP_DMA_CCR_REG(lch) = val; + dma_write(val, CCR(lch)); } - OMAP_DMA_CEN_REG(lch) = elem_count; - OMAP_DMA_CFN_REG(lch) = frame_count; + dma_write(elem_count, CEN(lch)); + dma_write(frame_count, CFN(lch)); } +EXPORT_SYMBOL(omap_set_dma_transfer_params); void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) { @@ -281,7 +321,9 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) return; } - w = OMAP1_DMA_CCR2_REG(lch) & ~0x03; + w = dma_read(CCR2(lch)); + w &= ~0x03; + switch (mode) { case OMAP_DMA_CONSTANT_FILL: w |= 0x01; @@ -294,52 +336,81 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - OMAP1_DMA_CCR2_REG(lch) = w; + dma_write(w, CCR2(lch)); - w = OMAP1_DMA_LCH_CTRL_REG(lch) & ~0x0f; + w = dma_read(LCH_CTRL(lch)); + w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - OMAP1_DMA_COLOR_L_REG(lch) = (u16)color; - OMAP1_DMA_COLOR_U_REG(lch) = (u16)(color >> 16); + dma_write((u16)color, COLOR_L(lch)); + dma_write((u16)(color >> 16), COLOR_U(lch)); w |= 1; /* Channel type G */ } - OMAP1_DMA_LCH_CTRL_REG(lch) = w; + dma_write(w, LCH_CTRL(lch)); } +EXPORT_SYMBOL(omap_set_dma_color_mode); void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) { if (cpu_class_is_omap2()) { - OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16); - OMAP_DMA_CSDP_REG(lch) |= (mode << 16); + u32 csdp; + + csdp = dma_read(CSDP(lch)); + csdp &= ~(0x3 << 16); + csdp |= (mode << 16); + dma_write(csdp, CSDP(lch)); + } +} +EXPORT_SYMBOL(omap_set_dma_write_mode); + +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 &= ~0x7; + l |= mode; + dma_write(l, LCH_CTRL(lch)); } } +EXPORT_SYMBOL(omap_set_dma_channel_mode); /* Note that src_port is only for omap1 */ void omap_set_dma_src_params(int lch, int src_port, int src_amode, unsigned long src_start, int src_ei, int src_fi) { + u32 l; + if (cpu_class_is_omap1()) { - OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 2); - OMAP_DMA_CSDP_REG(lch) |= src_port << 2; + u16 w; + + w = dma_read(CSDP(lch)); + w &= ~(0x1f << 2); + w |= src_port << 2; + dma_write(w, CSDP(lch)); } - OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 12); - OMAP_DMA_CCR_REG(lch) |= src_amode << 12; + l = dma_read(CCR(lch)); + l &= ~(0x03 << 12); + l |= src_amode << 12; + dma_write(l, CCR(lch)); if (cpu_class_is_omap1()) { - OMAP1_DMA_CSSA_U_REG(lch) = src_start >> 16; - OMAP1_DMA_CSSA_L_REG(lch) = src_start; + dma_write(src_start >> 16, CSSA_U(lch)); + dma_write((u16)src_start, CSSA_L(lch)); } if (cpu_class_is_omap2()) - OMAP2_DMA_CSSA_REG(lch) = src_start; + dma_write(src_start, CSSA(lch)); - OMAP_DMA_CSEI_REG(lch) = src_ei; - OMAP_DMA_CSFI_REG(lch) = src_fi; + dma_write(src_ei, CSEI(lch)); + dma_write(src_fi, CSFI(lch)); } +EXPORT_SYMBOL(omap_set_dma_src_params); -void omap_set_dma_params(int lch, struct omap_dma_channel_params * params) +void omap_set_dma_params(int lch, struct omap_dma_channel_params *params) { omap_set_dma_transfer_params(lch, params->data_type, params->elem_count, params->frame_count, @@ -356,28 +427,37 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params * params) omap_dma_set_prio_lch(lch, params->read_prio, params->write_prio); } +EXPORT_SYMBOL(omap_set_dma_params); void omap_set_dma_src_index(int lch, int eidx, int fidx) { - if (cpu_class_is_omap2()) { - REVISIT_24XX(); + if (cpu_class_is_omap2()) return; - } - OMAP_DMA_CSEI_REG(lch) = eidx; - OMAP_DMA_CSFI_REG(lch) = fidx; + + dma_write(eidx, CSEI(lch)); + dma_write(fidx, CSFI(lch)); } +EXPORT_SYMBOL(omap_set_dma_src_index); void omap_set_dma_src_data_pack(int lch, int enable) { - OMAP_DMA_CSDP_REG(lch) &= ~(1 << 6); + u32 l; + + l = dma_read(CSDP(lch)); + l &= ~(1 << 6); if (enable) - OMAP_DMA_CSDP_REG(lch) |= (1 << 6); + l |= (1 << 6); + dma_write(l, CSDP(lch)); } +EXPORT_SYMBOL(omap_set_dma_src_data_pack); void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { unsigned int burst = 0; - OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7); + u32 l; + + l = dma_read(CSDP(lch)); + l &= ~(0x03 << 7); switch (burst_mode) { case OMAP_DMA_DATA_BURST_DIS: @@ -408,55 +488,73 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) default: BUG(); } - OMAP_DMA_CSDP_REG(lch) |= (burst << 7); + + l |= (burst << 7); + dma_write(l, CSDP(lch)); } +EXPORT_SYMBOL(omap_set_dma_src_burst_mode); /* Note that dest_port is only for OMAP1 */ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, unsigned long dest_start, int dst_ei, int dst_fi) { + u32 l; + if (cpu_class_is_omap1()) { - OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 9); - OMAP_DMA_CSDP_REG(lch) |= dest_port << 9; + l = dma_read(CSDP(lch)); + l &= ~(0x1f << 9); + l |= dest_port << 9; + dma_write(l, CSDP(lch)); } - OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 14); - OMAP_DMA_CCR_REG(lch) |= dest_amode << 14; + l = dma_read(CCR(lch)); + l &= ~(0x03 << 14); + l |= dest_amode << 14; + dma_write(l, CCR(lch)); if (cpu_class_is_omap1()) { - OMAP1_DMA_CDSA_U_REG(lch) = dest_start >> 16; - OMAP1_DMA_CDSA_L_REG(lch) = dest_start; + dma_write(dest_start >> 16, CDSA_U(lch)); + dma_write(dest_start, CDSA_L(lch)); } if (cpu_class_is_omap2()) - OMAP2_DMA_CDSA_REG(lch) = dest_start; + dma_write(dest_start, CDSA(lch)); - OMAP_DMA_CDEI_REG(lch) = dst_ei; - OMAP_DMA_CDFI_REG(lch) = dst_fi; + dma_write(dst_ei, CDEI(lch)); + dma_write(dst_fi, CDFI(lch)); } +EXPORT_SYMBOL(omap_set_dma_dest_params); void omap_set_dma_dest_index(int lch, int eidx, int fidx) { - if (cpu_class_is_omap2()) { - REVISIT_24XX(); + if (cpu_class_is_omap2()) return; - } - OMAP_DMA_CDEI_REG(lch) = eidx; - OMAP_DMA_CDFI_REG(lch) = fidx; + + dma_write(eidx, CDEI(lch)); + dma_write(fidx, CDFI(lch)); } +EXPORT_SYMBOL(omap_set_dma_dest_index); void omap_set_dma_dest_data_pack(int lch, int enable) { - OMAP_DMA_CSDP_REG(lch) &= ~(1 << 13); + u32 l; + + l = dma_read(CSDP(lch)); + l &= ~(1 << 13); if (enable) - OMAP_DMA_CSDP_REG(lch) |= 1 << 13; + l |= 1 << 13; + dma_write(l, CSDP(lch)); } +EXPORT_SYMBOL(omap_set_dma_dest_data_pack); void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { unsigned int burst = 0; - OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14); + u32 l; + + l = dma_read(CSDP(lch)); + l &= ~(0x03 << 14); switch (burst_mode) { case OMAP_DMA_DATA_BURST_DIS: @@ -486,8 +584,10 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) BUG(); return; } - OMAP_DMA_CSDP_REG(lch) |= (burst << 14); + l |= (burst << 14); + dma_write(l, CSDP(lch)); } +EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); static inline void omap_enable_channel_irq(int lch) { @@ -495,64 +595,74 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = OMAP_DMA_CSR_REG(lch); + status = dma_read(CSR(lch)); else if (cpu_class_is_omap2()) - OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); /* Enable some nice interrupts. */ - OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs; - - dma_chan[lch].flags |= OMAP_DMA_ACTIVE; + dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - OMAP_DMA_CICR_REG(lch) = 0; + dma_write(0, CICR(lch)); } void omap_enable_dma_irq(int lch, u16 bits) { dma_chan[lch].enabled_irqs |= bits; } +EXPORT_SYMBOL(omap_enable_dma_irq); void omap_disable_dma_irq(int lch, u16 bits) { dma_chan[lch].enabled_irqs &= ~bits; } +EXPORT_SYMBOL(omap_disable_dma_irq); static inline void enable_lnk(int lch) { + u32 l; + + l = dma_read(CLNK_CTRL(lch)); + if (cpu_class_is_omap1()) - OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 14); + l &= ~(1 << 14); /* Set the ENABLE_LNK bits */ if (dma_chan[lch].next_lch != -1) - OMAP_DMA_CLNK_CTRL_REG(lch) = - dma_chan[lch].next_lch | (1 << 15); + l = dma_chan[lch].next_lch | (1 << 15); #ifndef CONFIG_ARCH_OMAP1 - if (dma_chan[lch].next_linked_ch != -1) - OMAP_DMA_CLNK_CTRL_REG(lch) = - dma_chan[lch].next_linked_ch | (1 << 15); + if (cpu_class_is_omap2()) + if (dma_chan[lch].next_linked_ch != -1) + l = dma_chan[lch].next_linked_ch | (1 << 15); #endif + + dma_write(l, CLNK_CTRL(lch)); } static inline void disable_lnk(int lch) { + u32 l; + + l = dma_read(CLNK_CTRL(lch)); + /* Disable interrupts */ if (cpu_class_is_omap1()) { - OMAP_DMA_CICR_REG(lch) = 0; + dma_write(0, CICR(lch)); /* Set the STOP_LNK bit */ - OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14; + l |= 1 << 14; } if (cpu_class_is_omap2()) { omap_disable_channel_irq(lch); /* Clear the ENABLE_LNK bit */ - OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15); + l &= ~(1 << 15); } + dma_write(l, CLNK_CTRL(lch)); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -563,13 +673,13 @@ static inline void omap2_enable_irq_lch(int lch) if (!cpu_class_is_omap2()) return; - val = omap_readl(OMAP_DMA4_IRQENABLE_L0); + val = dma_read(IRQENABLE_L0); val |= 1 << lch; - omap_writel(val, OMAP_DMA4_IRQENABLE_L0); + dma_write(val, IRQENABLE_L0); } int omap_request_dma(int dev_id, const char *dev_name, - void (* callback)(int lch, u16 ch_status, void *data), + void (*callback)(int lch, u16 ch_status, void *data), void *data, int *dma_ch_out) { int ch, free_ch = -1; @@ -602,10 +712,14 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->dev_name = dev_name; chan->callback = callback; chan->data = data; + #ifndef CONFIG_ARCH_OMAP1 - chan->chain_id = -1; - chan->next_linked_ch = -1; + if (cpu_class_is_omap2()) { + chan->chain_id = -1; + chan->next_linked_ch = -1; + } #endif + chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; if (cpu_class_is_omap1()) @@ -620,26 +734,28 @@ int omap_request_dma(int dev_id, const char *dev_name, set_gdma_dev(free_ch + 1, dev_id); dev_id = free_ch + 1; } - /* Disable the 1510 compatibility mode and set the sync device - * id. */ - OMAP_DMA_CCR_REG(free_ch) = dev_id | (1 << 10); + /* + * Disable the 1510 compatibility mode and set the sync device + * id. + */ + dma_write(dev_id | (1 << 10), CCR(free_ch)); } else if (cpu_is_omap730() || cpu_is_omap15xx()) { - OMAP_DMA_CCR_REG(free_ch) = dev_id; + 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 */ - OMAP_DMA_CSR_REG(free_ch) = OMAP2_DMA_CSR_CLEAR_MASK; - omap_writel(1 << free_ch, OMAP_DMA4_IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch)); + dma_write(1 << free_ch, IRQSTATUS_L0); } *dma_ch_out = free_ch; return 0; } +EXPORT_SYMBOL(omap_request_dma); void omap_free_dma(int lch) { @@ -647,11 +763,12 @@ void omap_free_dma(int lch) spin_lock_irqsave(&dma_chan_lock, flags); if (dma_chan[lch].dev_id == -1) { - printk("omap_dma: trying to free nonallocated DMA channel %d\n", + pr_err("omap_dma: trying to free unallocated DMA channel %d\n", lch); spin_unlock_irqrestore(&dma_chan_lock, flags); return; } + dma_chan[lch].dev_id = -1; dma_chan[lch].next_lch = -1; dma_chan[lch].callback = NULL; @@ -659,30 +776,31 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - OMAP_DMA_CICR_REG(lch) = 0; + dma_write(0, CICR(lch)); /* Make sure the DMA transfer is stopped. */ - OMAP_DMA_CCR_REG(lch) = 0; + dma_write(0, CCR(lch)); } if (cpu_class_is_omap2()) { u32 val; /* Disable interrupts */ - val = omap_readl(OMAP_DMA4_IRQENABLE_L0); + val = dma_read(IRQENABLE_L0); val &= ~(1 << lch); - omap_writel(val, OMAP_DMA4_IRQENABLE_L0); + dma_write(val, IRQENABLE_L0); /* Clear the CSR register and IRQ status register */ - OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; - omap_writel(1 << lch, OMAP_DMA4_IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); + dma_write(1 << lch, IRQSTATUS_L0); /* Disable all DMA interrupts for the channel. */ - OMAP_DMA_CICR_REG(lch) = 0; + dma_write(0, CICR(lch)); /* Make sure the DMA transfer is stopped. */ - OMAP_DMA_CCR_REG(lch) = 0; + dma_write(0, CCR(lch)); omap_clear_dma(lch); } } +EXPORT_SYMBOL(omap_free_dma); /** * @brief omap_dma_set_global_params : Set global priority settings for dma @@ -710,7 +828,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg = (arb_rate & 0xff) << 16; reg |= (0xff & max_fifo_depth); - omap_writel(reg, OMAP_DMA4_GCR_REG); + dma_write(reg, GCR); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -727,20 +845,21 @@ int omap_dma_set_prio_lch(int lch, unsigned char read_prio, unsigned char write_prio) { - u32 w; + u32 l; - if (unlikely((lch < 0 || lch >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((lch < 0 || lch >= dma_lch_count))) { printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - w = OMAP_DMA_CCR_REG(lch); - w &= ~((1 << 6) | (1 << 26)); + l = dma_read(CCR(lch)); + l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx()) - w |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); + l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else - w |= ((read_prio & 0x1) << 6); + l |= ((read_prio & 0x1) << 6); + + dma_write(l, CCR(lch)); - OMAP_DMA_CCR_REG(lch) = w; return 0; } EXPORT_SYMBOL(omap_dma_set_prio_lch); @@ -756,28 +875,34 @@ void omap_clear_dma(int lch) local_irq_save(flags); if (cpu_class_is_omap1()) { - int status; - OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN; + u32 l; + + l = dma_read(CCR(lch)); + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); /* Clear pending interrupts */ - status = OMAP_DMA_CSR_REG(lch); + l = dma_read(CSR(lch)); } if (cpu_class_is_omap2()) { int i; - u32 lch_base = OMAP_DMA4_BASE + lch * 0x60 + 0x80; + void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch); for (i = 0; i < 0x44; i += 4) - omap_writel(0, lch_base + i); + __raw_writel(0, lch_base + i); } local_irq_restore(flags); } +EXPORT_SYMBOL(omap_clear_dma); void omap_start_dma(int lch) { + u32 l; + if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch; - char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; dma_chan_link_map[lch] = 1; /* Set the link register of the first channel */ @@ -801,27 +926,34 @@ void omap_start_dma(int lch) } while (next_lch != -1); } else if (cpu_class_is_omap2()) { /* Errata: Need to write lch even if not using chaining */ - OMAP_DMA_CLNK_CTRL_REG(lch) = lch; + dma_write(lch, CLNK_CTRL(lch)); } omap_enable_channel_irq(lch); - /* Errata: On ES2.0 BUFFERING disable must be set. - * This will always fail on ES1.0 */ - if (cpu_is_omap24xx()) { - OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN; - } + l = dma_read(CCR(lch)); - OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN; + /* + * Errata: On ES2.0 BUFFERING disable must be set. + * This will always fail on ES1.0 + */ + if (cpu_is_omap24xx()) + l |= OMAP_DMA_CCR_EN; + + l |= OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } +EXPORT_SYMBOL(omap_start_dma); void omap_stop_dma(int lch) { + u32 l; + if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch = lch; - char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); do { @@ -842,18 +974,22 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - OMAP_DMA_CICR_REG(lch) = 0; + dma_write(0, CICR(lch)); + + l = dma_read(CCR(lch)); + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR(lch)); - OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN; dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } +EXPORT_SYMBOL(omap_stop_dma); /* * Allows changing the DMA callback function or data. This may be needed if * the driver shares a single DMA channel for multiple dma triggers. */ int omap_set_dma_callback(int lch, - void (* callback)(int lch, u16 ch_status, void *data), + void (*callback)(int lch, u16 ch_status, void *data), void *data) { unsigned long flags; @@ -873,6 +1009,7 @@ int omap_set_dma_callback(int lch, return 0; } +EXPORT_SYMBOL(omap_set_dma_callback); /* * Returns current physical source address for the given DMA channel. @@ -886,15 +1023,24 @@ dma_addr_t omap_get_dma_src_pos(int lch) { dma_addr_t offset = 0; - if (cpu_class_is_omap1()) - offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) | - (OMAP1_DMA_CSSA_U_REG(lch) << 16)); + if (cpu_is_omap15xx()) + offset = dma_read(CPC(lch)); + else + offset = dma_read(CSAC(lch)); - if (cpu_class_is_omap2()) - offset = OMAP_DMA_CSAC_REG(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 (cpu_class_is_omap1()) + offset |= (dma_read(CSSA_U(lch)) << 16); return offset; } +EXPORT_SYMBOL(omap_get_dma_src_pos); /* * Returns current physical destination address for the given DMA channel. @@ -908,25 +1054,30 @@ dma_addr_t omap_get_dma_dst_pos(int lch) { dma_addr_t offset = 0; - if (cpu_class_is_omap1()) - offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) | - (OMAP1_DMA_CDSA_U_REG(lch) << 16)); + if (cpu_is_omap15xx()) + offset = dma_read(CPC(lch)); + else + offset = dma_read(CDAC(lch)); - if (cpu_class_is_omap2()) - offset = OMAP_DMA_CDAC_REG(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)); + + if (cpu_class_is_omap1()) + offset |= (dma_read(CDSA_U(lch)) << 16); return offset; } +EXPORT_SYMBOL(omap_get_dma_dst_pos); -/* - * Returns current source transfer counting for the given DMA channel. - * Can be used to monitor the progress of a transfer inside a block. - * It must be called with disabled interrupts. - */ -int omap_get_dma_src_addr_counter(int lch) +int omap_get_dma_active_status(int lch) { - return (dma_addr_t) OMAP_DMA_CSAC_REG(lch); + return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0; } +EXPORT_SYMBOL(omap_get_dma_active_status); int omap_dma_running(void) { @@ -938,7 +1089,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (OMAP_DMA_CCR_REG(lch) & OMAP_DMA_CCR_EN) + if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -949,7 +1100,7 @@ int omap_dma_running(void) * For this DMA link to start, you still need to start (see omap_start_dma) * the first one. That will fire up the entire queue. */ -void omap_dma_link_lch (int lch_head, int lch_queue) +void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -966,11 +1117,12 @@ void omap_dma_link_lch (int lch_head, int lch_queue) dma_chan[lch_head].next_lch = lch_queue; } +EXPORT_SYMBOL(omap_dma_link_lch); /* * Once the DMA queue is stopped, we can destroy it. */ -void omap_dma_unlink_lch (int lch_head, int lch_queue) +void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -985,7 +1137,6 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue) dump_stack(); } - if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) || (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) { printk(KERN_ERR "omap_dma: You need to stop the DMA channels " @@ -995,12 +1146,15 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue) dma_chan[lch_head].next_lch = -1; } +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) { - u32 w; + u32 l; /* Check if this is the first link in chain */ if (dma_chan[lch_head].next_linked_ch == -1) { @@ -1020,15 +1174,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - w = OMAP_DMA_CLNK_CTRL_REG(lch_head); - w &= ~(0x1f); - w |= lch_queue; - OMAP_DMA_CLNK_CTRL_REG(lch_head) = w; + l = dma_read(CLNK_CTRL(lch_head)); + l &= ~(0x1f); + l |= lch_queue; + dma_write(l, CLNK_CTRL(lch_head)); - w = OMAP_DMA_CLNK_CTRL_REG(lch_queue); - w &= ~(0x1f); - w |= (dma_chan[lch_queue].next_linked_ch); - OMAP_DMA_CLNK_CTRL_REG(lch_queue) = w; + l = dma_read(CLNK_CTRL(lch_queue)); + l &= ~(0x1f); + l |= (dma_chan[lch_queue].next_linked_ch); + dma_write(l, CLNK_CTRL(lch_queue)); } /** @@ -1063,7 +1217,7 @@ int omap_request_dma_chain(int dev_id, const char *dev_name, } if (unlikely((no_of_chans < 1 - || no_of_chans > OMAP_LOGICAL_DMA_CH_COUNT))) { + || no_of_chans > dma_lch_count))) { printk(KERN_ERR "Invalid Number of channels requested\n"); return -EINVAL; } @@ -1118,6 +1272,7 @@ int omap_request_dma_chain(int dev_id, const char *dev_name, for (i = 0; i < (no_of_chans - 1); i++) create_dma_lch_chain(channels[i], channels[i + 1]); } + return 0; } EXPORT_SYMBOL(omap_request_dma_chain); @@ -1140,7 +1295,7 @@ int omap_modify_dma_chain_params(int chain_id, /* Check for input params */ if (unlikely((chain_id < 0 - || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1160,6 +1315,7 @@ int omap_modify_dma_chain_params(int chain_id, */ omap_set_dma_params(channels[i], ¶ms); } + return 0; } EXPORT_SYMBOL(omap_modify_dma_chain_params); @@ -1178,7 +1334,7 @@ int omap_free_dma_chain(int chain_id) u32 i; /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1203,6 +1359,7 @@ int omap_free_dma_chain(int chain_id) dma_linked_lch[chain_id].linked_dmach_q = NULL; dma_linked_lch[chain_id].chain_mode = -1; dma_linked_lch[chain_id].chain_state = -1; + return (0); } EXPORT_SYMBOL(omap_free_dma_chain); @@ -1218,7 +1375,7 @@ EXPORT_SYMBOL(omap_free_dma_chain); int omap_dma_chain_status(int chain_id) { /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1233,6 +1390,7 @@ int omap_dma_chain_status(int chain_id) if (OMAP_DMA_CHAIN_QEMPTY(chain_id)) return OMAP_DMA_CHAIN_INACTIVE; + return OMAP_DMA_CHAIN_ACTIVE; } EXPORT_SYMBOL(omap_dma_chain_status); @@ -1255,11 +1413,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, int elem_count, int frame_count, void *callbk_data) { int *channels; - u32 w, lch; + u32 l, lch; int start_dma = 0; - /* if buffer size is less than 1 then there is - * no use of starting the chain */ + /* + * if buffer size is less than 1 then there is + * no use of starting the chain + */ if (elem_count < 1) { printk(KERN_ERR "Invalid buffer size\n"); return -EINVAL; @@ -1267,7 +1427,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Check for input params */ if (unlikely((chain_id < 0 - || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1296,20 +1456,24 @@ 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) - OMAP2_DMA_CSSA_REG(lch) = src_start; + dma_write(src_start, CSSA(lch)); if (dest_start != 0) - OMAP2_DMA_CDSA_REG(lch) = dest_start; + dma_write(dest_start, CDSA(lch)); /* Write the buffer size */ - OMAP_DMA_CEN_REG(lch) = elem_count; - OMAP_DMA_CFN_REG(lch) = frame_count; + dma_write(elem_count, CEN(lch)); + dma_write(frame_count, CFN(lch)); - /* If the chain is dynamically linked, - * then we may have to start the chain if its not active */ + /* + * If the chain is dynamically linked, + * then we may have to start the chain if its not active + */ if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) { - /* In Dynamic chain, if the chain is not started, - * queue the channel */ + /* + * In Dynamic chain, if the chain is not started, + * queue the channel + */ if (dma_linked_lch[chain_id].chain_state == DMA_CHAIN_NOTSTARTED) { /* Enable the link in previous channel */ @@ -1319,8 +1483,10 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, dma_chan[lch].state = DMA_CH_QUEUED; } - /* Chain is already started, make sure its active, - * if not then start the chain */ + /* + * Chain is already started, make sure its active, + * if not then start the chain + */ else { start_dma = 1; @@ -1329,8 +1495,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) & (OMAP_DMA_CCR_REG - (dma_chan[lch].prev_linked_ch)))) { + if (0 == ((1 << 7) & 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"); @@ -1346,27 +1512,28 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - w = OMAP_DMA_CCR_REG(lch); + l = dma_read(CCR(lch)); - if ((0 == (w & (1 << 24)))) - w &= ~(1 << 25); + if ((0 == (l & (1 << 24)))) + l &= ~(1 << 25); else - w |= (1 << 25); + l |= (1 << 25); if (start_dma == 1) { - if (0 == (w & (1 << 7))) { - w |= (1 << 7); + if (0 == (l & (1 << 7))) { + l |= (1 << 7); dma_chan[lch].state = DMA_CH_STARTED; pr_debug("starting %d\n", lch); - OMAP_DMA_CCR_REG(lch) = w; + dma_write(l, CCR(lch)); } else start_dma = 0; } else { - if (0 == (w & (1 << 7))) - OMAP_DMA_CCR_REG(lch) = w; + if (0 == (l & (1 << 7))) + dma_write(l, CCR(lch)); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } } + return 0; } EXPORT_SYMBOL(omap_dma_chain_a_transfer); @@ -1382,9 +1549,9 @@ EXPORT_SYMBOL(omap_dma_chain_a_transfer); int omap_start_dma_chain_transfers(int chain_id) { int *channels; - u32 w, i; + u32 l, i; - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1406,18 +1573,19 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - w = OMAP_DMA_CCR_REG(channels[0]); - w |= (1 << 7); + l = 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; - if ((0 == (w & (1 << 24)))) - w &= ~(1 << 25); + if ((0 == (l & (1 << 24)))) + l &= ~(1 << 25); else - w |= (1 << 25); - OMAP_DMA_CCR_REG(channels[0]) = w; + l |= (1 << 25); + dma_write(l, CCR(channels[0])); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; + return 0; } EXPORT_SYMBOL(omap_start_dma_chain_transfers); @@ -1433,11 +1601,11 @@ EXPORT_SYMBOL(omap_start_dma_chain_transfers); int omap_stop_dma_chain_transfers(int chain_id) { int *channels; - u32 w, i; + u32 l, i; u32 sys_cf; /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1449,21 +1617,22 @@ int omap_stop_dma_chain_transfers(int chain_id) } channels = dma_linked_lch[chain_id].linked_dmach_q; - /* DMA Errata: + /* + * DMA Errata: * Special programming model needed to disable DMA before end of block */ - sys_cf = omap_readl(OMAP_DMA4_OCP_SYSCONFIG); - w = sys_cf; + sys_cf = dma_read(OCP_SYSCONFIG); + l = sys_cf; /* Middle mode reg set no Standby */ - w &= ~((1 << 12)|(1 << 13)); - omap_writel(w, OMAP_DMA4_OCP_SYSCONFIG); + l &= ~((1 << 12)|(1 << 13)); + dma_write(l, OCP_SYSCONFIG); for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - w = OMAP_DMA_CCR_REG(channels[i]); - w &= ~(1 << 7); - OMAP_DMA_CCR_REG(channels[i]) = w; + l = dma_read(CCR(channels[i])); + l &= ~(1 << 7); + dma_write(l, CCR(channels[i])); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1476,7 +1645,8 @@ int omap_stop_dma_chain_transfers(int chain_id) OMAP_DMA_CHAIN_QINIT(chain_id); /* Errata - put in the old value */ - omap_writel(sys_cf, OMAP_DMA4_OCP_SYSCONFIG); + dma_write(sys_cf, OCP_SYSCONFIG); + return 0; } EXPORT_SYMBOL(omap_stop_dma_chain_transfers); @@ -1499,7 +1669,7 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) int *channels; /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1517,8 +1687,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 = OMAP2_DMA_CCEN_REG(lch); - *fi = OMAP2_DMA_CCFN_REG(lch); + *ei = dma_read(CCEN(lch)); + *fi = dma_read(CCFN(lch)); return 0; } @@ -1539,7 +1709,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) int *channels; /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1555,7 +1725,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 (OMAP_DMA_CDAC_REG(lch)); + return dma_read(CDAC(lch)); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1573,7 +1743,7 @@ int omap_get_dma_chain_src_pos(int chain_id) int *channels; /* Check for input params */ - if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { + if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { printk(KERN_ERR "Invalid chain id\n"); return -EINVAL; } @@ -1589,10 +1759,10 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return (OMAP_DMA_CSAC_REG(lch)); + return dma_read(CSAC(lch)); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); -#endif +#endif /* ifndef CONFIG_ARCH_OMAP1 */ /*----------------------------------------------------------------------------*/ @@ -1600,13 +1770,13 @@ EXPORT_SYMBOL(omap_get_dma_chain_src_pos); static int omap1_dma_handle_ch(int ch) { - u16 csr; + u32 csr; if (enable_1510_mode && ch >= 6) { csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = OMAP_DMA_CSR_REG(ch); + csr = dma_read(CSR(ch)); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -1628,6 +1798,7 @@ static int omap1_dma_handle_ch(int ch) dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, csr, dma_chan[ch].data); + return 1; } @@ -1658,12 +1829,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = OMAP_DMA_CSR_REG(ch); + u32 status = dma_read(CSR(ch)); if (!status) { if (printk_ratelimit()) - printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0); + printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", + ch); + dma_write(1 << ch, IRQSTATUS_L0); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -1686,14 +1858,14 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK; - omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch)); + dma_write(1 << ch, IRQSTATUS_L0); /* 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 (OMAP_DMA_CLNK_CTRL_REG(ch) & (1 << 15)) + if (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 == @@ -1703,13 +1875,13 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = OMAP_DMA_CSR_REG(ch); + status = dma_read(CSR(ch)); } if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); - OMAP_DMA_CSR_REG(ch) = status; + dma_write(status, CSR(ch)); return 0; } @@ -1720,13 +1892,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val; int i; - val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); + val = dma_read(IRQSTATUS_L0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) { + for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) omap2_dma_handle_ch(i); val >>= 1; @@ -1750,7 +1922,7 @@ static struct irqaction omap24xx_dma_irq; static struct lcd_dma_info { spinlock_t lock; int reserved; - void (* callback)(u16 status, void *data); + void (*callback)(u16 status, void *data); void *cb_data; int active; @@ -1772,6 +1944,7 @@ void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, lcd_dma.xres = fb_xres; lcd_dma.yres = fb_yres; } +EXPORT_SYMBOL(omap_set_lcd_dma_b1); void omap_set_lcd_dma_src_port(int port) { @@ -1782,12 +1955,13 @@ void omap_set_lcd_dma_ext_controller(int external) { lcd_dma.ext_ctrl = external; } +EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); void omap_set_lcd_dma_single_transfer(int single) { lcd_dma.single_transfer = single; } - +EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); void omap_set_lcd_dma_b1_rotation(int rotate) { @@ -1798,6 +1972,7 @@ void omap_set_lcd_dma_b1_rotation(int rotate) } lcd_dma.rotate = rotate; } +EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); void omap_set_lcd_dma_b1_mirror(int mirror) { @@ -1807,6 +1982,7 @@ void omap_set_lcd_dma_b1_mirror(int mirror) } lcd_dma.mirror = mirror; } +EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); void omap_set_lcd_dma_b1_vxres(unsigned long vxres) { @@ -1817,6 +1993,7 @@ void omap_set_lcd_dma_b1_vxres(unsigned long vxres) } lcd_dma.vxres = vxres; } +EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) { @@ -1827,6 +2004,7 @@ void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) lcd_dma.xscale = xscale; lcd_dma.yscale = yscale; } +EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); static void set_b1_regs(void) { @@ -1857,8 +2035,11 @@ static void set_b1_regs(void) xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; BUG_ON(vxres < lcd_dma.xres); -#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es) + +#define PIXADDR(x, y) (lcd_dma.addr + \ + ((y) * vxres * yscale + (x) * xscale) * es) #define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) + switch (lcd_dma.rotate) { case 0: if (!lcd_dma.mirror) { @@ -1867,8 +2048,8 @@ static void set_b1_regs(void) /* 1510 DMA requires the bottom address to be 2 more * than the actual last memory access location. */ if (omap_dma_in_1510_mode() && - lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) - bottom += 2; + lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) + bottom += 2; ei = PIXSTEP(0, 0, 1, 0); fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); } else { @@ -1995,7 +2176,7 @@ static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -int omap_request_lcd_dma(void (* callback)(u16 status, void *data), +int omap_request_lcd_dma(void (*callback)(u16 status, void *data), void *data) { spin_lock_irq(&lcd_dma.lock); @@ -2021,6 +2202,7 @@ int omap_request_lcd_dma(void (* callback)(u16 status, void *data), return 0; } +EXPORT_SYMBOL(omap_request_lcd_dma); void omap_free_lcd_dma(void) { @@ -2037,12 +2219,14 @@ void omap_free_lcd_dma(void) lcd_dma.reserved = 0; spin_unlock(&lcd_dma.lock); } +EXPORT_SYMBOL(omap_free_lcd_dma); void omap_enable_lcd_dma(void) { u16 w; - /* Set the Enable bit only if an external controller is + /* + * Set the Enable bit only if an external controller is * connected. Otherwise the OMAP internal controller will * start the transfer when it gets enabled. */ @@ -2059,6 +2243,7 @@ void omap_enable_lcd_dma(void) w |= 1 << 7; omap_writew(w, OMAP1610_DMA_LCD_CCR); } +EXPORT_SYMBOL(omap_enable_lcd_dma); void omap_setup_lcd_dma(void) { @@ -2074,16 +2259,18 @@ void omap_setup_lcd_dma(void) u16 w; w = omap_readw(OMAP1610_DMA_LCD_CCR); - /* If DMA was already active set the end_prog bit to have + /* + * If DMA was already active set the end_prog bit to have * the programmed register set loaded into the active * register set. */ w |= 1 << 11; /* End_prog */ if (!lcd_dma.single_transfer) - w |= (3 << 8); /* Auto_init, repeat */ + w |= (3 << 8); /* Auto_init, repeat */ omap_writew(w, OMAP1610_DMA_LCD_CCR); } } +EXPORT_SYMBOL(omap_setup_lcd_dma); void omap_stop_lcd_dma(void) { @@ -2101,6 +2288,7 @@ void omap_stop_lcd_dma(void) w &= ~(1 << 8); omap_writew(w, OMAP1610_DMA_LCD_CTRL); } +EXPORT_SYMBOL(omap_stop_lcd_dma); /*----------------------------------------------------------------------------*/ @@ -2108,27 +2296,55 @@ static int __init omap_init_dma(void) { int ch, r; + if (cpu_class_is_omap1()) { + omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP1_DMA_BASE); + dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap24xx()) { + omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP24XX_DMA4_BASE); + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap34xx()) { + omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP34XX_DMA4_BASE); + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else { + pr_err("DMA init failed for unsupported omap\n"); + return -ENODEV; + } + + dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, + GFP_KERNEL); + if (!dma_chan) + return -ENOMEM; + + if (cpu_class_is_omap2()) { + dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * + dma_lch_count, GFP_KERNEL); + if (!dma_linked_lch) { + kfree(dma_chan); + return -ENOMEM; + } + } + 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_omap730()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", - omap_readw(OMAP_DMA_HW_ID)); + dma_read(HW_ID)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - (omap_readw(OMAP_DMA_CAPS_0_U) << 16) | - omap_readw(OMAP_DMA_CAPS_0_L), - (omap_readw(OMAP_DMA_CAPS_1_U) << 16) | - omap_readw(OMAP_DMA_CAPS_1_L), - omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3), - omap_readw(OMAP_DMA_CAPS_4)); + (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 = omap_readw(OMAP_DMA_GSCR); + w = dma_read(GSCR); w |= 1 << 3; - omap_writew(w, OMAP_DMA_GSCR); + dma_write(w, GSCR); dma_chan_count = 16; } else dma_chan_count = 9; @@ -2141,19 +2357,17 @@ static int __init omap_init_dma(void) omap_writew(w, OMAP1610_DMA_LCD_CTRL); } } else if (cpu_class_is_omap2()) { - u8 revision = omap_readb(OMAP_DMA4_REVISION); + u8 revision = dma_read(REVISION) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); - dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT; + dma_chan_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; } else { dma_chan_count = 0; return 0; } - memset(&lcd_dma, 0, sizeof(lcd_dma)); spin_lock_init(&lcd_dma.lock); spin_lock_init(&dma_chan_lock); - memset(&dma_chan, 0, sizeof(dma_chan)); for (ch = 0; ch < dma_chan_count; ch++) { omap_clear_dma(ch); @@ -2164,8 +2378,10 @@ static int __init omap_init_dma(void) continue; if (cpu_class_is_omap1()) { - /* request_irq() doesn't like dev_id (ie. ch) being - * zero, so we have to kludge around this. */ + /* + * 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)); @@ -2210,48 +2426,4 @@ static int __init omap_init_dma(void) arch_initcall(omap_init_dma); -EXPORT_SYMBOL(omap_get_dma_src_pos); -EXPORT_SYMBOL(omap_get_dma_dst_pos); -EXPORT_SYMBOL(omap_get_dma_src_addr_counter); -EXPORT_SYMBOL(omap_clear_dma); -EXPORT_SYMBOL(omap_set_dma_priority); -EXPORT_SYMBOL(omap_request_dma); -EXPORT_SYMBOL(omap_free_dma); -EXPORT_SYMBOL(omap_start_dma); -EXPORT_SYMBOL(omap_stop_dma); -EXPORT_SYMBOL(omap_set_dma_callback); -EXPORT_SYMBOL(omap_enable_dma_irq); -EXPORT_SYMBOL(omap_disable_dma_irq); - -EXPORT_SYMBOL(omap_set_dma_transfer_params); -EXPORT_SYMBOL(omap_set_dma_color_mode); -EXPORT_SYMBOL(omap_set_dma_write_mode); - -EXPORT_SYMBOL(omap_set_dma_src_params); -EXPORT_SYMBOL(omap_set_dma_src_index); -EXPORT_SYMBOL(omap_set_dma_src_data_pack); -EXPORT_SYMBOL(omap_set_dma_src_burst_mode); - -EXPORT_SYMBOL(omap_set_dma_dest_params); -EXPORT_SYMBOL(omap_set_dma_dest_index); -EXPORT_SYMBOL(omap_set_dma_dest_data_pack); -EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); - -EXPORT_SYMBOL(omap_set_dma_params); - -EXPORT_SYMBOL(omap_dma_link_lch); -EXPORT_SYMBOL(omap_dma_unlink_lch); - -EXPORT_SYMBOL(omap_request_lcd_dma); -EXPORT_SYMBOL(omap_free_lcd_dma); -EXPORT_SYMBOL(omap_enable_lcd_dma); -EXPORT_SYMBOL(omap_setup_lcd_dma); -EXPORT_SYMBOL(omap_stop_lcd_dma); -EXPORT_SYMBOL(omap_set_lcd_dma_b1); -EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); -EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 302ad8dff2cb..f22506af0e67 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -38,34 +38,113 @@ #include <asm/arch/irqs.h> /* register offsets */ -#define OMAP_TIMER_ID_REG 0x00 -#define OMAP_TIMER_OCP_CFG_REG 0x10 -#define OMAP_TIMER_SYS_STAT_REG 0x14 -#define OMAP_TIMER_STAT_REG 0x18 -#define OMAP_TIMER_INT_EN_REG 0x1c -#define OMAP_TIMER_WAKEUP_EN_REG 0x20 -#define OMAP_TIMER_CTRL_REG 0x24 -#define OMAP_TIMER_COUNTER_REG 0x28 -#define OMAP_TIMER_LOAD_REG 0x2c -#define OMAP_TIMER_TRIGGER_REG 0x30 -#define OMAP_TIMER_WRITE_PEND_REG 0x34 -#define OMAP_TIMER_MATCH_REG 0x38 -#define OMAP_TIMER_CAPTURE_REG 0x3c -#define OMAP_TIMER_IF_CTRL_REG 0x40 - -/* timer control reg bits */ -#define OMAP_TIMER_CTRL_GPOCFG (1 << 14) -#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13) -#define OMAP_TIMER_CTRL_PT (1 << 12) -#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8) -#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8) -#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8) -#define OMAP_TIMER_CTRL_SCPWM (1 << 7) -#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */ -#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */ -#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */ -#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */ -#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */ +#define _OMAP_TIMER_ID_OFFSET 0x00 +#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10 +#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14 +#define _OMAP_TIMER_STAT_OFFSET 0x18 +#define _OMAP_TIMER_INT_EN_OFFSET 0x1c +#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20 +#define _OMAP_TIMER_CTRL_OFFSET 0x24 +#define OMAP_TIMER_CTRL_GPOCFG (1 << 14) +#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13) +#define OMAP_TIMER_CTRL_PT (1 << 12) +#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8) +#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8) +#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8) +#define OMAP_TIMER_CTRL_SCPWM (1 << 7) +#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */ +#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */ +#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */ +#define OMAP_TIMER_CTRL_POSTED (1 << 2) +#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */ +#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */ +#define _OMAP_TIMER_COUNTER_OFFSET 0x28 +#define _OMAP_TIMER_LOAD_OFFSET 0x2c +#define _OMAP_TIMER_TRIGGER_OFFSET 0x30 +#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34 +#define WP_NONE 0 /* no write pending bit */ +#define WP_TCLR (1 << 0) +#define WP_TCRR (1 << 1) +#define WP_TLDR (1 << 2) +#define WP_TTGR (1 << 3) +#define WP_TMAR (1 << 4) +#define WP_TPIR (1 << 5) +#define WP_TNIR (1 << 6) +#define WP_TCVR (1 << 7) +#define WP_TOCR (1 << 8) +#define WP_TOWR (1 << 9) +#define _OMAP_TIMER_MATCH_OFFSET 0x38 +#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c +#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40 +#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */ +#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */ +#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */ +#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */ +#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */ +#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */ + +/* register offsets with the write pending bit encoded */ +#define WPSHIFT 16 + +#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \ + | (WP_TCLR << WPSHIFT)) + +#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \ + | (WP_TCRR << WPSHIFT)) + +#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \ + | (WP_TLDR << WPSHIFT)) + +#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \ + | (WP_TTGR << WPSHIFT)) + +#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \ + | (WP_TMAR << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \ + | (WP_TPIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \ + | (WP_TNIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \ + | (WP_TCVR << WPSHIFT)) + +#define OMAP_TIMER_TICK_INT_MASK_SET_REG \ + (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT)) + +#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ + (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) struct omap_dm_timer { unsigned long phys_base; @@ -76,6 +155,7 @@ struct omap_dm_timer { void __iomem *io_base; unsigned reserved:1; unsigned enabled:1; + unsigned posted:1; }; #ifdef CONFIG_ARCH_OMAP1 @@ -181,16 +261,34 @@ static struct clk **dm_source_clocks; static spinlock_t dm_timer_lock; -static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) +/* + * Reads timer registers in posted and non-posted mode. The posted mode bit + * is encoded in reg. Note that in posted mode write pending bit must be + * checked. Otherwise a read of a non completed write will produce an error. + */ +static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) { - return readl(timer->io_base + reg); + if (timer->posted) + while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) + & (reg >> WPSHIFT)) + cpu_relax(); + return readl(timer->io_base + (reg & 0xff)); } -static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) +/* + * Writes timer registers in posted and non-posted mode. The posted mode bit + * is encoded in reg. Note that in posted mode the write pending bit must be + * checked. Otherwise a write on a register which has a pending write will be + * lost. + */ +static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, + u32 value) { - writel(value, timer->io_base + reg); - while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG)) - ; + if (timer->posted) + while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff)) + & (reg >> WPSHIFT)) + cpu_relax(); + writel(value, timer->io_base + (reg & 0xff)); } static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) @@ -217,17 +315,23 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) } omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); - /* Set to smart-idle mode */ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); - l |= 0x02 << 3; - - if (cpu_class_is_omap2() && timer == &dm_timers[0]) { - /* Enable wake-up only for GPT1 on OMAP2 CPUs*/ + l |= 0x02 << 3; /* Set to smart-idle mode */ + l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ + + /* + * Enable wake-up only for GPT1 on OMAP2 CPUs. + * FIXME: All timers should have wake-up enabled and clear + * PRCM status. + */ + if (cpu_class_is_omap2() && (timer == &dm_timers[0])) l |= 1 << 2; - /* Non-posted mode */ - omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0); - } omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); + + /* Match hardware reset default of posted mode */ + omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, + OMAP_TIMER_CTRL_POSTED); + timer->posted = 1; } static void omap_dm_timer_prepare(struct omap_dm_timer *timer) @@ -434,9 +538,32 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, l &= ~OMAP_TIMER_CTRL_AR; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + + /* REVISIT: hw feature, ttgr overtaking tldr? */ + while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))) + cpu_relax(); + omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } +/* Optimized set_load which removes costly spin wait in timer_start */ +void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, + unsigned int load) +{ + u32 l; + + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + if (autoreload) + l |= OMAP_TIMER_CTRL_AR; + else + l &= ~OMAP_TIMER_CTRL_AR; + l |= OMAP_TIMER_CTRL_ST; + + omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); + omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); +} + void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match) { @@ -451,7 +578,6 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); } - void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger) { diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 9cf83c4da9fa..c7f74064696c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -15,95 +15,66 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/platform_device.h> #include <linux/wait.h> #include <linux/completion.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/delay.h> - -#include <asm/io.h> -#include <asm/irq.h> +#include <linux/io.h> #include <asm/arch/dma.h> -#include <asm/arch/mux.h> -#include <asm/arch/irqs.h> -#include <asm/arch/dsp_common.h> #include <asm/arch/mcbsp.h> -#ifdef CONFIG_MCBSP_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) do { } while (0) -#endif - -struct omap_mcbsp { - u32 io_base; - u8 id; - u8 free; - omap_mcbsp_word_length rx_word_length; - omap_mcbsp_word_length tx_word_length; - - omap_mcbsp_io_type_t io_type; /* IRQ or poll */ - /* IRQ based TX/RX */ - int rx_irq; - int tx_irq; - - /* DMA stuff */ - u8 dma_rx_sync; - short dma_rx_lch; - u8 dma_tx_sync; - short dma_tx_lch; - - /* Completion queues */ - struct completion tx_irq_completion; - struct completion rx_irq_completion; - struct completion tx_dma_completion; - struct completion rx_dma_completion; - - spinlock_t lock; -}; - static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; -#ifdef CONFIG_ARCH_OMAP1 -static struct clk *mcbsp_dsp_ck = 0; -static struct clk *mcbsp_api_ck = 0; -static struct clk *mcbsp_dspxor_ck = 0; -#endif -#ifdef CONFIG_ARCH_OMAP2 -static struct clk *mcbsp1_ick = 0; -static struct clk *mcbsp1_fck = 0; -static struct clk *mcbsp2_ick = 0; -static struct clk *mcbsp2_fck = 0; -#endif + +#define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \ + mcbsp[id].pdata->ops && \ + mcbsp[id].pdata->ops->check && \ + (mcbsp[id].pdata->ops->check(id) == 0)) static void omap_mcbsp_dump_reg(u8 id) { - DBG("**** MCBSP%d regs ****\n", mcbsp[id].id); - DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); - DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); - DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); - DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); - DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); - DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); - DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); - DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); - DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); - DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); - DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); - DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); - DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); - DBG("***********************\n"); + dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id); + dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); + dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); + dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); + dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); + dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); + dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); + dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); + dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); + dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); + dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); + dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); + dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); + dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); + dev_dbg(mcbsp[id].dev, "***********************\n"); } static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) { struct omap_mcbsp *mcbsp_tx = dev_id; - DBG("TX IRQ callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); + dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", + OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); complete(&mcbsp_tx->tx_irq_completion); + return IRQ_HANDLED; } @@ -111,10 +82,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) { struct omap_mcbsp *mcbsp_rx = dev_id; - DBG("RX IRQ callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); + dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", + OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); complete(&mcbsp_rx->rx_irq_completion); + return IRQ_HANDLED; } @@ -122,8 +94,8 @@ static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) { struct omap_mcbsp *mcbsp_dma_tx = data; - DBG("TX DMA callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); + dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", + OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); /* We can free the channels */ omap_free_dma(mcbsp_dma_tx->dma_tx_lch); @@ -136,8 +108,8 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) { struct omap_mcbsp *mcbsp_dma_rx = data; - DBG("RX DMA callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); + dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", + OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); /* We can free the channels */ omap_free_dma(mcbsp_dma_rx->dma_rx_lch); @@ -146,19 +118,24 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) complete(&mcbsp_dma_rx->rx_dma_completion); } - /* * omap_mcbsp_config simply write a config to the * appropriate McBSP. * You either call this function or set the McBSP registers * by yourself before calling omap_mcbsp_start(). */ - -void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config) +void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) { - u32 io_base = mcbsp[id].io_base; + u32 io_base; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } - DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base); + io_base = mcbsp[id].io_base; + dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n", + mcbsp[id].id, io_base); /* We write the given config */ OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); @@ -173,83 +150,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); } - - - -static int omap_mcbsp_check(unsigned int id) -{ - if (cpu_is_omap730()) { - if (id > OMAP_MAX_MCBSP_COUNT - 1) { - printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); - return -1; - } - return 0; - } - - if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) { - if (id > OMAP_MAX_MCBSP_COUNT) { - printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); - return -1; - } - return 0; - } - - return -1; -} - -#ifdef CONFIG_ARCH_OMAP1 -static void omap_mcbsp_dsp_request(void) -{ - if (cpu_is_omap15xx() || cpu_is_omap16xx()) { - int ret; - - ret = omap_dsp_request_mem(); - if (ret < 0) { - printk(KERN_ERR "Could not get dsp memory: %i\n", ret); - return; - } - - clk_enable(mcbsp_dsp_ck); - clk_enable(mcbsp_api_ck); - - /* enable 12MHz clock to mcbsp 1 & 3 */ - clk_enable(mcbsp_dspxor_ck); - - /* - * DSP external peripheral reset - * FIXME: This should be moved to dsp code - */ - __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1, - DSP_RSTCT2); - } -} - -static void omap_mcbsp_dsp_free(void) -{ - if (cpu_is_omap15xx() || cpu_is_omap16xx()) { - omap_dsp_release_mem(); - clk_disable(mcbsp_dspxor_ck); - clk_disable(mcbsp_dsp_ck); - clk_disable(mcbsp_api_ck); - } -} -#endif - -#ifdef CONFIG_ARCH_OMAP2 -static void omap2_mcbsp2_mux_setup(void) -{ - if (cpu_is_omap2420()) { - omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); - omap_cfg_reg(R14_24XX_MCBSP2_FSX); - omap_cfg_reg(W15_24XX_MCBSP2_DR); - omap_cfg_reg(V15_24XX_MCBSP2_DX); - omap_cfg_reg(V14_24XX_GPIO117); - } - /* - * Need to add MUX settings for OMAP 2430 SDP - */ -} -#endif +EXPORT_SYMBOL(omap_mcbsp_config); /* * We can choose between IRQ based or polled IO. @@ -257,13 +158,16 @@ static void omap2_mcbsp2_mux_setup(void) */ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) { - if (omap_mcbsp_check(id) < 0) - return -EINVAL; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } spin_lock(&mcbsp[id].lock); if (!mcbsp[id].free) { - printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); + dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", + mcbsp[id].id); spin_unlock(&mcbsp[id].lock); return -EINVAL; } @@ -274,38 +178,26 @@ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) return 0; } +EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { int err; - if (omap_mcbsp_check(id) < 0) - return -EINVAL; - -#ifdef CONFIG_ARCH_OMAP1 - /* - * On 1510, 1610 and 1710, McBSP1 and McBSP3 - * are DSP public peripherals. - */ - if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) - omap_mcbsp_dsp_request(); -#endif - -#ifdef CONFIG_ARCH_OMAP2 - if (cpu_is_omap24xx()) { - if (id == OMAP_MCBSP1) { - clk_enable(mcbsp1_ick); - clk_enable(mcbsp1_fck); - } else { - clk_enable(mcbsp2_ick); - clk_enable(mcbsp2_fck); - } + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; } -#endif + + if (mcbsp[id].pdata->ops->request) + mcbsp[id].pdata->ops->request(id); + + clk_enable(mcbsp[id].clk); spin_lock(&mcbsp[id].lock); if (!mcbsp[id].free) { - printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); + dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", + mcbsp[id].id); spin_unlock(&mcbsp[id].lock); return -1; } @@ -315,24 +207,23 @@ int omap_mcbsp_request(unsigned int id) if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { /* We need to get IRQs here */ - err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, - "McBSP", - (void *) (&mcbsp[id])); + err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, + 0, "McBSP", (void *) (&mcbsp[id])); if (err != 0) { - printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", - mcbsp[id].tx_irq, mcbsp[id].id); + dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d " + "for McBSP%d\n", mcbsp[id].tx_irq, + mcbsp[id].id); return err; } init_completion(&(mcbsp[id].tx_irq_completion)); - - err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, - "McBSP", - (void *) (&mcbsp[id])); + err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, + 0, "McBSP", (void *) (&mcbsp[id])); if (err != 0) { - printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", - mcbsp[id].rx_irq, mcbsp[id].id); + dev_err(mcbsp[id].dev, "Unable to request RX IRQ %d " + "for McBSP%d\n", mcbsp[id].rx_irq, + mcbsp[id].id); free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); return err; } @@ -341,36 +232,25 @@ int omap_mcbsp_request(unsigned int id) } return 0; - } +EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { - if (omap_mcbsp_check(id) < 0) + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; - -#ifdef CONFIG_ARCH_OMAP1 - if (cpu_class_is_omap1()) { - if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) - omap_mcbsp_dsp_free(); } -#endif - -#ifdef CONFIG_ARCH_OMAP2 - if (cpu_is_omap24xx()) { - if (id == OMAP_MCBSP1) { - clk_disable(mcbsp1_ick); - clk_disable(mcbsp1_fck); - } else { - clk_disable(mcbsp2_ick); - clk_disable(mcbsp2_fck); - } - } -#endif + + if (mcbsp[id].pdata->ops->free) + mcbsp[id].pdata->ops->free(id); + + clk_disable(mcbsp[id].clk); spin_lock(&mcbsp[id].lock); if (mcbsp[id].free) { - printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1); + dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n", + mcbsp[id].id); spin_unlock(&mcbsp[id].lock); return; } @@ -384,6 +264,7 @@ void omap_mcbsp_free(unsigned int id) free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); } } +EXPORT_SYMBOL(omap_mcbsp_free); /* * Here we start the McBSP, by enabling the sample @@ -395,13 +276,15 @@ void omap_mcbsp_start(unsigned int id) u32 io_base; u16 w; - if (omap_mcbsp_check(id) < 0) + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; + } io_base = mcbsp[id].io_base; - mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7); - mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7); + mcbsp[id].rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; + mcbsp[id].tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; /* Start the sample generator */ w = OMAP_MCBSP_READ(io_base, SPCR2); @@ -422,20 +305,22 @@ void omap_mcbsp_start(unsigned int id) /* Dump McBSP Regs */ omap_mcbsp_dump_reg(id); - } +EXPORT_SYMBOL(omap_mcbsp_start); void omap_mcbsp_stop(unsigned int id) { u32 io_base; u16 w; - if (omap_mcbsp_check(id) < 0) + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; + } io_base = mcbsp[id].io_base; - /* Reset transmitter */ + /* Reset transmitter */ w = OMAP_MCBSP_READ(io_base, SPCR2); OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); @@ -447,12 +332,19 @@ void omap_mcbsp_stop(unsigned int id) w = OMAP_MCBSP_READ(io_base, SPCR2); OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); } - +EXPORT_SYMBOL(omap_mcbsp_stop); /* polled mcbsp i/o operations */ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) { - u32 base = mcbsp[id].io_base; + u32 base; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + base = mcbsp[id].io_base; writew(buf, base + OMAP_MCBSP_REG_DXR1); /* if frame sync error - clear the error */ if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { @@ -474,18 +366,27 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) (XRST), base + OMAP_MCBSP_REG_SPCR2); udelay(10); - printk(KERN_ERR - " Could not write to McBSP Register\n"); + dev_err(mcbsp[id].dev, "Could not write to" + " McBSP%d Register\n", mcbsp[id].id); return -2; } } } + return 0; } +EXPORT_SYMBOL(omap_mcbsp_pollwrite); -int omap_mcbsp_pollread(unsigned int id, u16 * buf) +int omap_mcbsp_pollread(unsigned int id, u16 *buf) { - u32 base = mcbsp[id].io_base; + u32 base; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + base = mcbsp[id].io_base; /* if frame sync error - clear the error */ if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { /* clear error */ @@ -506,15 +407,17 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf) (RRST), base + OMAP_MCBSP_REG_SPCR1); udelay(10); - printk(KERN_ERR - " Could not read from McBSP Register\n"); + dev_err(mcbsp[id].dev, "Could not read from" + " McBSP%d Register\n", mcbsp[id].id); return -2; } } } *buf = readw(base + OMAP_MCBSP_REG_DRR1); + return 0; } +EXPORT_SYMBOL(omap_mcbsp_pollread); /* * IRQ based word transmission. @@ -522,12 +425,15 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf) void omap_mcbsp_xmit_word(unsigned int id, u32 word) { u32 io_base; - omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length; + omap_mcbsp_word_length word_length; - if (omap_mcbsp_check(id) < 0) + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; + } io_base = mcbsp[id].io_base; + word_length = mcbsp[id].tx_word_length; wait_for_completion(&(mcbsp[id].tx_irq_completion)); @@ -535,16 +441,20 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word) OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); } +EXPORT_SYMBOL(omap_mcbsp_xmit_word); u32 omap_mcbsp_recv_word(unsigned int id) { u32 io_base; u16 word_lsb, word_msb = 0; - omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length; + omap_mcbsp_word_length word_length; - if (omap_mcbsp_check(id) < 0) - return -EINVAL; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + word_length = mcbsp[id].rx_word_length; io_base = mcbsp[id].io_base; wait_for_completion(&(mcbsp[id].rx_irq_completion)); @@ -555,15 +465,24 @@ u32 omap_mcbsp_recv_word(unsigned int id) return (word_lsb | (word_msb << 16)); } - +EXPORT_SYMBOL(omap_mcbsp_recv_word); int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) { - u32 io_base = mcbsp[id].io_base; - omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; - omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; + u32 io_base; + omap_mcbsp_word_length tx_word_length; + omap_mcbsp_word_length rx_word_length; u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + io_base = mcbsp[id].io_base; + tx_word_length = mcbsp[id].tx_word_length; + rx_word_length = mcbsp[id].rx_word_length; + if (tx_word_length != rx_word_length) return -EINVAL; @@ -577,7 +496,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); udelay(10); - printk("McBSP transmitter not ready\n"); + dev_err(mcbsp[id].dev, "McBSP%d transmitter not " + "ready\n", mcbsp[id].id); return -EAGAIN; } } @@ -597,7 +517,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); udelay(10); - printk("McBSP receiver not ready\n"); + dev_err(mcbsp[id].dev, "McBSP%d receiver not " + "ready\n", mcbsp[id].id); return -EAGAIN; } } @@ -609,14 +530,24 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) return 0; } +EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); -int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) +int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) { - u32 io_base = mcbsp[id].io_base, clock_word = 0; - omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; - omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; + u32 io_base, clock_word = 0; + omap_mcbsp_word_length tx_word_length; + omap_mcbsp_word_length rx_word_length; u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + io_base = mcbsp[id].io_base; + tx_word_length = mcbsp[id].tx_word_length; + rx_word_length = mcbsp[id].rx_word_length; + if (tx_word_length != rx_word_length) return -EINVAL; @@ -630,7 +561,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); udelay(10); - printk("McBSP transmitter not ready\n"); + dev_err(mcbsp[id].dev, "McBSP%d transmitter not " + "ready\n", mcbsp[id].id); return -EAGAIN; } } @@ -650,7 +582,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); udelay(10); - printk("McBSP receiver not ready\n"); + dev_err(mcbsp[id].dev, "McBSP%d receiver not " + "ready\n", mcbsp[id].id); return -EAGAIN; } } @@ -664,7 +597,7 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) return 0; } - +EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); /* * Simple DMA based buffer rx/tx routines. @@ -673,25 +606,32 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) * For anything fancier, you should use your own customized DMA * routines and callbacks. */ -int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) +int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, + unsigned int length) { int dma_tx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; - if (omap_mcbsp_check(id) < 0) - return -EINVAL; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } - if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, - &mcbsp[id], - &dma_tx_ch)) { - printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1); + if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", + omap_mcbsp_tx_dma_callback, + &mcbsp[id], + &dma_tx_ch)) { + dev_err(mcbsp[id].dev, " Unable to request DMA channel for " + "McBSP%d TX. Trying IRQ based TX\n", + mcbsp[id].id); return -EAGAIN; } mcbsp[id].dma_tx_lch = dma_tx_ch; - DBG("TX DMA on channel %d\n", dma_tx_ch); + dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id, + dma_tx_ch); init_completion(&(mcbsp[id].tx_dma_completion)); @@ -699,7 +639,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } - if (cpu_is_omap24xx()) + if (cpu_class_is_omap2()) sync_dev = mcbsp[id].dma_tx_sync; omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, @@ -722,29 +662,37 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng omap_start_dma(mcbsp[id].dma_tx_lch); wait_for_completion(&(mcbsp[id].tx_dma_completion)); + return 0; } +EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); - -int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) +int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, + unsigned int length) { int dma_rx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; - if (omap_mcbsp_check(id) < 0) - return -EINVAL; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } - if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, - &mcbsp[id], - &dma_rx_ch)) { - printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1); + if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", + omap_mcbsp_rx_dma_callback, + &mcbsp[id], + &dma_rx_ch)) { + dev_err(mcbsp[id].dev, "Unable to request DMA channel for " + "McBSP%d RX. Trying IRQ based RX\n", + mcbsp[id].id); return -EAGAIN; } mcbsp[id].dma_rx_lch = dma_rx_ch; - DBG("RX DMA on channel %d\n", dma_rx_ch); + dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id, + dma_rx_ch); init_completion(&(mcbsp[id].rx_dma_completion)); @@ -752,14 +700,14 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } - if (cpu_is_omap24xx()) + if (cpu_class_is_omap2()) sync_dev = mcbsp[id].dma_rx_sync; omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, - OMAP_DMA_DATA_TYPE_S16, - length >> 1, 1, - OMAP_DMA_SYNC_ELEMENT, - sync_dev, 0); + OMAP_DMA_DATA_TYPE_S16, + length >> 1, 1, + OMAP_DMA_SYNC_ELEMENT, + sync_dev, 0); omap_set_dma_src_params(mcbsp[id].dma_rx_lch, src_port, @@ -768,16 +716,17 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng 0, 0); omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, - dest_port, - OMAP_DMA_AMODE_POST_INC, - buffer, - 0, 0); + dest_port, + OMAP_DMA_AMODE_POST_INC, + buffer, + 0, 0); omap_start_dma(mcbsp[id].dma_rx_lch); wait_for_completion(&(mcbsp[id].rx_dma_completion)); + return 0; } - +EXPORT_SYMBOL(omap_mcbsp_recv_buffer); /* * SPI wrapper. @@ -785,12 +734,15 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. * Once this is done, you can call omap_mcbsp_start(). */ -void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg) +void omap_mcbsp_set_spi_mode(unsigned int id, + const struct omap_mcbsp_spi_cfg *spi_cfg) { struct omap_mcbsp_reg_cfg mcbsp_cfg; - if (omap_mcbsp_check(id) < 0) + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; + } memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); @@ -798,7 +750,7 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0)); mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0)); - /* Clock stop mode */ + /* Clock stop mode */ if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY) mcbsp_cfg.spcr1 |= (1 << 12); else @@ -827,13 +779,12 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) { mcbsp_cfg.pcr0 |= CLKXM; - mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1); + mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1); mcbsp_cfg.pcr0 |= FSXM; mcbsp_cfg.srgr2 &= ~FSGM; mcbsp_cfg.xcr2 |= XDATDLY(1); mcbsp_cfg.rcr2 |= RDATDLY(1); - } - else { + } else { mcbsp_cfg.pcr0 &= ~CLKXM; mcbsp_cfg.srgr1 |= CLKGDV(1); mcbsp_cfg.pcr0 &= ~FSXM; @@ -846,199 +797,99 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * omap_mcbsp_config(id, &mcbsp_cfg); } - +EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); /* * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. */ -struct omap_mcbsp_info { - u32 virt_base; - u8 dma_rx_sync, dma_tx_sync; - u16 rx_irq, tx_irq; -}; +static int __init omap_mcbsp_probe(struct platform_device *pdev) +{ + struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; + int id = pdev->id - 1; + int ret = 0; -#ifdef CONFIG_ARCH_OMAP730 -static const struct omap_mcbsp_info mcbsp_730[] = { - [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_730_McBSP1RX, - .tx_irq = INT_730_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_730_McBSP2RX, - .tx_irq = INT_730_McBSP2TX }, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP15XX -static const struct omap_mcbsp_info mcbsp_1510[] = { - [0] = { .virt_base = OMAP1510_MCBSP1_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_McBSP1RX, - .tx_irq = INT_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP2_RX, - .dma_tx_sync = OMAP_DMA_MCBSP2_TX, - .rx_irq = INT_1510_SPI_RX, - .tx_irq = INT_1510_SPI_TX }, - [2] = { .virt_base = OMAP1510_MCBSP3_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_McBSP3RX, - .tx_irq = INT_McBSP3TX }, -}; -#endif - -#if defined(CONFIG_ARCH_OMAP16XX) -static const struct omap_mcbsp_info mcbsp_1610[] = { - [0] = { .virt_base = OMAP1610_MCBSP1_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_McBSP1RX, - .tx_irq = INT_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP2_RX, - .dma_tx_sync = OMAP_DMA_MCBSP2_TX, - .rx_irq = INT_1610_McBSP2_RX, - .tx_irq = INT_1610_McBSP2_TX }, - [2] = { .virt_base = OMAP1610_MCBSP3_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_McBSP3RX, - .tx_irq = INT_McBSP3TX }, -}; -#endif - -#if defined(CONFIG_ARCH_OMAP24XX) -static const struct omap_mcbsp_info mcbsp_24xx[] = { - [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), - .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, - .rx_irq = INT_24XX_MCBSP1_IRQ_RX, - .tx_irq = INT_24XX_MCBSP1_IRQ_TX, - }, - [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), - .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, - .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, - .rx_irq = INT_24XX_MCBSP2_IRQ_RX, - .tx_irq = INT_24XX_MCBSP2_IRQ_TX, - }, -}; -#endif + if (!pdata) { + dev_err(&pdev->dev, "McBSP device initialized without" + "platform data\n"); + ret = -EINVAL; + goto exit; + } + + dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); + + if (id >= OMAP_MAX_MCBSP_COUNT) { + dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); + ret = -EINVAL; + goto exit; + } + + spin_lock_init(&mcbsp[id].lock); + mcbsp[id].id = id + 1; + mcbsp[id].free = 1; + mcbsp[id].dma_tx_lch = -1; + mcbsp[id].dma_rx_lch = -1; + + mcbsp[id].io_base = pdata->virt_base; + /* Default I/O is IRQ based */ + mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; + mcbsp[id].tx_irq = pdata->tx_irq; + mcbsp[id].rx_irq = pdata->rx_irq; + mcbsp[id].dma_rx_sync = pdata->dma_rx_sync; + mcbsp[id].dma_tx_sync = pdata->dma_tx_sync; + + if (pdata->clk_name) + mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name); + if (IS_ERR(mcbsp[id].clk)) { + mcbsp[id].free = 0; + dev_err(&pdev->dev, + "Invalid clock configuration for McBSP%d.\n", + mcbsp[id].id); + ret = -EINVAL; + goto exit; + } + + mcbsp[id].pdata = pdata; + mcbsp[id].dev = &pdev->dev; + platform_set_drvdata(pdev, &mcbsp[id]); + +exit: + return ret; +} -static int __init omap_mcbsp_init(void) +static int omap_mcbsp_remove(struct platform_device *pdev) { - int mcbsp_count = 0, i; - static const struct omap_mcbsp_info *mcbsp_info; + struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - printk("Initializing OMAP McBSP system\n"); + platform_set_drvdata(pdev, NULL); + if (mcbsp) { -#ifdef CONFIG_ARCH_OMAP1 - mcbsp_dsp_ck = clk_get(0, "dsp_ck"); - if (IS_ERR(mcbsp_dsp_ck)) { - printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); - return PTR_ERR(mcbsp_dsp_ck); - } - mcbsp_api_ck = clk_get(0, "api_ck"); - if (IS_ERR(mcbsp_api_ck)) { - printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n"); - return PTR_ERR(mcbsp_api_ck); - } - mcbsp_dspxor_ck = clk_get(0, "dspxor_ck"); - if (IS_ERR(mcbsp_dspxor_ck)) { - printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); - return PTR_ERR(mcbsp_dspxor_ck); - } -#endif -#ifdef CONFIG_ARCH_OMAP2 - mcbsp1_ick = clk_get(0, "mcbsp1_ick"); - if (IS_ERR(mcbsp1_ick)) { - printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n"); - return PTR_ERR(mcbsp1_ick); - } - mcbsp1_fck = clk_get(0, "mcbsp1_fck"); - if (IS_ERR(mcbsp1_fck)) { - printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n"); - return PTR_ERR(mcbsp1_fck); - } - mcbsp2_ick = clk_get(0, "mcbsp2_ick"); - if (IS_ERR(mcbsp2_ick)) { - printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n"); - return PTR_ERR(mcbsp2_ick); - } - mcbsp2_fck = clk_get(0, "mcbsp2_fck"); - if (IS_ERR(mcbsp2_fck)) { - printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n"); - return PTR_ERR(mcbsp2_fck); - } -#endif + if (mcbsp->pdata && mcbsp->pdata->ops && + mcbsp->pdata->ops->free) + mcbsp->pdata->ops->free(mcbsp->id); -#ifdef CONFIG_ARCH_OMAP730 - if (cpu_is_omap730()) { - mcbsp_info = mcbsp_730; - mcbsp_count = ARRAY_SIZE(mcbsp_730); - } -#endif -#ifdef CONFIG_ARCH_OMAP15XX - if (cpu_is_omap15xx()) { - mcbsp_info = mcbsp_1510; - mcbsp_count = ARRAY_SIZE(mcbsp_1510); - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (cpu_is_omap16xx()) { - mcbsp_info = mcbsp_1610; - mcbsp_count = ARRAY_SIZE(mcbsp_1610); - } -#endif -#if defined(CONFIG_ARCH_OMAP24XX) - if (cpu_is_omap24xx()) { - mcbsp_info = mcbsp_24xx; - mcbsp_count = ARRAY_SIZE(mcbsp_24xx); - omap2_mcbsp2_mux_setup(); - } -#endif - for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { - if (i >= mcbsp_count) { - mcbsp[i].io_base = 0; - mcbsp[i].free = 0; - continue; - } - mcbsp[i].id = i + 1; - mcbsp[i].free = 1; - mcbsp[i].dma_tx_lch = -1; - mcbsp[i].dma_rx_lch = -1; - - mcbsp[i].io_base = mcbsp_info[i].virt_base; - mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */ - mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; - mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; - mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; - mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync; - spin_lock_init(&mcbsp[i].lock); + clk_disable(mcbsp->clk); + clk_put(mcbsp->clk); + + mcbsp->clk = NULL; + mcbsp->free = 0; + mcbsp->dev = NULL; } return 0; } -arch_initcall(omap_mcbsp_init); +static struct platform_driver omap_mcbsp_driver = { + .probe = omap_mcbsp_probe, + .remove = omap_mcbsp_remove, + .driver = { + .name = "omap-mcbsp", + }, +}; + +int __init omap_mcbsp_init(void) +{ + /* Register the McBSP driver */ + return platform_driver_register(&omap_mcbsp_driver); +} -EXPORT_SYMBOL(omap_mcbsp_config); -EXPORT_SYMBOL(omap_mcbsp_request); -EXPORT_SYMBOL(omap_mcbsp_set_io_type); -EXPORT_SYMBOL(omap_mcbsp_free); -EXPORT_SYMBOL(omap_mcbsp_start); -EXPORT_SYMBOL(omap_mcbsp_stop); -EXPORT_SYMBOL(omap_mcbsp_pollread); -EXPORT_SYMBOL(omap_mcbsp_pollwrite); -EXPORT_SYMBOL(omap_mcbsp_xmit_word); -EXPORT_SYMBOL(omap_mcbsp_recv_word); -EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); -EXPORT_SYMBOL(omap_mcbsp_recv_buffer); -EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); -EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); -EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); diff --git a/arch/arm/plat-omap/sram-fn.S b/arch/arm/plat-omap/sram-fn.S deleted file mode 100644 index 9e1813c77e05..000000000000 --- a/arch/arm/plat-omap/sram-fn.S +++ /dev/null @@ -1,57 +0,0 @@ -/* - * linux/arch/arm/plat-omap/sram-fn.S - * - * Functions that need to be run in internal SRAM - * - * 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/linkage.h> -#include <asm/assembler.h> -#include <asm/arch/io.h> -#include <asm/hardware.h> - - .text - -/* - * Reprograms ULPD and CKCTL. - */ -ENTRY(sram_reprogram_clock) - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - mov r2, #IO_ADDRESS(DPLL_CTL) & 0xff000000 - orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x00ff0000 - orr r2, r2, #IO_ADDRESS(DPLL_CTL) & 0x0000ff00 - - mov r3, #IO_ADDRESS(ARM_CKCTL) & 0xff000000 - orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x00ff0000 - orr r3, r3, #IO_ADDRESS(ARM_CKCTL) & 0x0000ff00 - - tst r0, #1 << 4 @ want lock mode? - beq newck @ nope - bic r0, r0, #1 << 4 @ else clear lock bit - strh r0, [r2] @ set dpll into bypass mode - orr r0, r0, #1 << 4 @ set lock bit again - -newck: - strh r1, [r3] @ write new ckctl value - strh r0, [r2] @ write new dpll value - - mov r4, #0x0700 @ let the clocks settle - orr r4, r4, #0x00ff -delay: sub r4, r4, #1 - cmp r4, #0 - bne delay - -lock: ldrh r4, [r2], #0 @ read back dpll value - tst r0, #1 << 4 @ want lock mode? - beq out @ nope - tst r4, #1 << 0 @ dpll rate locked? - beq lock @ try again - -out: - ldmfd sp!, {r0 - r12, pc} @ restore regs and return -ENTRY(sram_reprogram_clock_sz) - .word . - sram_reprogram_clock diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 1f23f0459e5f..554ee58e1294 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -10,6 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#undef DEBUG #include <linux/module.h> #include <linux/kernel.h> @@ -24,25 +25,43 @@ #include <asm/arch/sram.h> #include <asm/arch/board.h> +#include <asm/arch/control.h> + +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +# include "../mach-omap2/prm.h" +# include "../mach-omap2/cm.h" +# include "../mach-omap2/sdrc.h" +#endif + #define OMAP1_SRAM_PA 0x20000000 -#define OMAP1_SRAM_VA 0xd0000000 +#define OMAP1_SRAM_VA VMALLOC_END #define OMAP2_SRAM_PA 0x40200000 #define OMAP2_SRAM_PUB_PA 0x4020f800 -#define OMAP2_SRAM_VA 0xd0000000 -#define OMAP2_SRAM_PUB_VA 0xd0000800 - -#if defined(CONFIG_ARCH_OMAP24XX) +#define OMAP2_SRAM_VA VMALLOC_END +#define OMAP2_SRAM_PUB_VA (VMALLOC_END + 0x800) +#define OMAP3_SRAM_PA 0x40200000 +#define OMAP3_SRAM_VA 0xd7000000 +#define OMAP3_SRAM_PUB_PA 0x40208000 +#define OMAP3_SRAM_PUB_VA 0xd7008000 + +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #define SRAM_BOOTLOADER_SZ 0x00 #else #define SRAM_BOOTLOADER_SZ 0x80 #endif -#define VA_REQINFOPERM0 IO_ADDRESS(0x68005048) -#define VA_READPERM0 IO_ADDRESS(0x68005050) -#define VA_WRITEPERM0 IO_ADDRESS(0x68005058) -#define VA_CONTROL_STAT IO_ADDRESS(0x480002F8) +#define OMAP24XX_VA_REQINFOPERM0 IO_ADDRESS(0x68005048) +#define OMAP24XX_VA_READPERM0 IO_ADDRESS(0x68005050) +#define OMAP24XX_VA_WRITEPERM0 IO_ADDRESS(0x68005058) + +#define OMAP34XX_VA_REQINFOPERM0 IO_ADDRESS(0x68012848) +#define OMAP34XX_VA_READPERM0 IO_ADDRESS(0x68012850) +#define OMAP34XX_VA_WRITEPERM0 IO_ADDRESS(0x68012858) +#define OMAP34XX_VA_ADDR_MATCH2 IO_ADDRESS(0x68012880) +#define OMAP34XX_VA_SMS_RG_ATT0 IO_ADDRESS(0x6C000048) +#define OMAP34XX_VA_CONTROL_STAT IO_ADDRESS(0x480022F0) + #define GP_DEVICE 0x300 -#define TYPE_MASK 0x700 #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) @@ -68,14 +87,21 @@ static int is_sram_locked(void) int type = 0; if (cpu_is_omap242x()) - type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK; + type = system_rev & OMAP2_DEVICETYPE_MASK; if (type == GP_DEVICE) { /* RAMFW: R/W access to all initiators for all qualifier sets */ if (cpu_is_omap242x()) { - __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */ - __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */ - __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */ + __raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */ + __raw_writel(0xCFDE, OMAP24XX_VA_READPERM0); /* all i-read */ + __raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */ + } + if (cpu_is_omap34xx()) { + __raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */ + __raw_writel(0xFFFF, OMAP34XX_VA_READPERM0); /* all i-read */ + __raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */ + __raw_writel(0x0, OMAP34XX_VA_ADDR_MATCH2); + __raw_writel(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0); } return 0; } else @@ -92,18 +118,30 @@ void __init omap_detect_sram(void) { unsigned long reserved; - if (cpu_is_omap24xx()) { + if (cpu_class_is_omap2()) { if (is_sram_locked()) { - omap_sram_base = OMAP2_SRAM_PUB_VA; - omap_sram_start = OMAP2_SRAM_PUB_PA; - omap_sram_size = 0x800; /* 2K */ + if (cpu_is_omap34xx()) { + omap_sram_base = OMAP3_SRAM_PUB_VA; + omap_sram_start = OMAP3_SRAM_PUB_PA; + omap_sram_size = 0x8000; /* 32K */ + } else { + omap_sram_base = OMAP2_SRAM_PUB_VA; + omap_sram_start = OMAP2_SRAM_PUB_PA; + omap_sram_size = 0x800; /* 2K */ + } } else { - omap_sram_base = OMAP2_SRAM_VA; - omap_sram_start = OMAP2_SRAM_PA; - if (cpu_is_omap242x()) - omap_sram_size = 0xa0000; /* 640K */ - else if (cpu_is_omap243x()) + if (cpu_is_omap34xx()) { + omap_sram_base = OMAP3_SRAM_VA; + omap_sram_start = OMAP3_SRAM_PA; omap_sram_size = 0x10000; /* 64K */ + } else { + omap_sram_base = OMAP2_SRAM_VA; + omap_sram_start = OMAP2_SRAM_PA; + if (cpu_is_omap242x()) + omap_sram_size = 0xa0000; /* 640K */ + else if (cpu_is_omap243x()) + omap_sram_size = 0x10000; /* 64K */ + } } } else { omap_sram_base = OMAP1_SRAM_VA; @@ -157,6 +195,13 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].pfn = __phys_to_pfn(base); } + if (cpu_is_omap34xx()) { + omap_sram_io_desc[0].virtual = OMAP3_SRAM_VA; + base = OMAP3_SRAM_PA; + base = ROUND_DOWN(base, PAGE_SIZE); + omap_sram_io_desc[0].pfn = __phys_to_pfn(base); + } + omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); @@ -191,6 +236,7 @@ void * omap_sram_push(void * start, unsigned long size) omap_sram_ceil -= size; omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); memcpy((void *)omap_sram_ceil, start, size); + flush_icache_range((unsigned long)start, (unsigned long)(start + size)); return (void *)omap_sram_ceil; } @@ -214,8 +260,9 @@ void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) int __init omap1_sram_init(void) { - _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock, - sram_reprogram_clock_sz); + _omap_sram_reprogram_clock = + omap_sram_push(omap1_sram_reprogram_clock, + omap1_sram_reprogram_clock_sz); return 0; } @@ -224,7 +271,7 @@ int __init omap1_sram_init(void) #define omap1_sram_init() do {} while (0) #endif -#ifdef CONFIG_ARCH_OMAP2 +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, u32 base_cs, u32 force_unlock); @@ -259,19 +306,109 @@ u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass) return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass); } +#endif + +#ifdef CONFIG_ARCH_OMAP2420 +int __init omap242x_sram_init(void) +{ + _omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init, + omap242x_sram_ddr_init_sz); + + _omap2_sram_reprogram_sdrc = omap_sram_push(omap242x_sram_reprogram_sdrc, + omap242x_sram_reprogram_sdrc_sz); + + _omap2_set_prcm = omap_sram_push(omap242x_sram_set_prcm, + omap242x_sram_set_prcm_sz); + + return 0; +} +#else +static inline int omap242x_sram_init(void) +{ + return 0; +} +#endif + +#ifdef CONFIG_ARCH_OMAP2430 +int __init omap243x_sram_init(void) +{ + _omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init, + omap243x_sram_ddr_init_sz); + + _omap2_sram_reprogram_sdrc = omap_sram_push(omap243x_sram_reprogram_sdrc, + omap243x_sram_reprogram_sdrc_sz); + + _omap2_set_prcm = omap_sram_push(omap243x_sram_set_prcm, + omap243x_sram_set_prcm_sz); + + return 0; +} +#else +static inline int omap243x_sram_init(void) +{ + return 0; +} +#endif + +#ifdef CONFIG_ARCH_OMAP3 + +static u32 (*_omap2_sram_reprogram_gpmc)(u32 perf_level); +u32 omap2_sram_reprogram_gpmc(u32 perf_level) +{ + if (!_omap2_sram_reprogram_gpmc) + omap_sram_error(); + + return _omap2_sram_reprogram_gpmc(perf_level); +} + +static u32 (*_omap2_sram_configure_core_dpll)(u32 m, u32 n, + u32 freqsel, u32 m2); +u32 omap2_sram_configure_core_dpll(u32 m, u32 n, u32 freqsel, u32 m2) +{ + if (!_omap2_sram_configure_core_dpll) + omap_sram_error(); + + return _omap2_sram_configure_core_dpll(m, n, freqsel, m2); +} -int __init omap2_sram_init(void) +/* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */ +void restore_sram_functions(void) { - _omap2_sram_ddr_init = omap_sram_push(sram_ddr_init, sram_ddr_init_sz); + omap_sram_ceil = omap_sram_base + omap_sram_size; - _omap2_sram_reprogram_sdrc = omap_sram_push(sram_reprogram_sdrc, - sram_reprogram_sdrc_sz); - _omap2_set_prcm = omap_sram_push(sram_set_prcm, sram_set_prcm_sz); + _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc, + omap34xx_sram_reprogram_gpmc_sz); + + _omap2_sram_configure_core_dpll = + omap_sram_push(omap34xx_sram_configure_core_dpll, + omap34xx_sram_configure_core_dpll_sz); +} + +int __init omap34xx_sram_init(void) +{ + _omap2_sram_ddr_init = omap_sram_push(omap34xx_sram_ddr_init, + omap34xx_sram_ddr_init_sz); + + _omap2_sram_reprogram_sdrc = omap_sram_push(omap34xx_sram_reprogram_sdrc, + omap34xx_sram_reprogram_sdrc_sz); + + _omap2_set_prcm = omap_sram_push(omap34xx_sram_set_prcm, + omap34xx_sram_set_prcm_sz); + + _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc, + omap34xx_sram_reprogram_gpmc_sz); + + _omap2_sram_configure_core_dpll = + omap_sram_push(omap34xx_sram_configure_core_dpll, + omap34xx_sram_configure_core_dpll_sz); return 0; } #else -#define omap2_sram_init() do {} while (0) +static inline int omap34xx_sram_init(void) +{ + return 0; +} #endif int __init omap_sram_init(void) @@ -279,10 +416,14 @@ int __init omap_sram_init(void) omap_detect_sram(); omap_map_sram(); - if (!cpu_is_omap24xx()) + if (!(cpu_class_is_omap2())) omap1_sram_init(); - else - omap2_sram_init(); + else if (cpu_is_omap242x()) + omap242x_sram_init(); + else if (cpu_is_omap2430()) + omap243x_sram_init(); + else if (cpu_is_omap34xx()) + omap34xx_sram_init(); return 0; } diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index a619475c4b76..2699c16d4da0 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -1,4 +1,4 @@ -/* + /* * arch/arm/plat-omap/usb.c -- platform level USB initialization * * Copyright (C) 2004 Texas Instruments, Inc. @@ -156,8 +156,12 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) if (nwires == 0) { if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { + u32 l; + /* pulldown D+/D- */ - USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~(3 << 1); + omap_writel(l, USB_TRANSCEIVER_CTRL); } return 0; } @@ -171,6 +175,8 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) /* internal transceiver (unavailable on 17xx, 24xx) */ if (!cpu_class_is_omap2() && nwires == 2) { + u32 l; + // omap_cfg_reg(P9_USB_DP); // omap_cfg_reg(R8_USB_DM); @@ -185,9 +191,11 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) * - OTG support on this port not yet written */ - USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4); + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~(7 << 4); if (!is_device) - USB_TRANSCEIVER_CTRL_REG |= (3 << 1); + l |= (3 << 1); + omap_writel(l, USB_TRANSCEIVER_CTRL); return 3 << 16; } @@ -217,8 +225,13 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) * with VBUS switching and overcurrent detection. */ - if (cpu_class_is_omap1() && nwires != 6) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; + if (cpu_class_is_omap1() && nwires != 6) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } switch (nwires) { case 3: @@ -238,9 +251,13 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) omap_cfg_reg(K20_24XX_USB0_VM); omap2_usb_devconf_set(0, USB_UNIDIR); } else { + u32 l; + omap_cfg_reg(AA9_USB0_VP); omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + l = omap_readl(USB_TRANSCEIVER_CTRL); + l |= CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); } break; default: @@ -254,8 +271,13 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~CONF_USB1_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } if (cpu_is_omap24xx()) omap2_usb_devconf_clear(1, USB_BIDIR_TLL); @@ -316,8 +338,13 @@ static u32 __init omap_usb1_init(unsigned nwires) syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); - if (!cpu_is_omap15xx()) - USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; + if (!cpu_is_omap15xx()) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l |= CONF_USB1_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } break; default: bad: @@ -340,8 +367,13 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) if (alt_pingroup || nwires == 0) return 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } /* external transceiver */ if (cpu_is_omap15xx()) { @@ -410,9 +442,13 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) omap_cfg_reg(USB2_VP); omap_cfg_reg(USB2_VM); } else { + u32 l; + omap_cfg_reg(AA9_USB2_VP); omap_cfg_reg(R9_USB2_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + l = omap_readl(USB_TRANSCEIVER_CTRL); + l |= CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); } break; default: @@ -531,10 +567,6 @@ static struct platform_device otg_device = { /*-------------------------------------------------------------------------*/ -#define ULPD_CLOCK_CTRL_REG __REG16(ULPD_CLOCK_CTRL) -#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ) - - // FIXME correct answer depends on hmc_mode, // as does (on omap1) any nonzero value for config->otg port number #ifdef CONFIG_USB_GADGET_OMAP @@ -550,17 +582,17 @@ static struct platform_device otg_device = { void __init omap_otg_init(struct omap_usb_config *config) { - u32 syscon = OTG_SYSCON_1_REG & 0xffff; + u32 syscon; int status; int alt_pingroup = 0; /* NOTE: no bus or clock setup (yet?) */ - syscon = OTG_SYSCON_1_REG & 0xffff; + syscon = omap_readl(OTG_SYSCON_1) & 0xffff; if (!(syscon & OTG_RESET_DONE)) pr_debug("USB resets not complete?\n"); - // OTG_IRQ_EN_REG = 0; + //omap_writew(0, OTG_IRQ_EN); /* pin muxing and transceiver pinouts */ if (config->pins[0] > 2) /* alt pingroup 2 */ @@ -568,8 +600,8 @@ omap_otg_init(struct omap_usb_config *config) syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config)); syscon |= omap_usb1_init(config->pins[1]); syscon |= omap_usb2_init(config->pins[2], alt_pingroup); - pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon); - OTG_SYSCON_1_REG = syscon; + pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); + omap_writel(syscon, OTG_SYSCON_1); syscon = config->hmc_mode; syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */; @@ -578,9 +610,10 @@ omap_otg_init(struct omap_usb_config *config) syscon |= OTG_EN; #endif if (cpu_class_is_omap1()) - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); - pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); - OTG_SYSCON_2_REG = syscon; + pr_debug("USB_TRANSCEIVER_CTRL = %03x\n", + omap_readl(USB_TRANSCEIVER_CTRL)); + pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2)); + omap_writel(syscon, OTG_SYSCON_2); printk("USB: hmc %d", config->hmc_mode); if (!alt_pingroup) @@ -597,12 +630,19 @@ omap_otg_init(struct omap_usb_config *config) printk("\n"); if (cpu_class_is_omap1()) { + u16 w; + /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; + w = omap_readw(ULPD_SOFT_REQ); + w &= ~SOFT_USB_CLK_REQ; + omap_writew(w, ULPD_SOFT_REQ); + + w = omap_readw(ULPD_CLOCK_CTRL); + w &= ~USB_MCLK_EN; + w |= DIS_USB_PVCI_CLK; + omap_writew(w, ULPD_CLOCK_CTRL); } - syscon = OTG_SYSCON_1_REG; + syscon = omap_readl(OTG_SYSCON_1); syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; #ifdef CONFIG_USB_GADGET_OMAP @@ -639,8 +679,8 @@ omap_otg_init(struct omap_usb_config *config) pr_debug("can't register OTG device, %d\n", status); } #endif - pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon); - OTG_SYSCON_1_REG = syscon; + pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); + omap_writel(syscon, OTG_SYSCON_1); status = 0; } @@ -653,18 +693,19 @@ static inline void omap_otg_init(struct omap_usb_config *config) {} #ifdef CONFIG_ARCH_OMAP15XX -#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL) +/* ULPD_DPLL_CTRL */ #define DPLL_IOB (1 << 13) #define DPLL_PLL_ENABLE (1 << 4) #define DPLL_LOCK (1 << 0) -#define ULPD_APLL_CTRL_REG __REG16(ULPD_APLL_CTRL) +/* ULPD_APLL_CTRL */ #define APLL_NDPLL_SWITCH (1 << 0) static void __init omap_1510_usb_init(struct omap_usb_config *config) { unsigned int val; + u16 w; omap_usb0_init(config->pins[0], is_usb0_device(config)); omap_usb1_init(config->pins[1]); @@ -685,12 +726,22 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config) printk("\n"); /* use DPLL for 48 MHz function clock */ - pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG, - ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG); - ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH; - ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE; - ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ; - while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK)) + pr_debug("APLL %04x DPLL %04x REQ %04x\n", omap_readw(ULPD_APLL_CTRL), + omap_readw(ULPD_DPLL_CTRL), omap_readw(ULPD_SOFT_REQ)); + + w = omap_readw(ULPD_APLL_CTRL); + w &= ~APLL_NDPLL_SWITCH; + omap_writew(w, ULPD_APLL_CTRL); + + w = omap_readw(ULPD_DPLL_CTRL); + w |= DPLL_IOB | DPLL_PLL_ENABLE; + omap_writew(w, ULPD_DPLL_CTRL); + + w = omap_readw(ULPD_SOFT_REQ); + w |= SOFT_UDC_REQ | SOFT_DPLL_REQ; + omap_writew(w, ULPD_SOFT_REQ); + + while (!(omap_readw(ULPD_DPLL_CTRL) & DPLL_LOCK)) cpu_relax(); #ifdef CONFIG_USB_GADGET_OMAP |