From a4c537c7f60704691efc5f833b3d440252275c3b Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:17 -0800 Subject: [PATCH 1/9] OMAP: DMA: Replace read/write macros with functions Prepare DMA library to get converted into DMA driver using platform device model and hwmod infrastucture(for omap2+, resource structures for omap1) The low level read/write macros are replaced with static inline functions and register offsets are handled through static register offset tables mapped through enumeration constants. These low level read/write functions along with static register offset tables will be moved to respective mach-omap dma files in the later patches of this series. There are no functionality changes with these changes except change in logic for handling 16bit registers of OMAP1. Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 515 ++++++++++++++++---------- arch/arm/plat-omap/include/plat/dma.h | 151 ++------ 2 files changed, 344 insertions(+), 322 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index a863f5546a6b..49a7cd4763f9 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -40,6 +40,96 @@ #undef DEBUG +static u16 reg_map_omap1[] = { + [GCR] = 0x400, + [GSCR] = 0x404, + [GRST1] = 0x408, + [HW_ID] = 0x442, + [PCH2_ID] = 0x444, + [PCH0_ID] = 0x446, + [PCH1_ID] = 0x448, + [PCHG_ID] = 0x44a, + [PCHD_ID] = 0x44c, + [CAPS_0] = 0x44e, + [CAPS_1] = 0x452, + [CAPS_2] = 0x456, + [CAPS_3] = 0x458, + [CAPS_4] = 0x45a, + [PCH2_SR] = 0x460, + [PCH0_SR] = 0x480, + [PCH1_SR] = 0x482, + [PCHD_SR] = 0x4c0, + + /* Common Registers */ + [CSDP] = 0x00, + [CCR] = 0x02, + [CICR] = 0x04, + [CSR] = 0x06, + [CEN] = 0x10, + [CFN] = 0x12, + [CSFI] = 0x14, + [CSEI] = 0x16, + [CPC] = 0x18, /* 15xx only */ + [CSAC] = 0x18, + [CDAC] = 0x1a, + [CDEI] = 0x1c, + [CDFI] = 0x1e, + [CLNK_CTRL] = 0x28, + + /* Channel specific register offsets */ + [CSSA] = 0x08, + [CDSA] = 0x0c, + [COLOR] = 0x20, + [CCR2] = 0x24, + [LCH_CTRL] = 0x2a, +}; + +static u16 reg_map_omap2[] = { + [REVISION] = 0x00, + [GCR] = 0x78, + [IRQSTATUS_L0] = 0x08, + [IRQSTATUS_L1] = 0x0c, + [IRQSTATUS_L2] = 0x10, + [IRQSTATUS_L3] = 0x14, + [IRQENABLE_L0] = 0x18, + [IRQENABLE_L1] = 0x1c, + [IRQENABLE_L2] = 0x20, + [IRQENABLE_L3] = 0x24, + [SYSSTATUS] = 0x28, + [OCP_SYSCONFIG] = 0x2c, + [CAPS_0] = 0x64, + [CAPS_2] = 0x6c, + [CAPS_3] = 0x70, + [CAPS_4] = 0x74, + + /* Common register offsets */ + [CCR] = 0x80, + [CLNK_CTRL] = 0x84, + [CICR] = 0x88, + [CSR] = 0x8c, + [CSDP] = 0x90, + [CEN] = 0x94, + [CFN] = 0x98, + [CSEI] = 0xa4, + [CSFI] = 0xa8, + [CDEI] = 0xac, + [CDFI] = 0xb0, + [CSAC] = 0xb4, + [CDAC] = 0xb8, + + /* Channel specific register offsets */ + [CSSA] = 0x9c, + [CDSA] = 0xa0, + [CCEN] = 0xbc, + [CCFN] = 0xc0, + [COLOR] = 0xc4, + + /* OMAP4 specific registers */ + [CDP] = 0xd0, + [CNDP] = 0xd4, + [CCDN] = 0xd8, +}; + #ifndef CONFIG_ARCH_OMAP1 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED @@ -138,6 +228,9 @@ static int omap_dma_reserve_channels; static spinlock_t dma_chan_lock; static struct omap_dma_lch *dma_chan; static void __iomem *omap_dma_base; +static u16 *reg_map; +static u8 dma_stride; +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; 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, @@ -154,23 +247,48 @@ 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; \ -}) +static inline void dma_write(u32 val, int reg, int lch) +{ + u8 stride; + u32 offset; -#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); \ -}) + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + if (dma_stride == 0x40) { + __raw_writew(val, omap_dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + __raw_writew(val >> 16, omap_dma_base + offset2); + } + } else { + __raw_writel(val, omap_dma_base + offset); + } +} + +static inline u32 dma_read(int reg, int lch) +{ + u8 stride; + u32 offset, val; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + if (dma_stride == 0x40) { + val = __raw_readw(omap_dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u16 upper; + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + upper = __raw_readw(omap_dma_base + offset2); + val |= (upper << 16); + } + } else { + val = __raw_readl(omap_dma_base + offset); + } + return val; +} #ifdef CONFIG_ARCH_OMAP15XX /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ @@ -209,11 +327,10 @@ static inline void set_gdma_dev(int req, int dev) /* Omap1 only */ static void clear_lch_regs(int lch) { - int i; - void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch); + int i = dma_common_ch_start; - for (i = 0; i < 0x2c; i += 2) - __raw_writew(0, lch_base + i); + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); } void omap_set_dma_priority(int lch, int dst_port, int priority) @@ -248,12 +365,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) if (cpu_class_is_omap2()) { u32 ccr; - ccr = dma_read(CCR(lch)); + ccr = dma_read(CCR, lch); if (priority) ccr |= (1 << 6); else ccr &= ~(1 << 6); - dma_write(ccr, CCR(lch)); + dma_write(ccr, CCR, lch); } } EXPORT_SYMBOL(omap_set_dma_priority); @@ -264,31 +381,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~0x03; l |= data_type; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); if (cpu_class_is_omap1()) { u16 ccr; - ccr = dma_read(CCR(lch)); + ccr = dma_read(CCR, lch); ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) ccr |= 1 << 5; - dma_write(ccr, CCR(lch)); + dma_write(ccr, CCR, lch); - ccr = dma_read(CCR2(lch)); + ccr = dma_read(CCR2, lch); ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) ccr |= 1 << 2; - dma_write(ccr, CCR2(lch)); + dma_write(ccr, CCR2, lch); } if (cpu_class_is_omap2() && dma_trigger) { u32 val; - val = dma_read(CCR(lch)); + val = dma_read(CCR, lch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -313,11 +430,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, } else { val &= ~(1 << 24); /* dest synch */ } - dma_write(val, CCR(lch)); + dma_write(val, CCR, lch); } - dma_write(elem_count, CEN(lch)); - dma_write(frame_count, CFN(lch)); + dma_write(elem_count, CEN, lch); + dma_write(frame_count, CFN, lch); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -328,7 +445,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CCR2(lch)); + w = dma_read(CCR2, lch); w &= ~0x03; switch (mode) { @@ -343,23 +460,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(w, CCR2(lch)); + dma_write(w, CCR2, lch); - w = dma_read(LCH_CTRL(lch)); + w = dma_read(LCH_CTRL, lch); w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - dma_write((u16)color, COLOR_L(lch)); - dma_write((u16)(color >> 16), COLOR_U(lch)); + dma_write(color, COLOR, lch); w |= 1; /* Channel type G */ } - dma_write(w, LCH_CTRL(lch)); + dma_write(w, LCH_CTRL, lch); } if (cpu_class_is_omap2()) { u32 val; - val = dma_read(CCR(lch)); + val = dma_read(CCR, lch); val &= ~((1 << 17) | (1 << 16)); switch (mode) { @@ -374,10 +490,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(val, CCR(lch)); + dma_write(val, CCR, lch); color &= 0xffffff; - dma_write(color, COLOR(lch)); + dma_write(color, COLOR, lch); } } EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -387,10 +503,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) if (cpu_class_is_omap2()) { u32 csdp; - csdp = dma_read(CSDP(lch)); + csdp = dma_read(CSDP, lch); csdp &= ~(0x3 << 16); csdp |= (mode << 16); - dma_write(csdp, CSDP(lch)); + dma_write(csdp, CSDP, lch); } } EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -400,10 +516,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { u32 l; - l = dma_read(LCH_CTRL(lch)); + l = dma_read(LCH_CTRL, lch); l &= ~0x7; l |= mode; - dma_write(l, LCH_CTRL(lch)); + dma_write(l, LCH_CTRL, lch); } } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -418,27 +534,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CSDP(lch)); + w = dma_read(CSDP, lch); w &= ~(0x1f << 2); w |= src_port << 2; - dma_write(w, CSDP(lch)); + dma_write(w, CSDP, lch); } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~(0x03 << 12); l |= src_amode << 12; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); - if (cpu_class_is_omap1()) { - dma_write(src_start >> 16, CSSA_U(lch)); - dma_write((u16)src_start, CSSA_L(lch)); - } + dma_write(src_start, CSSA, lch); - if (cpu_class_is_omap2()) - dma_write(src_start, CSSA(lch)); - - dma_write(src_ei, CSEI(lch)); - dma_write(src_fi, CSFI(lch)); + dma_write(src_ei, CSEI, lch); + dma_write(src_fi, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_params); @@ -466,8 +576,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CSEI(lch)); - dma_write(fidx, CSFI(lch)); + dma_write(eidx, CSEI, lch); + dma_write(fidx, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -475,11 +585,11 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(1 << 6); if (enable) l |= (1 << 6); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -488,7 +598,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x03 << 7); switch (burst_mode) { @@ -524,7 +634,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) } l |= (burst << 7); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -536,27 +646,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, u32 l; if (cpu_class_is_omap1()) { - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x1f << 9); l |= dest_port << 9; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~(0x03 << 14); l |= dest_amode << 14; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); - if (cpu_class_is_omap1()) { - dma_write(dest_start >> 16, CDSA_U(lch)); - dma_write(dest_start, CDSA_L(lch)); - } + dma_write(dest_start, CDSA, lch); - if (cpu_class_is_omap2()) - dma_write(dest_start, CDSA(lch)); - - dma_write(dst_ei, CDEI(lch)); - dma_write(dst_fi, CDFI(lch)); + dma_write(dst_ei, CDEI, lch); + dma_write(dst_fi, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -565,8 +669,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CDEI(lch)); - dma_write(fidx, CDFI(lch)); + dma_write(eidx, CDEI, lch); + dma_write(fidx, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -574,11 +678,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(1 << 13); if (enable) l |= 1 << 13; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -587,7 +691,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x03 << 14); switch (burst_mode) { @@ -620,7 +724,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) return; } l |= (burst << 14); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -630,18 +734,18 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = dma_read(CSR(lch)); + status = dma_read(CSR, lch); else if (cpu_class_is_omap2()) - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); /* Enable some nice interrupts. */ - dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); + dma_write(dma_chan[lch].enabled_irqs, CICR, lch); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); } void omap_enable_dma_irq(int lch, u16 bits) @@ -660,7 +764,7 @@ static inline void enable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL(lch)); + l = dma_read(CLNK_CTRL, lch); if (cpu_class_is_omap1()) l &= ~(1 << 14); @@ -675,18 +779,18 @@ static inline void enable_lnk(int lch) l = dma_chan[lch].next_linked_ch | (1 << 15); #endif - dma_write(l, CLNK_CTRL(lch)); + dma_write(l, CLNK_CTRL, lch); } static inline void disable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL(lch)); + l = dma_read(CLNK_CTRL, lch); /* Disable interrupts */ if (cpu_class_is_omap1()) { - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Set the STOP_LNK bit */ l |= 1 << 14; } @@ -697,7 +801,7 @@ static inline void disable_lnk(int lch) l &= ~(1 << 15); } - dma_write(l, CLNK_CTRL(lch)); + dma_write(l, CLNK_CTRL, lch); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -710,9 +814,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0); + val = dma_read(IRQENABLE_L0, lch); val |= 1 << lch; - dma_write(val, IRQENABLE_L0); + dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -725,9 +829,9 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0); + val = dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0); + dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -792,17 +896,17 @@ int omap_request_dma(int dev_id, const char *dev_name, * Disable the 1510 compatibility mode and set the sync device * id. */ - dma_write(dev_id | (1 << 10), CCR(free_ch)); + dma_write(dev_id | (1 << 10), CCR, free_ch); } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { - dma_write(dev_id, CCR(free_ch)); + dma_write(dev_id, CCR, free_ch); } if (cpu_class_is_omap2()) { omap2_enable_irq_lch(free_ch); omap_enable_channel_irq(free_ch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch)); - dma_write(1 << free_ch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); + dma_write(1 << free_ch, IRQSTATUS_L0, 0); } *dma_ch_out = free_ch; @@ -823,23 +927,23 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR(lch)); + dma_write(0, CCR, lch); } if (cpu_class_is_omap2()) { omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); - dma_write(1 << lch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + dma_write(1 << lch, IRQSTATUS_L0, lch); /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR(lch)); + dma_write(0, CCR, lch); omap_clear_dma(lch); } @@ -880,7 +984,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; - dma_write(reg, GCR); + dma_write(reg, GCR, 0); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -903,14 +1007,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else l |= ((read_prio & 0x1) << 6); - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); return 0; } @@ -929,19 +1033,18 @@ void omap_clear_dma(int lch) if (cpu_class_is_omap1()) { u32 l; - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); /* Clear pending interrupts */ - l = dma_read(CSR(lch)); + l = dma_read(CSR, lch); } if (cpu_class_is_omap2()) { - int i; - void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch); - for (i = 0; i < 0x44; i += 4) - __raw_writel(0, lch_base + i); + int i = dma_common_ch_start; + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); } local_irq_restore(flags); @@ -957,9 +1060,9 @@ void omap_start_dma(int lch) * before starting dma transfer. */ if (cpu_is_omap15xx()) - dma_write(0, CPC(lch)); + dma_write(0, CPC, lch); else - dma_write(0, CDAC(lch)); + dma_write(0, CDAC, lch); if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch; @@ -989,12 +1092,12 @@ void omap_start_dma(int lch) (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) { /* Errata: Need to write lch even if not using chaining */ - dma_write(lch, CLNK_CTRL(lch)); + dma_write(lch, CLNK_CTRL, lch); } omap_enable_channel_irq(lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); /* * Errata: Inter Frame DMA buffering issue (All OMAP2420 and @@ -1010,7 +1113,7 @@ void omap_start_dma(int lch) l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1022,41 +1125,41 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; /* Configure No-Standby */ - l = dma_read(OCP_SYSCONFIG); + l = dma_read(OCP_SYSCONFIG, lch); sys_cf = l; l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - dma_write(l , OCP_SYSCONFIG); + dma_write(l , OCP_SYSCONFIG, 0); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); /* Wait for sDMA FIFO drain */ - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) { udelay(5); i++; - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); } if (i >= 100) printk(KERN_ERR "DMA drain did not complete on " "lch %d\n", lch); /* Restore OCP_SYSCONFIG */ - dma_write(sys_cf, OCP_SYSCONFIG); + dma_write(sys_cf, OCP_SYSCONFIG, lch); } else { l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { @@ -1122,19 +1225,19 @@ dma_addr_t omap_get_dma_src_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC(lch)); + offset = dma_read(CPC, lch); else - offset = dma_read(CSAC(lch)); + offset = dma_read(CSAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CSAC(lch)); + offset = dma_read(CSAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CSSA_U(lch)) << 16); + offset |= (dma_read(CSSA, lch) & 0xFFFF0000); return offset; } @@ -1153,19 +1256,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC(lch)); + offset = dma_read(CPC, lch); else - offset = dma_read(CDAC(lch)); + offset = dma_read(CDAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CDAC(lch)); + offset = dma_read(CDAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CDSA_U(lch)) << 16); + offset |= (dma_read(CDSA, lch) & 0xFFFF0000); return offset; } @@ -1173,7 +1276,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0; + return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1186,7 +1289,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) + if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -1201,8 +1304,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) | (3 << 8), - CCR(lch_head)); + dma_write(dma_read(CCR, lch_head) | (3 << 8), + CCR, lch_head); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1228,8 +1331,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), - CCR(lch_head)); + dma_write(dma_read(CCR, lch_head) & ~(3 << 8), + CCR, lch_head); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1281,15 +1384,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - l = dma_read(CLNK_CTRL(lch_head)); + l = dma_read(CLNK_CTRL, lch_head); l &= ~(0x1f); l |= lch_queue; - dma_write(l, CLNK_CTRL(lch_head)); + dma_write(l, CLNK_CTRL, lch_head); - l = dma_read(CLNK_CTRL(lch_queue)); + l = dma_read(CLNK_CTRL, lch_queue); l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); - dma_write(l, CLNK_CTRL(lch_queue)); + dma_write(l, CLNK_CTRL, lch_queue); } /** @@ -1565,13 +1668,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Set the params to the free channel */ if (src_start != 0) - dma_write(src_start, CSSA(lch)); + dma_write(src_start, CSSA, lch); if (dest_start != 0) - dma_write(dest_start, CDSA(lch)); + dma_write(dest_start, CDSA, lch); /* Write the buffer size */ - dma_write(elem_count, CEN(lch)); - dma_write(frame_count, CFN(lch)); + dma_write(elem_count, CEN, lch); + dma_write(frame_count, CFN, lch); /* * If the chain is dynamically linked, @@ -1605,7 +1708,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, dma_chan[lch].state = DMA_CH_QUEUED; start_dma = 0; if (0 == ((1 << 7) & dma_read( - CCR(dma_chan[lch].prev_linked_ch)))) { + CCR, dma_chan[lch].prev_linked_ch))) { disable_lnk(dma_chan[lch]. prev_linked_ch); pr_debug("\n prev ch is stopped\n"); @@ -1621,7 +1724,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); if ((0 == (l & (1 << 24)))) l &= ~(1 << 25); @@ -1632,12 +1735,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, l |= (1 << 7); dma_chan[lch].state = DMA_CH_STARTED; pr_debug("starting %d\n", lch); - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } else start_dma = 0; } else { if (0 == (l & (1 << 7))) - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1682,7 +1785,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - l = dma_read(CCR(channels[0])); + 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; @@ -1691,7 +1794,7 @@ int omap_start_dma_chain_transfers(int chain_id) l &= ~(1 << 25); else l |= (1 << 25); - dma_write(l, CCR(channels[0])); + dma_write(l, CCR, channels[0]); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1730,18 +1833,18 @@ int omap_stop_dma_chain_transfers(int chain_id) * DMA Errata: * Special programming model needed to disable DMA before end of block */ - sys_cf = dma_read(OCP_SYSCONFIG); + sys_cf = dma_read(OCP_SYSCONFIG, 0); l = sys_cf; /* Middle mode reg set no Standby */ l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG); + dma_write(l, OCP_SYSCONFIG, 0); for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - l = dma_read(CCR(channels[i])); + l = dma_read(CCR, channels[i]); l &= ~(1 << 7); - dma_write(l, CCR(channels[i])); + dma_write(l, CCR, channels[i]); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1754,7 +1857,7 @@ int omap_stop_dma_chain_transfers(int chain_id) OMAP_DMA_CHAIN_QINIT(chain_id); /* Errata - put in the old value */ - dma_write(sys_cf, OCP_SYSCONFIG); + dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -1796,8 +1899,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - *ei = dma_read(CCEN(lch)); - *fi = dma_read(CCFN(lch)); + *ei = dma_read(CCEN, lch); + *fi = dma_read(CCFN, lch); return 0; } @@ -1834,7 +1937,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CDAC(lch)); + return dma_read(CDAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1868,7 +1971,7 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CSAC(lch)); + return dma_read(CSAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1885,7 +1988,7 @@ static int omap1_dma_handle_ch(int ch) csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = dma_read(CSR(ch)); + csr = dma_read(CSR, ch); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -1938,13 +2041,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = dma_read(CSR(ch)); + u32 status = dma_read(CSR, ch); if (!status) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - dma_write(1 << ch, IRQSTATUS_L0); + dma_write(1 << ch, IRQSTATUS_L0, ch); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -1968,9 +2071,9 @@ static int omap2_dma_handle_ch(int ch) */ u32 ccr; - ccr = dma_read(CCR(ch)); + ccr = dma_read(CCR, ch); ccr &= ~OMAP_DMA_CCR_EN; - dma_write(ccr, CCR(ch)); + dma_write(ccr, CCR, ch); dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; } } @@ -1981,16 +2084,16 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch)); - dma_write(1 << ch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); + dma_write(1 << ch, IRQSTATUS_L0, ch); /* read back the register to flush the write */ - dma_read(IRQSTATUS_L0); + dma_read(IRQSTATUS_L0, ch); /* If the ch is not chained then chain_id will be -1 */ if (dma_chan[ch].chain_id != -1) { int chain_id = dma_chan[ch].chain_id; dma_chan[ch].state = DMA_CH_NOTSTARTED; - if (dma_read(CLNK_CTRL(ch)) & (1 << 15)) + if (dma_read(CLNK_CTRL, ch) & (1 << 15)) dma_chan[dma_chan[ch].next_linked_ch].state = DMA_CH_STARTED; if (dma_linked_lch[chain_id].chain_mode == @@ -2000,10 +2103,10 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = dma_read(CSR(ch)); + status = dma_read(CSR, ch); } - dma_write(status, CSR(ch)); + dma_write(status, CSR, ch); if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -2017,13 +2120,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val, enable_reg; int i; - val = dma_read(IRQSTATUS_L0); + val = dma_read(IRQSTATUS_L0, 0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - enable_reg = dma_read(IRQENABLE_L0); + enable_reg = dma_read(IRQENABLE_L0, 0); val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) @@ -2049,21 +2152,21 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = - dma_read(IRQENABLE_L0); + dma_read(IRQENABLE_L0, 0); omap_dma_global_context.dma_ocp_sysconfig = - dma_read(OCP_SYSCONFIG); - omap_dma_global_context.dma_gcr = dma_read(GCR); + dma_read(OCP_SYSCONFIG, 0); + omap_dma_global_context.dma_gcr = dma_read(GCR, 0); } void omap_dma_global_context_restore(void) { int ch; - dma_write(omap_dma_global_context.dma_gcr, GCR); + dma_write(omap_dma_global_context.dma_gcr, GCR, 0); dma_write(omap_dma_global_context.dma_ocp_sysconfig, - OCP_SYSCONFIG); + OCP_SYSCONFIG, 0); dma_write(omap_dma_global_context.dma_irqenable_l0, - IRQENABLE_L0); + IRQENABLE_L0, 0); /* * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared @@ -2072,7 +2175,7 @@ void omap_dma_global_context_restore(void) * affects only secure devices. */ if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) - dma_write(0x3 , IRQSTATUS_L0); + dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) @@ -2106,6 +2209,21 @@ static int __init omap_init_dma(void) omap_dma_base = ioremap(base, SZ_4K); BUG_ON(!omap_dma_base); + if (cpu_class_is_omap1()) { + dma_stride = 0x40; + reg_map = reg_map_omap1; + dma_common_ch_start = CPC; + dma_common_ch_end = COLOR; + } else { + dma_stride = 0x60; + reg_map = reg_map_omap2; + dma_common_ch_start = CSDP; + if (cpu_is_omap3630() || cpu_is_omap4430()) + dma_common_ch_end = CCDN; + else + dma_common_ch_end = CCFN; + } + if (cpu_class_is_omap2() && omap_dma_reserve_channels && (omap_dma_reserve_channels <= dma_lch_count)) dma_lch_count = omap_dma_reserve_channels; @@ -2132,26 +2250,23 @@ static int __init omap_init_dma(void) enable_1510_mode = 1; } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", - dma_read(HW_ID)); + dma_read(HW_ID, 0)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - (dma_read(CAPS_0_U) << 16) | - dma_read(CAPS_0_L), - (dma_read(CAPS_1_U) << 16) | - dma_read(CAPS_1_L), - dma_read(CAPS_2), dma_read(CAPS_3), - dma_read(CAPS_4)); + dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), + dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), + dma_read(CAPS_4, 0)); if (!enable_1510_mode) { u16 w; /* Disable OMAP 3.0/3.1 compatibility mode. */ - w = dma_read(GSCR); + w = dma_read(GSCR, 0); w |= 1 << 3; - dma_write(w, GSCR); + dma_write(w, GSCR, 0); dma_chan_count = 16; } else dma_chan_count = 9; } else if (cpu_class_is_omap2()) { - u8 revision = dma_read(REVISION) & 0xff; + u8 revision = dma_read(REVISION, 0) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); dma_chan_count = dma_lch_count; @@ -2210,14 +2325,14 @@ static int __init omap_init_dma(void) if (cpu_is_omap34xx() || cpu_is_omap44xx()) { /* Enable smartidle idlemodes and autoidle */ - u32 v = dma_read(OCP_SYSCONFIG); + u32 v = dma_read(OCP_SYSCONFIG, 0); v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | DMA_SYSCONFIG_SIDLEMODE_MASK | DMA_SYSCONFIG_AUTOIDLE); v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_AUTOIDLE); - dma_write(v , OCP_SYSCONFIG); + dma_write(v , OCP_SYSCONFIG, 0); /* reserve dma channels 0 and 1 in high security devices */ if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) { diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 0cce4ca83aa0..dfb1b10dc920 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -27,136 +27,14 @@ /* Hardware registers for omap1 */ #define OMAP1_DMA_BASE (0xfffed800) -#define OMAP1_DMA_GCR 0x400 -#define OMAP1_DMA_GSCR 0x404 -#define OMAP1_DMA_GRST 0x408 -#define OMAP1_DMA_HW_ID 0x442 -#define OMAP1_DMA_PCH2_ID 0x444 -#define OMAP1_DMA_PCH0_ID 0x446 -#define OMAP1_DMA_PCH1_ID 0x448 -#define OMAP1_DMA_PCHG_ID 0x44a -#define OMAP1_DMA_PCHD_ID 0x44c -#define OMAP1_DMA_CAPS_0_U 0x44e -#define OMAP1_DMA_CAPS_0_L 0x450 -#define OMAP1_DMA_CAPS_1_U 0x452 -#define OMAP1_DMA_CAPS_1_L 0x454 -#define OMAP1_DMA_CAPS_2 0x456 -#define OMAP1_DMA_CAPS_3 0x458 -#define OMAP1_DMA_CAPS_4 0x45a -#define OMAP1_DMA_PCH2_SR 0x460 -#define OMAP1_DMA_PCH0_SR 0x480 -#define OMAP1_DMA_PCH1_SR 0x482 -#define OMAP1_DMA_PCHD_SR 0x4c0 - /* Hardware registers for omap2 and omap3 */ #define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000) #define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000) #define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000) -#define OMAP_DMA4_REVISION 0x00 -#define OMAP_DMA4_GCR 0x78 -#define OMAP_DMA4_IRQSTATUS_L0 0x08 -#define OMAP_DMA4_IRQSTATUS_L1 0x0c -#define OMAP_DMA4_IRQSTATUS_L2 0x10 -#define OMAP_DMA4_IRQSTATUS_L3 0x14 -#define OMAP_DMA4_IRQENABLE_L0 0x18 -#define OMAP_DMA4_IRQENABLE_L1 0x1c -#define OMAP_DMA4_IRQENABLE_L2 0x20 -#define OMAP_DMA4_IRQENABLE_L3 0x24 -#define OMAP_DMA4_SYSSTATUS 0x28 -#define OMAP_DMA4_OCP_SYSCONFIG 0x2c -#define OMAP_DMA4_CAPS_0 0x64 -#define OMAP_DMA4_CAPS_2 0x6c -#define OMAP_DMA4_CAPS_3 0x70 -#define OMAP_DMA4_CAPS_4 0x74 - #define OMAP1_LOGICAL_DMA_CH_COUNT 17 #define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ -/* Common channel specific registers for omap1 */ -#define OMAP1_DMA_CH_BASE(n) (0x40 * (n) + 0x00) -#define OMAP1_DMA_CSDP(n) (0x40 * (n) + 0x00) -#define OMAP1_DMA_CCR(n) (0x40 * (n) + 0x02) -#define OMAP1_DMA_CICR(n) (0x40 * (n) + 0x04) -#define OMAP1_DMA_CSR(n) (0x40 * (n) + 0x06) -#define OMAP1_DMA_CEN(n) (0x40 * (n) + 0x10) -#define OMAP1_DMA_CFN(n) (0x40 * (n) + 0x12) -#define OMAP1_DMA_CSFI(n) (0x40 * (n) + 0x14) -#define OMAP1_DMA_CSEI(n) (0x40 * (n) + 0x16) -#define OMAP1_DMA_CPC(n) (0x40 * (n) + 0x18) /* 15xx only */ -#define OMAP1_DMA_CSAC(n) (0x40 * (n) + 0x18) -#define OMAP1_DMA_CDAC(n) (0x40 * (n) + 0x1a) -#define OMAP1_DMA_CDEI(n) (0x40 * (n) + 0x1c) -#define OMAP1_DMA_CDFI(n) (0x40 * (n) + 0x1e) -#define OMAP1_DMA_CLNK_CTRL(n) (0x40 * (n) + 0x28) - -/* Common channel specific registers for omap2 */ -#define OMAP_DMA4_CH_BASE(n) (0x60 * (n) + 0x80) -#define OMAP_DMA4_CCR(n) (0x60 * (n) + 0x80) -#define OMAP_DMA4_CLNK_CTRL(n) (0x60 * (n) + 0x84) -#define OMAP_DMA4_CICR(n) (0x60 * (n) + 0x88) -#define OMAP_DMA4_CSR(n) (0x60 * (n) + 0x8c) -#define OMAP_DMA4_CSDP(n) (0x60 * (n) + 0x90) -#define OMAP_DMA4_CEN(n) (0x60 * (n) + 0x94) -#define OMAP_DMA4_CFN(n) (0x60 * (n) + 0x98) -#define OMAP_DMA4_CSEI(n) (0x60 * (n) + 0xa4) -#define OMAP_DMA4_CSFI(n) (0x60 * (n) + 0xa8) -#define OMAP_DMA4_CDEI(n) (0x60 * (n) + 0xac) -#define OMAP_DMA4_CDFI(n) (0x60 * (n) + 0xb0) -#define OMAP_DMA4_CSAC(n) (0x60 * (n) + 0xb4) -#define OMAP_DMA4_CDAC(n) (0x60 * (n) + 0xb8) - -/* Channel specific registers only on omap1 */ -#define OMAP1_DMA_CSSA_L(n) (0x40 * (n) + 0x08) -#define OMAP1_DMA_CSSA_U(n) (0x40 * (n) + 0x0a) -#define OMAP1_DMA_CDSA_L(n) (0x40 * (n) + 0x0c) -#define OMAP1_DMA_CDSA_U(n) (0x40 * (n) + 0x0e) -#define OMAP1_DMA_COLOR_L(n) (0x40 * (n) + 0x20) -#define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22) -#define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24) -#define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */ -#define OMAP1_DMA_CCEN(n) 0 -#define OMAP1_DMA_CCFN(n) 0 - -/* Channel specific registers only on omap2 */ -#define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c) -#define OMAP_DMA4_CDSA(n) (0x60 * (n) + 0xa0) -#define OMAP_DMA4_CCEN(n) (0x60 * (n) + 0xbc) -#define OMAP_DMA4_CCFN(n) (0x60 * (n) + 0xc0) -#define OMAP_DMA4_COLOR(n) (0x60 * (n) + 0xc4) - -/* Additional registers available on OMAP4 */ -#define OMAP_DMA4_CDP(n) (0x60 * (n) + 0xd0) -#define OMAP_DMA4_CNDP(n) (0x60 * (n) + 0xd4) -#define OMAP_DMA4_CCDN(n) (0x60 * (n) + 0xd8) - -/* Dummy defines to keep multi-omap compiles happy */ -#define OMAP1_DMA_REVISION 0 -#define OMAP1_DMA_IRQSTATUS_L0 0 -#define OMAP1_DMA_IRQENABLE_L0 0 -#define OMAP1_DMA_OCP_SYSCONFIG 0 -#define OMAP_DMA4_HW_ID 0 -#define OMAP_DMA4_CAPS_0_L 0 -#define OMAP_DMA4_CAPS_0_U 0 -#define OMAP_DMA4_CAPS_1_L 0 -#define OMAP_DMA4_CAPS_1_U 0 -#define OMAP_DMA4_GSCR 0 -#define OMAP_DMA4_CPC(n) 0 - -#define OMAP_DMA4_LCH_CTRL(n) 0 -#define OMAP_DMA4_COLOR_L(n) 0 -#define OMAP_DMA4_COLOR_U(n) 0 -#define OMAP_DMA4_CCR2(n) 0 -#define OMAP1_DMA_CSSA(n) 0 -#define OMAP1_DMA_CDSA(n) 0 -#define OMAP_DMA4_CSSA_L(n) 0 -#define OMAP_DMA4_CSSA_U(n) 0 -#define OMAP_DMA4_CDSA_L(n) 0 -#define OMAP_DMA4_CDSA_U(n) 0 -#define OMAP1_DMA_COLOR(n) 0 - -/*----------------------------------------------------------------------------*/ - /* DMA channels for omap1 */ #define OMAP_DMA_NO_DEVICE 0 #define OMAP_DMA_MCSI1_TX 1 @@ -405,6 +283,35 @@ #define DMA_CH_PRIO_HIGH 0x1 #define DMA_CH_PRIO_LOW 0x0 /* Def */ +enum omap_reg_offsets { + +GCR, GSCR, GRST1, HW_ID, +PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID, +PCHD_ID, CAPS_0, CAPS_1, CAPS_2, +CAPS_3, CAPS_4, PCH2_SR, PCH0_SR, +PCH1_SR, PCHD_SR, REVISION, IRQSTATUS_L0, +IRQSTATUS_L1, IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, +IRQENABLE_L1, IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, +OCP_SYSCONFIG, + +/* omap1+ specific */ +CPC, CCR2, LCH_CTRL, + +/* Common registers for all omap's */ +CSDP, CCR, CICR, CSR, +CEN, CFN, CSFI, CSEI, +CSAC, CDAC, CDEI, +CDFI, CLNK_CTRL, + +/* Channel specific registers */ +CSSA, CDSA, COLOR, +CCEN, CCFN, + +/* omap3630 and omap4 specific */ +CDP, CNDP, CCDN, + +}; + enum omap_dma_burst_mode { OMAP_DMA_DATA_BURST_DIS = 0, OMAP_DMA_DATA_BURST_4, From d3c9be2f42223f256d06b2b69ed26afdcb02f64a Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: [PATCH 2/9] OMAP: DMA: Introduce errata handling feature Implement errata handling to use flags instead of cpu_is_* and cpu_class_* in the code. The errata flags are initialized at init time and during runtime we are using the errata variable (via the IS_DMA_ERRATA macro) to execute the required errata workaround. Reused errata handling patch from: Peter Ujfalusi https://patchwork.kernel.org/patch/231191/ Changes to above patch: 1. Changes are done for converting all the existing errata work arounds to use this feature. 2. Detailed description for each errata is added. 3. Fixed bug in SET_DMA_ERRATA macro 4. Bit shifting in macro definitions are replaced with BIT() macro Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 152 +++++++++++++++++--------- arch/arm/plat-omap/include/plat/dma.h | 12 ++ 2 files changed, 114 insertions(+), 50 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 49a7cd4763f9..6f51bf37ec02 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -144,6 +144,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) static int enable_1510_mode; +static u32 errata; static struct omap_dma_global_context_registers { u32 dma_irqenable_l0; @@ -1088,31 +1089,17 @@ void omap_start_dma(int lch) cur_lch = next_lch; } while (next_lch != -1); - } else if (cpu_is_omap242x() || - (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) { - - /* Errata: Need to write lch even if not using chaining */ + } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) dma_write(lch, CLNK_CTRL, lch); - } omap_enable_channel_irq(lch); l = dma_read(CCR, lch); - /* - * Errata: Inter Frame DMA buffering issue (All OMAP2420 and - * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and - * bursting is enabled. This might result in data gets stalled in - * FIFO at the end of the block. - * Workaround: DMA channels must have BUFFERING_DISABLED bit set to - * guarantee no data will stay in the DMA FIFO in case inter frame - * buffering occurs. - */ - if (cpu_is_omap2420() || - (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) - l |= OMAP_DMA_CCR_BUFFERING_DISABLE; - + if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) + l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; + dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; @@ -1128,8 +1115,8 @@ void omap_stop_dma(int lch) dma_write(0, CICR, lch); l = dma_read(CCR, lch); - /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ - if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { + if (IS_DMA_ERRATA(DMA_ERRATA_i541) && + (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; @@ -1229,11 +1216,7 @@ dma_addr_t omap_get_dma_src_pos(int lch) else offset = dma_read(CSAC, lch); - /* - * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!cpu_is_omap15xx() && offset == 0) + if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) offset = dma_read(CSAC, lch); if (cpu_class_is_omap1()) @@ -1814,7 +1797,7 @@ int omap_stop_dma_chain_transfers(int chain_id) { int *channels; u32 l, i; - u32 sys_cf; + u32 sys_cf = 0; /* Check for input params */ if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1829,15 +1812,13 @@ int omap_stop_dma_chain_transfers(int chain_id) } channels = dma_linked_lch[chain_id].linked_dmach_q; - /* - * DMA Errata: - * Special programming model needed to disable DMA before end of block - */ - sys_cf = dma_read(OCP_SYSCONFIG, 0); - l = sys_cf; - /* Middle mode reg set no Standby */ - l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG, 0); + if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { + sys_cf = dma_read(OCP_SYSCONFIG, 0); + l = sys_cf; + /* Middle mode reg set no Standby */ + l &= ~((1 << 12)|(1 << 13)); + dma_write(l, OCP_SYSCONFIG, 0); + } for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { @@ -1856,8 +1837,8 @@ int omap_stop_dma_chain_transfers(int chain_id) /* Reset the Queue pointers */ OMAP_DMA_CHAIN_QINIT(chain_id); - /* Errata - put in the old value */ - dma_write(sys_cf, OCP_SYSCONFIG, 0); + if (IS_DMA_ERRATA(DMA_ERRATA_i88)) + dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -2063,12 +2044,7 @@ static int omap2_dma_handle_ch(int ch) if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) { printk(KERN_INFO "DMA transaction error with device %d\n", dma_chan[ch].dev_id); - if (cpu_class_is_omap2()) { - /* - * Errata: sDMA Channel is not disabled - * after a transaction error. So we explicitely - * disable the channel - */ + if (IS_DMA_ERRATA(DMA_ERRATA_i378)) { u32 ccr; ccr = dma_read(CCR, ch); @@ -2168,13 +2144,7 @@ void omap_dma_global_context_restore(void) dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0, 0); - /* - * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared - * after secure sram context save and restore. Hence we need to - * manually clear those IRQs to avoid spurious interrupts. This - * affects only secure devices. - */ - if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) @@ -2182,6 +2152,87 @@ void omap_dma_global_context_restore(void) omap_clear_dma(ch); } +static void configure_dma_errata(void) +{ + + /* + * Errata applicable for OMAP2430ES1.0 and all omap2420 + * + * I. + * Erratum ID: Not Available + * Inter Frame DMA buffering issue DMA will wrongly + * buffer elements if packing and bursting is enabled. This might + * result in data gets stalled in FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs + * + * II. + * Erratum ID: Not Available + * DMA may hang when several channels are used in parallel + * In the following configuration, DMA channel hanging can occur: + * a. Channel i, hardware synchronized, is enabled + * b. Another channel (Channel x), software synchronized, is enabled. + * c. Channel i is disabled before end of transfer + * d. Channel i is reenabled. + * e. Steps 1 to 4 are repeated a certain number of times. + * f. A third channel (Channel y), software synchronized, is enabled. + * Channel x and Channel y may hang immediately after step 'f'. + * Workaround: + * For any channel used - make sure NextLCH_ID is set to the value j. + */ + if (cpu_is_omap2420() || (cpu_is_omap2430() && + (omap_type() == OMAP2430_REV_ES1_0))) { + SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); + SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); + } + + /* + * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled + * after a transaction error. + * Workaround: SW should explicitely disable the channel. + */ + if (cpu_class_is_omap2()) + SET_DMA_ERRATA(DMA_ERRATA_i378); + + /* + * Erratum ID: i541: sDMA FIFO draining does not finish + * If sDMA channel is disabled on the fly, sDMA enters standby even + * through FIFO Drain is still in progress + * Workaround: Put sDMA in NoStandby more before a logical channel is + * disabled, then put it back to SmartStandby right after the channel + * finishes FIFO draining. + */ + if (cpu_is_omap34xx()) + SET_DMA_ERRATA(DMA_ERRATA_i541); + + /* + * Erratum ID: i88 : Special programming model needed to disable DMA + * before end of block. + * Workaround: software must ensure that the DMA is configured in No + * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") + */ + if (cpu_is_omap34xx() && (omap_type() == OMAP3430_REV_ES1_0)) + SET_DMA_ERRATA(DMA_ERRATA_i88); + + /* + * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + if (!cpu_is_omap15xx()) + SET_DMA_ERRATA(DMA_ERRATA_3_3); + + /* + * Erratum ID: Not Available + * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared + * after secure sram context save and restore. + * Work around: Hence we need to manually clear those IRQs to avoid + * spurious interrupts. This affects only secure devices. + */ + if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + SET_DMA_ERRATA(DMA_ROMCODE_BUG); +} + /*----------------------------------------------------------------------------*/ static int __init omap_init_dma(void) @@ -2342,6 +2393,7 @@ static int __init omap_init_dma(void) dma_chan[1].dev_id = 1; } } + configure_dma_errata(); return 0; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index dfb1b10dc920..23783990eb9a 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -283,6 +283,18 @@ #define DMA_CH_PRIO_HIGH 0x1 #define DMA_CH_PRIO_LOW 0x0 /* Def */ +/* Errata handling */ +#define IS_DMA_ERRATA(id) (errata & (id)) +#define SET_DMA_ERRATA(id) (errata |= (id)) + +#define DMA_ERRATA_IFRAME_BUFFERING BIT(0x0) +#define DMA_ERRATA_PARALLEL_CHANNELS BIT(0x1) +#define DMA_ERRATA_i378 BIT(0x2) +#define DMA_ERRATA_i541 BIT(0x3) +#define DMA_ERRATA_i88 BIT(0x4) +#define DMA_ERRATA_3_3 BIT(0x5) +#define DMA_ROMCODE_BUG BIT(0x6) + enum omap_reg_offsets { GCR, GSCR, GRST1, HW_ID, From 745685df95961ebbf0bcafcf28f31217a75070ae Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: [PATCH 3/9] OMAP2420: hwmod data: add system DMA Add OMAP2420 DMA hwmod data and also add required DMA device attributes. Signed-off-by: G, Manjunath Kondaiah Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 86 ++++++++++++++++++++++ arch/arm/plat-omap/include/plat/dma.h | 11 +++ 2 files changed, 97 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index d95342599793..42606f6b0cdf 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -42,6 +42,7 @@ static struct omap_hwmod omap2420_gpio1_hwmod; static struct omap_hwmod omap2420_gpio2_hwmod; static struct omap_hwmod omap2420_gpio3_hwmod; static struct omap_hwmod omap2420_gpio4_hwmod; +static struct omap_hwmod omap2420_dma_system_hwmod; /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = { @@ -779,6 +780,88 @@ static struct omap_hwmod omap2420_gpio4_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), }; +/* system dma */ +static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | + SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | + SYSC_HAS_AUTOIDLE), + .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_dma_hwmod_class = { + .name = "dma", + .sysc = &omap2420_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32, + .lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = { + .master = &omap2420_dma_system_hwmod, + .slave = &omap2420_l3_main_hwmod, + .clk = "core_l3_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = { + &omap2420_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dma_system_hwmod, + .clk = "sdma_ick", + .addr = omap2420_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = { + &omap2420_l4_core__dma_system, +}; + +static struct omap_hwmod omap2420_dma_system_hwmod = { + .name = "dma", + .class = &omap2420_dma_hwmod_class, + .mpu_irqs = omap2420_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dma_system_irqs), + .main_clk = "core_l3_ck", + .slaves = omap2420_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dma_system_slaves), + .masters = omap2420_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap2420_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_l3_main_hwmod, &omap2420_l4_core_hwmod, @@ -797,6 +880,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_gpio2_hwmod, &omap2420_gpio3_hwmod, &omap2420_gpio4_hwmod, + + /* dma_system class*/ + &omap2420_dma_system_hwmod, NULL, }; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 23783990eb9a..c4665669a8a3 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -295,6 +295,13 @@ #define DMA_ERRATA_3_3 BIT(0x5) #define DMA_ROMCODE_BUG BIT(0x6) +/* Attributes for OMAP DMA Contrller */ +#define DMA_LINKED_LCH BIT(0x0) +#define GLOBAL_PRIORITY BIT(0x1) +#define RESERVE_CHANNEL BIT(0x2) +#define IS_CSSA_32 BIT(0x3) +#define IS_CDSA_32 BIT(0x4) + enum omap_reg_offsets { GCR, GSCR, GRST1, HW_ID, @@ -389,6 +396,10 @@ struct omap_dma_channel_params { #endif }; +struct omap_dma_dev_attr { + u32 dev_caps; + u16 lch_count; +}; extern void omap_set_dma_priority(int lch, int dst_port, int priority); extern int omap_request_dma(int dev_id, const char *dev_name, From 82cbd1aebafd126f40a8ed0725a6feb6ed710576 Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: [PATCH 4/9] OMAP2430: hwmod data: add system DMA Add OMAP2430 DMA hwmod data and also add required DMA device attributes. Signed-off-by: G, Manjunath Kondaiah Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 86 ++++++++++++++++++++++ arch/arm/plat-omap/include/plat/dma.h | 1 + 2 files changed, 87 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index f68409e9fd3e..c893e00b6544 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -43,6 +43,7 @@ static struct omap_hwmod omap2430_gpio2_hwmod; static struct omap_hwmod omap2430_gpio3_hwmod; static struct omap_hwmod omap2430_gpio4_hwmod; static struct omap_hwmod omap2430_gpio5_hwmod; +static struct omap_hwmod omap2430_dma_system_hwmod; /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = { @@ -840,6 +841,88 @@ static struct omap_hwmod omap2430_gpio5_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), }; +/* dma_system */ +static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | + SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | + SYSC_HAS_AUTOIDLE), + .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_dma_hwmod_class = { + .name = "dma", + .sysc = &omap2430_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = { + .master = &omap2430_dma_system_hwmod, + .slave = &omap2430_l3_main_hwmod, + .clk = "core_l3_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = { + &omap2430_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dma_system_hwmod, + .clk = "sdma_ick", + .addr = omap2430_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = { + &omap2430_l4_core__dma_system, +}; + +static struct omap_hwmod omap2430_dma_system_hwmod = { + .name = "dma", + .class = &omap2430_dma_hwmod_class, + .mpu_irqs = omap2430_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dma_system_irqs), + .main_clk = "core_l3_ck", + .slaves = omap2430_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dma_system_slaves), + .masters = omap2430_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap2430_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_l3_main_hwmod, &omap2430_l4_core_hwmod, @@ -859,6 +942,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_gpio3_hwmod, &omap2430_gpio4_hwmod, &omap2430_gpio5_hwmod, + + /* dma_system class*/ + &omap2430_dma_system_hwmod, NULL, }; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index c4665669a8a3..4b51d2b93b0e 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -301,6 +301,7 @@ #define RESERVE_CHANNEL BIT(0x2) #define IS_CSSA_32 BIT(0x3) #define IS_CDSA_32 BIT(0x4) +#define IS_RW_PRIORITY BIT(0x5) enum omap_reg_offsets { From 01438ab6a49b63ef02b2eb44b63345a09792f982 Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: [PATCH 5/9] OMAP3: hwmod data: add system DMA Add OMAP3 DMA hwmod data Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 2687be10d7aa..d5acb63ba9e0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -52,6 +52,8 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod; static struct omap_hwmod omap3xxx_gpio5_hwmod; static struct omap_hwmod omap3xxx_gpio6_hwmod; +static struct omap_hwmod omap3xxx_dma_system_hwmod; + /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = { .master = &omap3xxx_l3_main_hwmod, @@ -1090,6 +1092,98 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = { + .master = &omap3xxx_dma_system_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "core_l3_ick", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_dma_hwmod_class = { + .name = "dma", + .sysc = &omap3xxx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = { + &omap3xxx_dma_system__l3, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dma_system_hwmod, + .clk = "core_l4_ick", + .addr = omap3xxx_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = { + &omap3xxx_l4_core__dma_system, +}; + +static struct omap_hwmod omap3xxx_dma_system_hwmod = { + .name = "dma", + .class = &omap3xxx_dma_hwmod_class, + .mpu_irqs = omap3xxx_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dma_system_irqs), + .main_clk = "core_l3_ick", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_ST_SDMA_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_ST_SDMA_SHIFT, + }, + }, + .slaves = omap3xxx_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dma_system_slaves), + .masters = omap3xxx_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap3xxx_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_l3_main_hwmod, &omap3xxx_l4_core_hwmod, @@ -1113,6 +1207,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_gpio4_hwmod, &omap3xxx_gpio5_hwmod, &omap3xxx_gpio6_hwmod, + + /* dma_system class*/ + &omap3xxx_dma_system_hwmod, NULL, }; From 531ce0d57caf7e49073608873de6976558fd7e4f Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: [PATCH 6/9] OMAP4: hwmod data: add system DMA Add OMAP4 DMA hwmod data. In addition to original dma hwmod data, the following changes are added. 1. DMA device attributes structure is introduced for diffenrenciating OMAP cpu's based on DMA features. Signed-off-by: Benoit Cousson Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index d258936410fb..f9778fba8322 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "omap_hwmod_common_data.h" @@ -36,6 +37,7 @@ #define OMAP44XX_DMA_REQ_START 1 /* Backward references (IPs with Bus Master capability) */ +static struct omap_hwmod omap44xx_dma_system_hwmod; static struct omap_hwmod omap44xx_dmm_hwmod; static struct omap_hwmod omap44xx_emif_fw_hwmod; static struct omap_hwmod omap44xx_l3_instr_hwmod; @@ -216,6 +218,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* dma_system -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = { + .master = &omap44xx_dma_system_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_cfg -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = { .master = &omap44xx_l4_cfg_hwmod, @@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = { /* l3_main_2 slave ports */ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = { + &omap44xx_dma_system__l3_main_2, &omap44xx_l3_main_1__l3_main_2, &omap44xx_l4_cfg__l3_main_2, }; @@ -1376,6 +1387,93 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_gpio6_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; + +/* + * 'dma' class + * dma controller for data exchange between memory to memory (i.e. internal or + * external memory) and gp peripherals to memory or memory to gp peripherals + */ + +static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_class omap44xx_dma_hwmod_class = { + .name = "dma", + .sysc = &omap44xx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = { + { .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START }, + { .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START }, + { .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START }, + { .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START }, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = { + &omap44xx_dma_system__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = { + { + .pa_start = 0x4a056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_dma_system_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = { + &omap44xx_l4_cfg__dma_system, +}; + +static struct omap_hwmod omap44xx_dma_system_hwmod = { + .name = "dma_system", + .class = &omap44xx_dma_hwmod_class, + .mpu_irqs = omap44xx_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dma_system_irqs), + .main_clk = "l3_div_ck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL, + }, + }, + .slaves = omap44xx_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dma_system_slaves), + .masters = omap44xx_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* dmm class */ &omap44xx_dmm_hwmod, @@ -1391,6 +1489,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_l4_cfg_hwmod, &omap44xx_l4_per_hwmod, &omap44xx_l4_wkup_hwmod, + + /* dma class */ + &omap44xx_dma_system_hwmod, + /* i2c class */ &omap44xx_i2c1_hwmod, &omap44xx_i2c2_hwmod, From 6568f7c43a72f9631910e26092ef3ecf67cc99eb Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: [PATCH 7/9] OMAP1: DMA: Implement in platform device model Implement OMAP1 DMA as platform device and add support for registering through platform device layer using resource structures. Signed-off-by: G, Manjunath Kondaiah Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/dma.c | 179 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 arch/arm/mach-omap1/dma.c diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c new file mode 100644 index 000000000000..120eff707ab2 --- /dev/null +++ b/arch/arm/mach-omap1/dma.c @@ -0,0 +1,179 @@ +/* + * OMAP1/OMAP7xx - specific DMA driver + * + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä + * DMA channel linking for 1610 by Samuel Ortiz + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into platform driver + * - G, Manjunath Kondaiah + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define OMAP1_DMA_BASE (0xfffed800) + +static struct resource res[] __initdata = { + [0] = { + .start = OMAP1_DMA_BASE, + .end = OMAP1_DMA_BASE + SZ_2K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "0", + .start = INT_DMA_CH0_6, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .name = "1", + .start = INT_DMA_CH1_7, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .name = "2", + .start = INT_DMA_CH2_8, + .flags = IORESOURCE_IRQ, + }, + [4] = { + .name = "3", + .start = INT_DMA_CH3, + .flags = IORESOURCE_IRQ, + }, + [5] = { + .name = "4", + .start = INT_DMA_CH4, + .flags = IORESOURCE_IRQ, + }, + [6] = { + .name = "5", + .start = INT_DMA_CH5, + .flags = IORESOURCE_IRQ, + }, + [7] = { + .name = "6", + .start = INT_1610_DMA_CH6, + .flags = IORESOURCE_IRQ, + }, + /* irq's for omap16xx and omap7xx */ + [8] = { + .name = "7", + .start = INT_1610_DMA_CH7, + .flags = IORESOURCE_IRQ, + }, + [9] = { + .name = "8", + .start = INT_1610_DMA_CH8, + .flags = IORESOURCE_IRQ, + }, + [10] = { + .name = "9", + .start = INT_1610_DMA_CH9, + .flags = IORESOURCE_IRQ, + }, + [11] = { + .name = "10", + .start = INT_1610_DMA_CH10, + .flags = IORESOURCE_IRQ, + }, + [12] = { + .name = "11", + .start = INT_1610_DMA_CH11, + .flags = IORESOURCE_IRQ, + }, + [13] = { + .name = "12", + .start = INT_1610_DMA_CH12, + .flags = IORESOURCE_IRQ, + }, + [14] = { + .name = "13", + .start = INT_1610_DMA_CH13, + .flags = IORESOURCE_IRQ, + }, + [15] = { + .name = "14", + .start = INT_1610_DMA_CH14, + .flags = IORESOURCE_IRQ, + }, + [16] = { + .name = "15", + .start = INT_1610_DMA_CH15, + .flags = IORESOURCE_IRQ, + }, + [17] = { + .name = "16", + .start = INT_DMA_LCD, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init omap1_system_dma_init(void) +{ + struct omap_system_dma_plat_info *p; + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc("omap_dma_system", 0); + if (!pdev) { + pr_err("%s: Unable to device alloc for dma\n", + __func__); + return -ENOMEM; + } + + ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); + if (ret) { + dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", + __func__, pdev->name, pdev->id); + goto exit_device_del; + } + + p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); + if (!p) { + dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", + __func__, pdev->name); + ret = -ENOMEM; + goto exit_device_put; + } + + ret = platform_device_add_data(pdev, p, sizeof(*p)); + if (ret) { + dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", + __func__, pdev->name, pdev->id); + goto exit_device_put; + } + + ret = platform_device_add(pdev); + if (ret) { + dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", + __func__, pdev->name, pdev->id); + goto exit_device_put; + } + + return ret; + +exit_device_put: + platform_device_put(pdev); +exit_device_del: + platform_device_del(pdev); + + return ret; +} +arch_initcall(omap1_system_dma_init); From 59de3cf1ce9a961ba9ab657707727db2111e72fa Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: [PATCH 8/9] OMAP2+: DMA: hwmod: Device registration Prepare OMAP2+ DMA to use hwmod infrastructure so that DMA can register as platform device. Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/dma.c | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 arch/arm/mach-omap2/dma.c diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c new file mode 100644 index 000000000000..2130059e98cb --- /dev/null +++ b/arch/arm/mach-omap2/dma.c @@ -0,0 +1,74 @@ +/* + * OMAP2+ DMA driver + * + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä + * DMA channel linking for 1610 by Samuel Ortiz + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into platform driver + * - G, Manjunath Kondaiah + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct omap_device_pm_latency omap2_dma_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +/* One time initializations */ +static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) +{ + struct omap_device *od; + struct omap_system_dma_plat_info *p; + char *name = "omap_dma_system"; + + p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); + if (!p) { + pr_err("%s: Unable to allocate pdata for %s:%s\n", + __func__, name, oh->name); + return -ENOMEM; + } + + od = omap_device_build(name, 0, oh, p, sizeof(*p), + omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0); + kfree(p); + if (IS_ERR(od)) { + pr_err("%s: Cant build omap_device for %s:%s.\n", + __func__, name, oh->name); + return IS_ERR(od); + } + + return 0; +} + +static int __init omap2_system_dma_init(void) +{ + return omap_hwmod_for_each_by_class("dma", + omap2_system_dma_init_dev, NULL); +} +arch_initcall(omap2_system_dma_init); From f31cc9622d75c1c6f041d786698daa425c0425c2 Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: [PATCH 9/9] OMAP: DMA: Convert DMA library into platform driver Convert DMA library into DMA platform driver and make use of platform data provided by hwmod data base for OMAP2+ onwards. For OMAP1 processors, the DMA driver in mach-omap uses resource structures for getting platform data. Thanks to Tony Lindgren for fixing various omap1 issues and testing the same on OSK5912 board. Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Makefile | 2 +- arch/arm/mach-omap1/dma.c | 215 ++++++- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/dma.c | 223 +++++++ arch/arm/plat-omap/dma.c | 822 +++++++++----------------- arch/arm/plat-omap/include/plat/dma.h | 57 +- 6 files changed, 755 insertions(+), 566 deletions(-) diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 0b1c07ffa2f1..6ee19504845f 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o +obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o obj-y += clock.o clock_data.o opp_data.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 120eff707ab2..d8559344c6e2 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -30,6 +30,57 @@ #include #define OMAP1_DMA_BASE (0xfffed800) +#define OMAP1_LOGICAL_DMA_CH_COUNT 17 +#define OMAP1_DMA_STRIDE 0x40 + +static u32 errata; +static u32 enable_1510_mode; +static u8 dma_stride; +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; + +static u16 reg_map[] = { + [GCR] = 0x400, + [GSCR] = 0x404, + [GRST1] = 0x408, + [HW_ID] = 0x442, + [PCH2_ID] = 0x444, + [PCH0_ID] = 0x446, + [PCH1_ID] = 0x448, + [PCHG_ID] = 0x44a, + [PCHD_ID] = 0x44c, + [CAPS_0] = 0x44e, + [CAPS_1] = 0x452, + [CAPS_2] = 0x456, + [CAPS_3] = 0x458, + [CAPS_4] = 0x45a, + [PCH2_SR] = 0x460, + [PCH0_SR] = 0x480, + [PCH1_SR] = 0x482, + [PCHD_SR] = 0x4c0, + + /* Common Registers */ + [CSDP] = 0x00, + [CCR] = 0x02, + [CICR] = 0x04, + [CSR] = 0x06, + [CEN] = 0x10, + [CFN] = 0x12, + [CSFI] = 0x14, + [CSEI] = 0x16, + [CPC] = 0x18, /* 15xx only */ + [CSAC] = 0x18, + [CDAC] = 0x1a, + [CDEI] = 0x1c, + [CDFI] = 0x1e, + [CLNK_CTRL] = 0x28, + + /* Channel specific register offsets */ + [CSSA] = 0x08, + [CDSA] = 0x0c, + [COLOR] = 0x20, + [CCR2] = 0x24, + [LCH_CTRL] = 0x2a, +}; static struct resource res[] __initdata = { [0] = { @@ -67,6 +118,7 @@ static struct resource res[] __initdata = { .start = INT_DMA_CH5, .flags = IORESOURCE_IRQ, }, + /* Handled in lcd_dma.c */ [7] = { .name = "6", .start = INT_1610_DMA_CH6, @@ -125,9 +177,100 @@ static struct resource res[] __initdata = { }, }; +static void __iomem *dma_base; +static inline void dma_write(u32 val, int reg, int lch) +{ + u8 stride; + u32 offset; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + __raw_writew(val, dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + __raw_writew(val >> 16, dma_base + offset2); + } +} + +static inline u32 dma_read(int reg, int lch) +{ + u8 stride; + u32 offset, val; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + val = __raw_readw(dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u16 upper; + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + upper = __raw_readw(dma_base + offset2); + val |= (upper << 16); + } + return val; +} + +static void omap1_clear_lch_regs(int lch) +{ + int i = dma_common_ch_start; + + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); +} + +static void omap1_clear_dma(int lch) +{ + u32 l; + + l = dma_read(CCR, lch); + l &= ~OMAP_DMA_CCR_EN; + dma_write(l, CCR, lch); + + /* Clear pending interrupts */ + l = dma_read(CSR, lch); +} + +static void omap1_show_dma_caps(void) +{ + if (enable_1510_mode) { + printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); + } else { + u16 w; + printk(KERN_INFO "OMAP DMA hardware version %d\n", + dma_read(HW_ID, 0)); + printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", + dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), + dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), + dma_read(CAPS_4, 0)); + + /* Disable OMAP 3.0/3.1 compatibility mode. */ + w = dma_read(GSCR, 0); + w |= 1 << 3; + dma_write(w, GSCR, 0); + } + return; +} + +static u32 configure_dma_errata(void) +{ + + /* + * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + if (!cpu_is_omap15xx()) + SET_DMA_ERRATA(DMA_ERRATA_3_3); + + return errata; +} + static int __init omap1_system_dma_init(void) { struct omap_system_dma_plat_info *p; + struct omap_dma_dev_attr *d; struct platform_device *pdev; int ret; @@ -138,6 +281,12 @@ static int __init omap1_system_dma_init(void) return -ENOMEM; } + dma_base = ioremap(res[0].start, resource_size(&res[0])); + if (!dma_base) { + pr_err("%s: Unable to ioremap\n", __func__); + return -ENODEV; + } + ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", @@ -153,22 +302,84 @@ static int __init omap1_system_dma_init(void) goto exit_device_put; } + d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); + if (!d) { + dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", + __func__, pdev->name); + ret = -ENOMEM; + goto exit_release_p; + } + + d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; + + /* Valid attributes for omap1 plus processors */ + if (cpu_is_omap15xx()) + d->dev_caps = ENABLE_1510_MODE; + enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; + + d->dev_caps |= SRC_PORT; + d->dev_caps |= DST_PORT; + d->dev_caps |= SRC_INDEX; + d->dev_caps |= DST_INDEX; + d->dev_caps |= IS_BURST_ONLY4; + d->dev_caps |= CLEAR_CSR_ON_READ; + d->dev_caps |= IS_WORD_16; + + + d->chan = kzalloc(sizeof(struct omap_dma_lch) * + (d->lch_count), GFP_KERNEL); + if (!d->chan) { + dev_err(&pdev->dev, "%s: Memory allocation failed" + "for d->chan!!!\n", __func__); + goto exit_release_d; + } + + if (cpu_is_omap15xx()) + d->chan_count = 9; + else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { + if (!(d->dev_caps & ENABLE_1510_MODE)) + d->chan_count = 16; + else + d->chan_count = 9; + } + + p->dma_attr = d; + + p->show_dma_caps = omap1_show_dma_caps; + p->clear_lch_regs = omap1_clear_lch_regs; + p->clear_dma = omap1_clear_dma; + p->dma_write = dma_write; + p->dma_read = dma_read; + p->disable_irq_lch = NULL; + + p->errata = configure_dma_errata(); + ret = platform_device_add_data(pdev, p, sizeof(*p)); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_device_put; + goto exit_release_chan; } ret = platform_device_add(pdev); if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_device_put; + goto exit_release_chan; } + dma_stride = OMAP1_DMA_STRIDE; + dma_common_ch_start = CPC; + dma_common_ch_end = COLOR; + return ret; +exit_release_chan: + kfree(d->chan); +exit_release_d: + kfree(d); +exit_release_p: + kfree(p); exit_device_put: platform_device_put(pdev); exit_device_del: diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 25bc9453700d..1538e32637b9 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \ - common.o gpio.o + common.o gpio.o dma.o omap-2-3-common = irq.o sdrc.o prm2xxx_3xxx.o hwmod-common = omap_hwmod.o \ diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 2130059e98cb..d2f15f5cfd36 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -32,6 +32,61 @@ #include #include +#define OMAP2_DMA_STRIDE 0x60 + +static u32 errata; +static u8 dma_stride; + +static struct omap_dma_dev_attr *d; + +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; + +static u16 reg_map[] = { + [REVISION] = 0x00, + [GCR] = 0x78, + [IRQSTATUS_L0] = 0x08, + [IRQSTATUS_L1] = 0x0c, + [IRQSTATUS_L2] = 0x10, + [IRQSTATUS_L3] = 0x14, + [IRQENABLE_L0] = 0x18, + [IRQENABLE_L1] = 0x1c, + [IRQENABLE_L2] = 0x20, + [IRQENABLE_L3] = 0x24, + [SYSSTATUS] = 0x28, + [OCP_SYSCONFIG] = 0x2c, + [CAPS_0] = 0x64, + [CAPS_2] = 0x6c, + [CAPS_3] = 0x70, + [CAPS_4] = 0x74, + + /* Common register offsets */ + [CCR] = 0x80, + [CLNK_CTRL] = 0x84, + [CICR] = 0x88, + [CSR] = 0x8c, + [CSDP] = 0x90, + [CEN] = 0x94, + [CFN] = 0x98, + [CSEI] = 0xa4, + [CSFI] = 0xa8, + [CDEI] = 0xac, + [CDFI] = 0xb0, + [CSAC] = 0xb4, + [CDAC] = 0xb8, + + /* Channel specific register offsets */ + [CSSA] = 0x9c, + [CDSA] = 0xa0, + [CCEN] = 0xbc, + [CCFN] = 0xc0, + [COLOR] = 0xc4, + + /* OMAP4 specific registers */ + [CDP] = 0xd0, + [CNDP] = 0xd4, + [CCDN] = 0xd8, +}; + static struct omap_device_pm_latency omap2_dma_latency[] = { { .deactivate_func = omap_device_idle_hwmods, @@ -40,13 +95,151 @@ static struct omap_device_pm_latency omap2_dma_latency[] = { }, }; +static void __iomem *dma_base; +static inline void dma_write(u32 val, int reg, int lch) +{ + u8 stride; + u32 offset; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + __raw_writel(val, dma_base + offset); +} + +static inline u32 dma_read(int reg, int lch) +{ + u8 stride; + u32 offset, val; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + val = __raw_readl(dma_base + offset); + return val; +} + +static inline void omap2_disable_irq_lch(int lch) +{ + u32 val; + + val = dma_read(IRQENABLE_L0, lch); + val &= ~(1 << lch); + dma_write(val, IRQENABLE_L0, lch); +} + +static void omap2_clear_dma(int lch) +{ + int i = dma_common_ch_start; + + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); +} + +static void omap2_show_dma_caps(void) +{ + u8 revision = dma_read(REVISION, 0) & 0xff; + printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", + revision >> 4, revision & 0xf); + return; +} + +static u32 configure_dma_errata(void) +{ + + /* + * Errata applicable for OMAP2430ES1.0 and all omap2420 + * + * I. + * Erratum ID: Not Available + * Inter Frame DMA buffering issue DMA will wrongly + * buffer elements if packing and bursting is enabled. This might + * result in data gets stalled in FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs + * + * II. + * Erratum ID: Not Available + * DMA may hang when several channels are used in parallel + * In the following configuration, DMA channel hanging can occur: + * a. Channel i, hardware synchronized, is enabled + * b. Another channel (Channel x), software synchronized, is enabled. + * c. Channel i is disabled before end of transfer + * d. Channel i is reenabled. + * e. Steps 1 to 4 are repeated a certain number of times. + * f. A third channel (Channel y), software synchronized, is enabled. + * Channel x and Channel y may hang immediately after step 'f'. + * Workaround: + * For any channel used - make sure NextLCH_ID is set to the value j. + */ + if (cpu_is_omap2420() || (cpu_is_omap2430() && + (omap_type() == OMAP2430_REV_ES1_0))) { + + SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); + SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); + } + + /* + * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled + * after a transaction error. + * Workaround: SW should explicitely disable the channel. + */ + if (cpu_class_is_omap2()) + SET_DMA_ERRATA(DMA_ERRATA_i378); + + /* + * Erratum ID: i541: sDMA FIFO draining does not finish + * If sDMA channel is disabled on the fly, sDMA enters standby even + * through FIFO Drain is still in progress + * Workaround: Put sDMA in NoStandby more before a logical channel is + * disabled, then put it back to SmartStandby right after the channel + * finishes FIFO draining. + */ + if (cpu_is_omap34xx()) + SET_DMA_ERRATA(DMA_ERRATA_i541); + + /* + * Erratum ID: i88 : Special programming model needed to disable DMA + * before end of block. + * Workaround: software must ensure that the DMA is configured in No + * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") + */ + if (omap_type() == OMAP3430_REV_ES1_0) + SET_DMA_ERRATA(DMA_ERRATA_i88); + + /* + * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + SET_DMA_ERRATA(DMA_ERRATA_3_3); + + /* + * Erratum ID: Not Available + * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared + * after secure sram context save and restore. + * Work around: Hence we need to manually clear those IRQs to avoid + * spurious interrupts. This affects only secure devices. + */ + if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + SET_DMA_ERRATA(DMA_ROMCODE_BUG); + + return errata; +} + /* One time initializations */ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) { struct omap_device *od; struct omap_system_dma_plat_info *p; + struct resource *mem; char *name = "omap_dma_system"; + dma_stride = OMAP2_DMA_STRIDE; + dma_common_ch_start = CSDP; + if (cpu_is_omap3630() || cpu_is_omap4430()) + dma_common_ch_end = CCDN; + else + dma_common_ch_end = CCFN; + p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); if (!p) { pr_err("%s: Unable to allocate pdata for %s:%s\n", @@ -54,6 +247,17 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return -ENOMEM; } + p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; + p->disable_irq_lch = omap2_disable_irq_lch; + p->show_dma_caps = omap2_show_dma_caps; + p->clear_dma = omap2_clear_dma; + p->dma_write = dma_write; + p->dma_read = dma_read; + + p->clear_lch_regs = NULL; + + p->errata = configure_dma_errata(); + od = omap_device_build(name, 0, oh, p, sizeof(*p), omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0); kfree(p); @@ -63,6 +267,25 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) return IS_ERR(od); } + mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__); + return -EINVAL; + } + dma_base = ioremap(mem->start, resource_size(mem)); + if (!dma_base) { + dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__); + return -ENOMEM; + } + + d = oh->dev_attr; + d->chan = kzalloc(sizeof(struct omap_dma_lch) * + (d->lch_count), GFP_KERNEL); + + if (!d->chan) { + dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__); + return -ENOMEM; + } return 0; } diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 6f51bf37ec02..c4b2b478b1a5 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -15,6 +15,10 @@ * * Support functions for the OMAP internal DMA channels. * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into DMA platform driver. + * - G, Manjunath Kondaiah + * * 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. @@ -40,96 +44,6 @@ #undef DEBUG -static u16 reg_map_omap1[] = { - [GCR] = 0x400, - [GSCR] = 0x404, - [GRST1] = 0x408, - [HW_ID] = 0x442, - [PCH2_ID] = 0x444, - [PCH0_ID] = 0x446, - [PCH1_ID] = 0x448, - [PCHG_ID] = 0x44a, - [PCHD_ID] = 0x44c, - [CAPS_0] = 0x44e, - [CAPS_1] = 0x452, - [CAPS_2] = 0x456, - [CAPS_3] = 0x458, - [CAPS_4] = 0x45a, - [PCH2_SR] = 0x460, - [PCH0_SR] = 0x480, - [PCH1_SR] = 0x482, - [PCHD_SR] = 0x4c0, - - /* Common Registers */ - [CSDP] = 0x00, - [CCR] = 0x02, - [CICR] = 0x04, - [CSR] = 0x06, - [CEN] = 0x10, - [CFN] = 0x12, - [CSFI] = 0x14, - [CSEI] = 0x16, - [CPC] = 0x18, /* 15xx only */ - [CSAC] = 0x18, - [CDAC] = 0x1a, - [CDEI] = 0x1c, - [CDFI] = 0x1e, - [CLNK_CTRL] = 0x28, - - /* Channel specific register offsets */ - [CSSA] = 0x08, - [CDSA] = 0x0c, - [COLOR] = 0x20, - [CCR2] = 0x24, - [LCH_CTRL] = 0x2a, -}; - -static u16 reg_map_omap2[] = { - [REVISION] = 0x00, - [GCR] = 0x78, - [IRQSTATUS_L0] = 0x08, - [IRQSTATUS_L1] = 0x0c, - [IRQSTATUS_L2] = 0x10, - [IRQSTATUS_L3] = 0x14, - [IRQENABLE_L0] = 0x18, - [IRQENABLE_L1] = 0x1c, - [IRQENABLE_L2] = 0x20, - [IRQENABLE_L3] = 0x24, - [SYSSTATUS] = 0x28, - [OCP_SYSCONFIG] = 0x2c, - [CAPS_0] = 0x64, - [CAPS_2] = 0x6c, - [CAPS_3] = 0x70, - [CAPS_4] = 0x74, - - /* Common register offsets */ - [CCR] = 0x80, - [CLNK_CTRL] = 0x84, - [CICR] = 0x88, - [CSR] = 0x8c, - [CSDP] = 0x90, - [CEN] = 0x94, - [CFN] = 0x98, - [CSEI] = 0xa4, - [CSFI] = 0xa8, - [CDEI] = 0xac, - [CDFI] = 0xb0, - [CSAC] = 0xb4, - [CDAC] = 0xb8, - - /* Channel specific register offsets */ - [CSSA] = 0x9c, - [CDSA] = 0xa0, - [CCEN] = 0xbc, - [CCFN] = 0xc0, - [COLOR] = 0xc4, - - /* OMAP4 specific registers */ - [CDP] = 0xd0, - [CNDP] = 0xd4, - [CCDN] = 0xd8, -}; - #ifndef CONFIG_ARCH_OMAP1 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED @@ -143,6 +57,9 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) +static struct omap_system_dma_plat_info *p; +static struct omap_dma_dev_attr *d; + static int enable_1510_mode; static u32 errata; @@ -152,27 +69,6 @@ static struct omap_dma_global_context_registers { u32 dma_gcr; } omap_dma_global_context; -struct omap_dma_lch { - int next_lch; - int dev_id; - u16 saved_csr; - u16 enabled_irqs; - const char *dev_name; - void (*callback)(int lch, u16 ch_status, void *data); - void *data; - -#ifndef CONFIG_ARCH_OMAP1 - /* required for Dynamic chaining */ - int prev_linked_ch; - int next_linked_ch; - int state; - int chain_id; - - int status; -#endif - long flags; -}; - struct dma_link_info { int *linked_dmach_q; int no_of_lchs_linked; @@ -228,18 +124,6 @@ static int omap_dma_reserve_channels; static spinlock_t dma_chan_lock; static struct omap_dma_lch *dma_chan; -static void __iomem *omap_dma_base; -static u16 *reg_map; -static u8 dma_stride; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; - -static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = { - INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, - INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, - INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, - INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, - INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD -}; static inline void disable_lnk(int lch); static void omap_disable_channel_irq(int lch); @@ -248,52 +132,9 @@ static inline void omap_enable_channel_irq(int lch); #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ __func__); -static inline void dma_write(u32 val, int reg, int lch) -{ - u8 stride; - u32 offset; - - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; - offset = reg_map[reg] + (stride * lch); - - if (dma_stride == 0x40) { - __raw_writew(val, omap_dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - __raw_writew(val >> 16, omap_dma_base + offset2); - } - } else { - __raw_writel(val, omap_dma_base + offset); - } -} - -static inline u32 dma_read(int reg, int lch) -{ - u8 stride; - u32 offset, val; - - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; - offset = reg_map[reg] + (stride * lch); - - if (dma_stride == 0x40) { - val = __raw_readw(omap_dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u16 upper; - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - upper = __raw_readw(omap_dma_base + offset2); - val |= (upper << 16); - } - } else { - val = __raw_readl(omap_dma_base + offset); - } - return val; -} - #ifdef CONFIG_ARCH_OMAP15XX /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ -static int omap_dma_in_1510_mode(void) +int omap_dma_in_1510_mode(void) { return enable_1510_mode; } @@ -325,15 +166,6 @@ static inline void set_gdma_dev(int req, int dev) #define set_gdma_dev(req, dev) do {} while (0) #endif -/* Omap1 only */ -static void clear_lch_regs(int lch) -{ - int i = dma_common_ch_start; - - for (; i <= dma_common_ch_end; i += 1) - dma_write(0, i, lch); -} - void omap_set_dma_priority(int lch, int dst_port, int priority) { unsigned long reg; @@ -366,12 +198,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) if (cpu_class_is_omap2()) { u32 ccr; - ccr = dma_read(CCR, lch); + ccr = p->dma_read(CCR, lch); if (priority) ccr |= (1 << 6); else ccr &= ~(1 << 6); - dma_write(ccr, CCR, lch); + p->dma_write(ccr, CCR, lch); } } EXPORT_SYMBOL(omap_set_dma_priority); @@ -382,31 +214,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~0x03; l |= data_type; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); if (cpu_class_is_omap1()) { u16 ccr; - ccr = dma_read(CCR, lch); + ccr = p->dma_read(CCR, lch); ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) ccr |= 1 << 5; - dma_write(ccr, CCR, lch); + p->dma_write(ccr, CCR, lch); - ccr = dma_read(CCR2, lch); + ccr = p->dma_read(CCR2, lch); ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) ccr |= 1 << 2; - dma_write(ccr, CCR2, lch); + p->dma_write(ccr, CCR2, lch); } if (cpu_class_is_omap2() && dma_trigger) { u32 val; - val = dma_read(CCR, lch); + val = p->dma_read(CCR, lch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -431,11 +263,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, } else { val &= ~(1 << 24); /* dest synch */ } - dma_write(val, CCR, lch); + p->dma_write(val, CCR, lch); } - dma_write(elem_count, CEN, lch); - dma_write(frame_count, CFN, lch); + p->dma_write(elem_count, CEN, lch); + p->dma_write(frame_count, CFN, lch); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -446,7 +278,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CCR2, lch); + w = p->dma_read(CCR2, lch); w &= ~0x03; switch (mode) { @@ -461,22 +293,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(w, CCR2, lch); + p->dma_write(w, CCR2, lch); - w = dma_read(LCH_CTRL, lch); + w = p->dma_read(LCH_CTRL, lch); w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - dma_write(color, COLOR, lch); + p->dma_write(color, COLOR, lch); w |= 1; /* Channel type G */ } - dma_write(w, LCH_CTRL, lch); + p->dma_write(w, LCH_CTRL, lch); } if (cpu_class_is_omap2()) { u32 val; - val = dma_read(CCR, lch); + val = p->dma_read(CCR, lch); val &= ~((1 << 17) | (1 << 16)); switch (mode) { @@ -491,10 +323,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(val, CCR, lch); + p->dma_write(val, CCR, lch); color &= 0xffffff; - dma_write(color, COLOR, lch); + p->dma_write(color, COLOR, lch); } } EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -504,10 +336,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) if (cpu_class_is_omap2()) { u32 csdp; - csdp = dma_read(CSDP, lch); + csdp = p->dma_read(CSDP, lch); csdp &= ~(0x3 << 16); csdp |= (mode << 16); - dma_write(csdp, CSDP, lch); + p->dma_write(csdp, CSDP, lch); } } EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -517,10 +349,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { u32 l; - l = dma_read(LCH_CTRL, lch); + l = p->dma_read(LCH_CTRL, lch); l &= ~0x7; l |= mode; - dma_write(l, LCH_CTRL, lch); + p->dma_write(l, LCH_CTRL, lch); } } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -535,21 +367,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CSDP, lch); + w = p->dma_read(CSDP, lch); w &= ~(0x1f << 2); w |= src_port << 2; - dma_write(w, CSDP, lch); + p->dma_write(w, CSDP, lch); } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~(0x03 << 12); l |= src_amode << 12; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); - dma_write(src_start, CSSA, lch); + p->dma_write(src_start, CSSA, lch); - dma_write(src_ei, CSEI, lch); - dma_write(src_fi, CSFI, lch); + p->dma_write(src_ei, CSEI, lch); + p->dma_write(src_fi, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_params); @@ -577,8 +409,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CSEI, lch); - dma_write(fidx, CSFI, lch); + p->dma_write(eidx, CSEI, lch); + p->dma_write(fidx, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -586,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(1 << 6); if (enable) l |= (1 << 6); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -599,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x03 << 7); switch (burst_mode) { @@ -635,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) } l |= (burst << 7); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -647,21 +479,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, u32 l; if (cpu_class_is_omap1()) { - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x1f << 9); l |= dest_port << 9; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~(0x03 << 14); l |= dest_amode << 14; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); - dma_write(dest_start, CDSA, lch); + p->dma_write(dest_start, CDSA, lch); - dma_write(dst_ei, CDEI, lch); - dma_write(dst_fi, CDFI, lch); + p->dma_write(dst_ei, CDEI, lch); + p->dma_write(dst_fi, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -670,8 +502,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CDEI, lch); - dma_write(fidx, CDFI, lch); + p->dma_write(eidx, CDEI, lch); + p->dma_write(fidx, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -679,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(1 << 13); if (enable) l |= 1 << 13; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -692,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x03 << 14); switch (burst_mode) { @@ -725,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) return; } l |= (burst << 14); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -735,18 +567,18 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = dma_read(CSR, lch); + status = p->dma_read(CSR, lch); else if (cpu_class_is_omap2()) - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); /* Enable some nice interrupts. */ - dma_write(dma_chan[lch].enabled_irqs, CICR, lch); + p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); } void omap_enable_dma_irq(int lch, u16 bits) @@ -765,7 +597,7 @@ static inline void enable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL, lch); + l = p->dma_read(CLNK_CTRL, lch); if (cpu_class_is_omap1()) l &= ~(1 << 14); @@ -780,18 +612,18 @@ static inline void enable_lnk(int lch) l = dma_chan[lch].next_linked_ch | (1 << 15); #endif - dma_write(l, CLNK_CTRL, lch); + p->dma_write(l, CLNK_CTRL, lch); } static inline void disable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL, lch); + l = p->dma_read(CLNK_CTRL, lch); /* Disable interrupts */ if (cpu_class_is_omap1()) { - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Set the STOP_LNK bit */ l |= 1 << 14; } @@ -802,7 +634,7 @@ static inline void disable_lnk(int lch) l &= ~(1 << 15); } - dma_write(l, CLNK_CTRL, lch); + p->dma_write(l, CLNK_CTRL, lch); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -815,9 +647,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0, lch); + val = p->dma_read(IRQENABLE_L0, lch); val |= 1 << lch; - dma_write(val, IRQENABLE_L0, lch); + p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -830,9 +662,9 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0, lch); + val = p->dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0, lch); + p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -859,8 +691,8 @@ int omap_request_dma(int dev_id, const char *dev_name, chan = dma_chan + free_ch; chan->dev_id = dev_id; - if (cpu_class_is_omap1()) - clear_lch_regs(free_ch); + if (p->clear_lch_regs) + p->clear_lch_regs(free_ch); if (cpu_class_is_omap2()) omap_clear_dma(free_ch); @@ -897,17 +729,17 @@ int omap_request_dma(int dev_id, const char *dev_name, * Disable the 1510 compatibility mode and set the sync device * id. */ - dma_write(dev_id | (1 << 10), CCR, free_ch); + p->dma_write(dev_id | (1 << 10), CCR, free_ch); } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { - dma_write(dev_id, CCR, free_ch); + p->dma_write(dev_id, CCR, free_ch); } if (cpu_class_is_omap2()) { omap2_enable_irq_lch(free_ch); omap_enable_channel_irq(free_ch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); - dma_write(1 << free_ch, IRQSTATUS_L0, 0); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); + p->dma_write(1 << free_ch, IRQSTATUS_L0, 0); } *dma_ch_out = free_ch; @@ -928,23 +760,23 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR, lch); + p->dma_write(0, CCR, lch); } if (cpu_class_is_omap2()) { omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); - dma_write(1 << lch, IRQSTATUS_L0, lch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + p->dma_write(1 << lch, IRQSTATUS_L0, lch); /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR, lch); + p->dma_write(0, CCR, lch); omap_clear_dma(lch); } @@ -985,7 +817,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; - dma_write(reg, GCR, 0); + p->dma_write(reg, GCR, 0); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -1008,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else l |= ((read_prio & 0x1) << 6); - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); return 0; } @@ -1030,24 +862,7 @@ void omap_clear_dma(int lch) unsigned long flags; local_irq_save(flags); - - if (cpu_class_is_omap1()) { - u32 l; - - l = dma_read(CCR, lch); - l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); - - /* Clear pending interrupts */ - l = dma_read(CSR, lch); - } - - if (cpu_class_is_omap2()) { - int i = dma_common_ch_start; - for (; i <= dma_common_ch_end; i += 1) - dma_write(0, i, lch); - } - + p->clear_dma(lch); local_irq_restore(flags); } EXPORT_SYMBOL(omap_clear_dma); @@ -1061,13 +876,13 @@ void omap_start_dma(int lch) * before starting dma transfer. */ if (cpu_is_omap15xx()) - dma_write(0, CPC, lch); + p->dma_write(0, CPC, lch); else - dma_write(0, CDAC, lch); + p->dma_write(0, CDAC, lch); if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch; - char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[dma_lch_count]; dma_chan_link_map[lch] = 1; /* Set the link register of the first channel */ @@ -1090,17 +905,17 @@ void omap_start_dma(int lch) cur_lch = next_lch; } while (next_lch != -1); } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) - dma_write(lch, CLNK_CTRL, lch); + p->dma_write(lch, CLNK_CTRL, lch); omap_enable_channel_irq(lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1112,46 +927,46 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if (IS_DMA_ERRATA(DMA_ERRATA_i541) && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; /* Configure No-Standby */ - l = dma_read(OCP_SYSCONFIG, lch); + l = p->dma_read(OCP_SYSCONFIG, lch); sys_cf = l; l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - dma_write(l , OCP_SYSCONFIG, 0); + p->dma_write(l , OCP_SYSCONFIG, 0); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); /* Wait for sDMA FIFO drain */ - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) { udelay(5); i++; - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); } if (i >= 100) printk(KERN_ERR "DMA drain did not complete on " "lch %d\n", lch); /* Restore OCP_SYSCONFIG */ - dma_write(sys_cf, OCP_SYSCONFIG, lch); + p->dma_write(sys_cf, OCP_SYSCONFIG, lch); } else { l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch = lch; - char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[dma_lch_count]; memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); do { @@ -1212,15 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC, lch); + offset = p->dma_read(CPC, lch); else - offset = dma_read(CSAC, lch); + offset = p->dma_read(CSAC, lch); if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) - offset = dma_read(CSAC, lch); + offset = p->dma_read(CSAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CSSA, lch) & 0xFFFF0000); + offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000); return offset; } @@ -1239,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC, lch); + offset = p->dma_read(CPC, lch); else - offset = dma_read(CDAC, lch); + offset = p->dma_read(CDAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CDAC, lch); + offset = p->dma_read(CDAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CDSA, lch) & 0xFFFF0000); + offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000); return offset; } @@ -1259,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; + return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1272,7 +1087,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) + if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -1287,7 +1102,7 @@ void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR, lch_head) | (3 << 8), + p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8), CCR, lch_head); return; } @@ -1314,7 +1129,7 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR, lch_head) & ~(3 << 8), + p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), CCR, lch_head); return; } @@ -1341,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) } EXPORT_SYMBOL(omap_dma_unlink_lch); -/*----------------------------------------------------------------------------*/ - #ifndef CONFIG_ARCH_OMAP1 /* Create chain of DMA channesls */ static void create_dma_lch_chain(int lch_head, int lch_queue) @@ -1367,15 +1180,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - l = dma_read(CLNK_CTRL, lch_head); + l = p->dma_read(CLNK_CTRL, lch_head); l &= ~(0x1f); l |= lch_queue; - dma_write(l, CLNK_CTRL, lch_head); + p->dma_write(l, CLNK_CTRL, lch_head); - l = dma_read(CLNK_CTRL, lch_queue); + l = p->dma_read(CLNK_CTRL, lch_queue); l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); - dma_write(l, CLNK_CTRL, lch_queue); + p->dma_write(l, CLNK_CTRL, lch_queue); } /** @@ -1651,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Set the params to the free channel */ if (src_start != 0) - dma_write(src_start, CSSA, lch); + p->dma_write(src_start, CSSA, lch); if (dest_start != 0) - dma_write(dest_start, CDSA, lch); + p->dma_write(dest_start, CDSA, lch); /* Write the buffer size */ - dma_write(elem_count, CEN, lch); - dma_write(frame_count, CFN, lch); + p->dma_write(elem_count, CEN, lch); + p->dma_write(frame_count, CFN, lch); /* * If the chain is dynamically linked, @@ -1690,7 +1503,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, enable_lnk(dma_chan[lch].prev_linked_ch); dma_chan[lch].state = DMA_CH_QUEUED; start_dma = 0; - if (0 == ((1 << 7) & dma_read( + if (0 == ((1 << 7) & p->dma_read( CCR, dma_chan[lch].prev_linked_ch))) { disable_lnk(dma_chan[lch]. prev_linked_ch); @@ -1707,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if ((0 == (l & (1 << 24)))) l &= ~(1 << 25); @@ -1718,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, l |= (1 << 7); dma_chan[lch].state = DMA_CH_STARTED; pr_debug("starting %d\n", lch); - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } else start_dma = 0; } else { if (0 == (l & (1 << 7))) - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1768,7 +1581,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - l = dma_read(CCR, channels[0]); + l = p->dma_read(CCR, channels[0]); l |= (1 << 7); dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; dma_chan[channels[0]].state = DMA_CH_STARTED; @@ -1777,7 +1590,7 @@ int omap_start_dma_chain_transfers(int chain_id) l &= ~(1 << 25); else l |= (1 << 25); - dma_write(l, CCR, channels[0]); + p->dma_write(l, CCR, channels[0]); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1813,19 +1626,19 @@ int omap_stop_dma_chain_transfers(int chain_id) channels = dma_linked_lch[chain_id].linked_dmach_q; if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { - sys_cf = dma_read(OCP_SYSCONFIG, 0); + sys_cf = p->dma_read(OCP_SYSCONFIG, 0); l = sys_cf; /* Middle mode reg set no Standby */ l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG, 0); + p->dma_write(l, OCP_SYSCONFIG, 0); } for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - l = dma_read(CCR, channels[i]); + l = p->dma_read(CCR, channels[i]); l &= ~(1 << 7); - dma_write(l, CCR, channels[i]); + p->dma_write(l, CCR, channels[i]); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1838,7 +1651,7 @@ int omap_stop_dma_chain_transfers(int chain_id) OMAP_DMA_CHAIN_QINIT(chain_id); if (IS_DMA_ERRATA(DMA_ERRATA_i88)) - dma_write(sys_cf, OCP_SYSCONFIG, 0); + p->dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -1880,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - *ei = dma_read(CCEN, lch); - *fi = dma_read(CCFN, lch); + *ei = p->dma_read(CCEN, lch); + *fi = p->dma_read(CCFN, lch); return 0; } @@ -1918,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CDAC, lch); + return p->dma_read(CDAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1952,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CSAC, lch); + return p->dma_read(CSAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1969,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch) csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = dma_read(CSR, ch); + csr = p->dma_read(CSR, ch); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -2022,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = dma_read(CSR, ch); + u32 status = p->dma_read(CSR, ch); if (!status) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - dma_write(1 << ch, IRQSTATUS_L0, ch); + p->dma_write(1 << ch, IRQSTATUS_L0, ch); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -2047,9 +1860,9 @@ static int omap2_dma_handle_ch(int ch) if (IS_DMA_ERRATA(DMA_ERRATA_i378)) { u32 ccr; - ccr = dma_read(CCR, ch); + ccr = p->dma_read(CCR, ch); ccr &= ~OMAP_DMA_CCR_EN; - dma_write(ccr, CCR, ch); + p->dma_write(ccr, CCR, ch); dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; } } @@ -2060,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); - dma_write(1 << ch, IRQSTATUS_L0, ch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); + p->dma_write(1 << ch, IRQSTATUS_L0, ch); /* read back the register to flush the write */ - dma_read(IRQSTATUS_L0, ch); + p->dma_read(IRQSTATUS_L0, ch); /* If the ch is not chained then chain_id will be -1 */ if (dma_chan[ch].chain_id != -1) { int chain_id = dma_chan[ch].chain_id; dma_chan[ch].state = DMA_CH_NOTSTARTED; - if (dma_read(CLNK_CTRL, ch) & (1 << 15)) + if (p->dma_read(CLNK_CTRL, ch) & (1 << 15)) dma_chan[dma_chan[ch].next_linked_ch].state = DMA_CH_STARTED; if (dma_linked_lch[chain_id].chain_mode == @@ -2079,10 +1892,10 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = dma_read(CSR, ch); + status = p->dma_read(CSR, ch); } - dma_write(status, CSR, ch); + p->dma_write(status, CSR, ch); if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -2096,13 +1909,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val, enable_reg; int i; - val = dma_read(IRQSTATUS_L0, 0); + val = p->dma_read(IRQSTATUS_L0, 0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - enable_reg = dma_read(IRQENABLE_L0, 0); + enable_reg = p->dma_read(IRQENABLE_L0, 0); val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) @@ -2128,206 +1941,66 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = - dma_read(IRQENABLE_L0, 0); + p->dma_read(IRQENABLE_L0, 0); omap_dma_global_context.dma_ocp_sysconfig = - dma_read(OCP_SYSCONFIG, 0); - omap_dma_global_context.dma_gcr = dma_read(GCR, 0); + p->dma_read(OCP_SYSCONFIG, 0); + omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0); } void omap_dma_global_context_restore(void) { int ch; - dma_write(omap_dma_global_context.dma_gcr, GCR, 0); - dma_write(omap_dma_global_context.dma_ocp_sysconfig, + p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0); + p->dma_write(omap_dma_global_context.dma_ocp_sysconfig, OCP_SYSCONFIG, 0); - dma_write(omap_dma_global_context.dma_irqenable_l0, + p->dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0, 0); if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) - dma_write(0x3 , IRQSTATUS_L0, 0); + p->dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) omap_clear_dma(ch); } -static void configure_dma_errata(void) +static int __devinit omap_system_dma_probe(struct platform_device *pdev) { + int ch, ret = 0; + int dma_irq; + char irq_name[4]; + int irq_rel; - /* - * Errata applicable for OMAP2430ES1.0 and all omap2420 - * - * I. - * Erratum ID: Not Available - * Inter Frame DMA buffering issue DMA will wrongly - * buffer elements if packing and bursting is enabled. This might - * result in data gets stalled in FIFO at the end of the block. - * Workaround: DMA channels must have BUFFERING_DISABLED bit set to - * guarantee no data will stay in the DMA FIFO in case inter frame - * buffering occurs - * - * II. - * Erratum ID: Not Available - * DMA may hang when several channels are used in parallel - * In the following configuration, DMA channel hanging can occur: - * a. Channel i, hardware synchronized, is enabled - * b. Another channel (Channel x), software synchronized, is enabled. - * c. Channel i is disabled before end of transfer - * d. Channel i is reenabled. - * e. Steps 1 to 4 are repeated a certain number of times. - * f. A third channel (Channel y), software synchronized, is enabled. - * Channel x and Channel y may hang immediately after step 'f'. - * Workaround: - * For any channel used - make sure NextLCH_ID is set to the value j. - */ - if (cpu_is_omap2420() || (cpu_is_omap2430() && - (omap_type() == OMAP2430_REV_ES1_0))) { - SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); - SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); + p = pdev->dev.platform_data; + if (!p) { + dev_err(&pdev->dev, "%s: System DMA initialized without" + "platform data\n", __func__); + return -EINVAL; } - /* - * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled - * after a transaction error. - * Workaround: SW should explicitely disable the channel. - */ - if (cpu_class_is_omap2()) - SET_DMA_ERRATA(DMA_ERRATA_i378); + d = p->dma_attr; + errata = p->errata; - /* - * Erratum ID: i541: sDMA FIFO draining does not finish - * If sDMA channel is disabled on the fly, sDMA enters standby even - * through FIFO Drain is still in progress - * Workaround: Put sDMA in NoStandby more before a logical channel is - * disabled, then put it back to SmartStandby right after the channel - * finishes FIFO draining. - */ - if (cpu_is_omap34xx()) - SET_DMA_ERRATA(DMA_ERRATA_i541); - - /* - * Erratum ID: i88 : Special programming model needed to disable DMA - * before end of block. - * Workaround: software must ensure that the DMA is configured in No - * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") - */ - if (cpu_is_omap34xx() && (omap_type() == OMAP3430_REV_ES1_0)) - SET_DMA_ERRATA(DMA_ERRATA_i88); - - /* - * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!cpu_is_omap15xx()) - SET_DMA_ERRATA(DMA_ERRATA_3_3); - - /* - * Erratum ID: Not Available - * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared - * after secure sram context save and restore. - * Work around: Hence we need to manually clear those IRQs to avoid - * spurious interrupts. This affects only secure devices. - */ - if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) - SET_DMA_ERRATA(DMA_ROMCODE_BUG); -} - -/*----------------------------------------------------------------------------*/ - -static int __init omap_init_dma(void) -{ - unsigned long base; - int ch, r; - - if (cpu_class_is_omap1()) { - base = OMAP1_DMA_BASE; - dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap24xx()) { - base = OMAP24XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap34xx()) { - base = OMAP34XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap44xx()) { - base = OMAP44XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else { - pr_err("DMA init failed for unsupported omap\n"); - return -ENODEV; - } - - omap_dma_base = ioremap(base, SZ_4K); - BUG_ON(!omap_dma_base); - - if (cpu_class_is_omap1()) { - dma_stride = 0x40; - reg_map = reg_map_omap1; - dma_common_ch_start = CPC; - dma_common_ch_end = COLOR; - } else { - dma_stride = 0x60; - reg_map = reg_map_omap2; - dma_common_ch_start = CSDP; - if (cpu_is_omap3630() || cpu_is_omap4430()) - dma_common_ch_end = CCDN; - else - dma_common_ch_end = CCFN; - } - - if (cpu_class_is_omap2() && omap_dma_reserve_channels + if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels && (omap_dma_reserve_channels <= dma_lch_count)) - dma_lch_count = omap_dma_reserve_channels; + d->lch_count = omap_dma_reserve_channels; - dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, - GFP_KERNEL); - if (!dma_chan) { - r = -ENOMEM; - goto out_unmap; - } + dma_lch_count = d->lch_count; + dma_chan_count = dma_lch_count; + dma_chan = d->chan; + enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; if (cpu_class_is_omap2()) { dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * dma_lch_count, GFP_KERNEL); if (!dma_linked_lch) { - r = -ENOMEM; - goto out_free; + ret = -ENOMEM; + goto exit_dma_lch_fail; } } - if (cpu_is_omap15xx()) { - printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); - dma_chan_count = 9; - enable_1510_mode = 1; - } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { - printk(KERN_INFO "OMAP DMA hardware version %d\n", - dma_read(HW_ID, 0)); - printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), - dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), - dma_read(CAPS_4, 0)); - if (!enable_1510_mode) { - u16 w; - - /* Disable OMAP 3.0/3.1 compatibility mode. */ - w = dma_read(GSCR, 0); - w |= 1 << 3; - dma_write(w, GSCR, 0); - dma_chan_count = 16; - } else - dma_chan_count = 9; - } else if (cpu_class_is_omap2()) { - u8 revision = dma_read(REVISION, 0) & 0xff; - printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", - revision >> 4, revision & 0xf); - dma_chan_count = dma_lch_count; - } else { - dma_chan_count = 0; - return 0; - } - spin_lock_init(&dma_chan_lock); - for (ch = 0; ch < dma_chan_count; ch++) { omap_clear_dma(ch); if (cpu_class_is_omap2()) @@ -2344,20 +2017,23 @@ static int __init omap_init_dma(void) * request_irq() doesn't like dev_id (ie. ch) being * zero, so we have to kludge around this. */ - r = request_irq(omap1_dma_irq[ch], + sprintf(&irq_name[0], "%d", ch); + dma_irq = platform_get_irq_byname(pdev, irq_name); + + if (dma_irq < 0) { + ret = dma_irq; + goto exit_dma_irq_fail; + } + + /* INT_DMA_LCD is handled in lcd_dma.c */ + if (dma_irq == INT_DMA_LCD) + continue; + + ret = request_irq(dma_irq, omap1_dma_irq_handler, 0, "DMA", (void *) (ch + 1)); - if (r != 0) { - int i; - - printk(KERN_ERR "unable to request IRQ %d " - "for DMA (error %d)\n", - omap1_dma_irq[ch], r); - for (i = 0; i < ch; i++) - free_irq(omap1_dma_irq[i], - (void *) (i + 1)); - goto out_free; - } + if (ret != 0) + goto exit_dma_irq_fail; } } @@ -2366,47 +2042,91 @@ static int __init omap_init_dma(void) DMA_DEFAULT_FIFO_DEPTH, 0); if (cpu_class_is_omap2()) { - int irq; - if (cpu_is_omap44xx()) - irq = OMAP44XX_IRQ_SDMA_0; - else - irq = INT_24XX_SDMA_IRQ0; - setup_irq(irq, &omap24xx_dma_irq); - } - - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - /* Enable smartidle idlemodes and autoidle */ - u32 v = dma_read(OCP_SYSCONFIG, 0); - v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | - DMA_SYSCONFIG_SIDLEMODE_MASK | - DMA_SYSCONFIG_AUTOIDLE); - v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | - DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | - DMA_SYSCONFIG_AUTOIDLE); - dma_write(v , OCP_SYSCONFIG, 0); - /* reserve dma channels 0 and 1 in high security devices */ - if (cpu_is_omap34xx() && - (omap_type() != OMAP2_DEVICE_TYPE_GP)) { - printk(KERN_INFO "Reserving DMA channels 0 and 1 for " - "HS ROM code\n"); - dma_chan[0].dev_id = 0; - dma_chan[1].dev_id = 1; + strcpy(irq_name, "0"); + dma_irq = platform_get_irq_byname(pdev, irq_name); + if (dma_irq < 0) { + dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq); + goto exit_dma_lch_fail; + } + ret = setup_irq(dma_irq, &omap24xx_dma_irq); + if (ret) { + dev_err(&pdev->dev, "set_up failed for IRQ %d" + "for DMA (error %d)\n", dma_irq, ret); + goto exit_dma_lch_fail; } } - configure_dma_errata(); + /* reserve dma channels 0 and 1 in high security devices */ + if (cpu_is_omap34xx() && + (omap_type() != OMAP2_DEVICE_TYPE_GP)) { + printk(KERN_INFO "Reserving DMA channels 0 and 1 for " + "HS ROM code\n"); + dma_chan[0].dev_id = 0; + dma_chan[1].dev_id = 1; + } + p->show_dma_caps(); return 0; -out_free: +exit_dma_irq_fail: + dev_err(&pdev->dev, "unable to request IRQ %d" + "for DMA (error %d)\n", dma_irq, ret); + for (irq_rel = 0; irq_rel < ch; irq_rel++) { + dma_irq = platform_get_irq(pdev, irq_rel); + free_irq(dma_irq, (void *)(irq_rel + 1)); + } + +exit_dma_lch_fail: + kfree(p); + kfree(d); kfree(dma_chan); - -out_unmap: - iounmap(omap_dma_base); - - return r; + return ret; } -arch_initcall(omap_init_dma); +static int __devexit omap_system_dma_remove(struct platform_device *pdev) +{ + int dma_irq; + + if (cpu_class_is_omap2()) { + char irq_name[4]; + strcpy(irq_name, "0"); + dma_irq = platform_get_irq_byname(pdev, irq_name); + remove_irq(dma_irq, &omap24xx_dma_irq); + } else { + int irq_rel = 0; + for ( ; irq_rel < dma_chan_count; irq_rel++) { + dma_irq = platform_get_irq(pdev, irq_rel); + free_irq(dma_irq, (void *)(irq_rel + 1)); + } + } + kfree(p); + kfree(d); + kfree(dma_chan); + return 0; +} + +static struct platform_driver omap_system_dma_driver = { + .probe = omap_system_dma_probe, + .remove = omap_system_dma_remove, + .driver = { + .name = "omap_dma_system" + }, +}; + +static int __init omap_system_dma_init(void) +{ + return platform_driver_register(&omap_system_dma_driver); +} +arch_initcall(omap_system_dma_init); + +static void __exit omap_system_dma_exit(void) +{ + platform_driver_unregister(&omap_system_dma_driver); +} + +MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_AUTHOR("Texas Instruments Inc"); /* * Reserve the omap SDMA channels using cmdline bootarg diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 4b51d2b93b0e..d1c916fcf770 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -21,20 +21,16 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H +#include + +/* + * TODO: These dma channel defines should go away once all + * the omap drivers hwmod adapted. + */ + /* Move omap4 specific defines to dma-44xx.h */ #include "dma-44xx.h" -/* Hardware registers for omap1 */ -#define OMAP1_DMA_BASE (0xfffed800) - -/* Hardware registers for omap2 and omap3 */ -#define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000) -#define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000) -#define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000) - -#define OMAP1_LOGICAL_DMA_CH_COUNT 17 -#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ - /* DMA channels for omap1 */ #define OMAP_DMA_NO_DEVICE 0 #define OMAP_DMA_MCSI1_TX 1 @@ -302,6 +298,14 @@ #define IS_CSSA_32 BIT(0x3) #define IS_CDSA_32 BIT(0x4) #define IS_RW_PRIORITY BIT(0x5) +#define ENABLE_1510_MODE BIT(0x6) +#define SRC_PORT BIT(0x7) +#define DST_PORT BIT(0x8) +#define SRC_INDEX BIT(0x9) +#define DST_INDEX BIT(0xA) +#define IS_BURST_ONLY4 BIT(0xB) +#define CLEAR_CSR_ON_READ BIT(0xC) +#define IS_WORD_16 BIT(0xD) enum omap_reg_offsets { @@ -397,9 +401,40 @@ struct omap_dma_channel_params { #endif }; +struct omap_dma_lch { + int next_lch; + int dev_id; + u16 saved_csr; + u16 enabled_irqs; + const char *dev_name; + void (*callback)(int lch, u16 ch_status, void *data); + void *data; + long flags; + /* required for Dynamic chaining */ + int prev_linked_ch; + int next_linked_ch; + int state; + int chain_id; + int status; +}; + struct omap_dma_dev_attr { u32 dev_caps; u16 lch_count; + u16 chan_count; + struct omap_dma_lch *chan; +}; + +/* System DMA platform data structure */ +struct omap_system_dma_plat_info { + struct omap_dma_dev_attr *dma_attr; + u32 errata; + void (*disable_irq_lch)(int lch); + void (*show_dma_caps)(void); + void (*clear_lch_regs)(int lch); + void (*clear_dma)(int lch); + void (*dma_write)(u32 val, int reg, int lch); + u32 (*dma_read)(int reg, int lch); }; extern void omap_set_dma_priority(int lch, int dst_port, int priority);