diff options
Diffstat (limited to 'arch/arm/plat-omap/dma.c')
-rw-r--r-- | arch/arm/plat-omap/dma.c | 766 |
1 files changed, 469 insertions, 297 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index c00eda588cd..fac8e994f58 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); |