diff options
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r-- | arch/arm/mach-davinci/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-tnetv107x-evm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/davinci.h | 30 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices-tnetv107x.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm355.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm365.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm644x.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm646x.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dma.c | 1591 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/cp_intc.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/da8xx.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/edma.h | 267 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/tnetv107x.h | 6 |
14 files changed, 41 insertions, 1895 deletions
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index dd1ffccc75e..63997a1128e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o clock.o serial.o psc.o \ - dma.o usb.o common.o sram.o aemif.o + usb.o common.o sram.o aemif.o obj-$(CONFIG_DAVINCI_MUX) += mux.o diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index ba798370fc9..78ea395d2ac 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -26,12 +26,12 @@ #include <linux/input.h> #include <linux/input/matrix_keypad.h> #include <linux/spi/spi.h> +#include <linux/platform_data/edma.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/irqs.h> -#include <mach/edma.h> #include <mach/mux.h> #include <mach/cp_intc.h> #include <mach/tnetv107x.h> diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 1ab3df423da..a883043d082 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -23,9 +23,9 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/platform_data/davinci_asp.h> +#include <linux/platform_data/edma.h> #include <linux/platform_data/keyscan-davinci.h> #include <mach/hardware.h> -#include <mach/edma.h> #include <media/davinci/vpfe_capture.h> #include <media/davinci/vpif_types.h> @@ -77,32 +77,32 @@ void davinci_map_sysmod(void); #define DM646X_ASYNC_EMIF_CS2_SPACE_BASE 0x42000000 /* DM355 function declarations */ -void __init dm355_init(void); +void dm355_init(void); void dm355_init_spi0(unsigned chipselect_mask, const struct spi_board_info *info, unsigned len); -void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata); +void dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata); int dm355_init_video(struct vpfe_config *, struct vpbe_config *); /* DM365 function declarations */ -void __init dm365_init(void); -void __init dm365_init_asp(struct snd_platform_data *pdata); -void __init dm365_init_vc(struct snd_platform_data *pdata); -void __init dm365_init_ks(struct davinci_ks_platform_data *pdata); -void __init dm365_init_rtc(void); +void dm365_init(void); +void dm365_init_asp(struct snd_platform_data *pdata); +void dm365_init_vc(struct snd_platform_data *pdata); +void dm365_init_ks(struct davinci_ks_platform_data *pdata); +void dm365_init_rtc(void); void dm365_init_spi0(unsigned chipselect_mask, const struct spi_board_info *info, unsigned len); int dm365_init_video(struct vpfe_config *, struct vpbe_config *); /* DM644x function declarations */ -void __init dm644x_init(void); -void __init dm644x_init_asp(struct snd_platform_data *pdata); -int __init dm644x_init_video(struct vpfe_config *, struct vpbe_config *); +void dm644x_init(void); +void dm644x_init_asp(struct snd_platform_data *pdata); +int dm644x_init_video(struct vpfe_config *, struct vpbe_config *); /* DM646x function declarations */ -void __init dm646x_init(void); -void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); -void __init dm646x_init_mcasp1(struct snd_platform_data *pdata); -int __init dm646x_init_edma(struct edma_rsv_info *rsv); +void dm646x_init(void); +void dm646x_init_mcasp0(struct snd_platform_data *pdata); +void dm646x_init_mcasp1(struct snd_platform_data *pdata); +int dm646x_init_edma(struct edma_rsv_info *rsv); void dm646x_video_init(void); void dm646x_setup_vpif(struct vpif_display_config *, struct vpif_capture_config *); diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index cfb194df18e..612a0856e9c 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -18,10 +18,10 @@ #include <linux/dma-mapping.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/platform_data/edma.h> #include <mach/common.h> #include <mach/irqs.h> -#include <mach/edma.h> #include <mach/tnetv107x.h> #include "clock.h" diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index a7068a3aa9d..90b83d00fe2 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -19,9 +19,10 @@ #include <mach/irqs.h> #include <mach/cputype.h> #include <mach/mux.h> -#include <mach/edma.h> #include <linux/platform_data/mmc-davinci.h> #include <mach/time.h> +#include <linux/platform_data/edma.h> + #include "davinci.h" #include "clock.h" @@ -34,6 +35,9 @@ #define DM365_MMCSD0_BASE 0x01D11000 #define DM365_MMCSD1_BASE 0x01D00000 +#define DAVINCI_DMA_MMCRXEVT 26 +#define DAVINCI_DMA_MMCTXEVT 27 + void __iomem *davinci_sysmod_base; void davinci_map_sysmod(void) diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index a11034a358f..526cf7d06d0 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -19,7 +19,6 @@ #include <asm/mach/map.h> #include <mach/cputype.h> -#include <mach/edma.h> #include <mach/psc.h> #include <mach/mux.h> #include <mach/irqs.h> @@ -28,6 +27,7 @@ #include <mach/common.h> #include <linux/platform_data/spi-davinci.h> #include <mach/gpio-davinci.h> +#include <linux/platform_data/edma.h> #include "davinci.h" #include "clock.h" diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 40fa4fee933..c4b741173c0 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -18,11 +18,11 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/spi/spi.h> +#include <linux/platform_data/edma.h> #include <asm/mach/map.h> #include <mach/cputype.h> -#include <mach/edma.h> #include <mach/psc.h> #include <mach/mux.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 4d37d3e2a19..dd156d58fe6 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -12,11 +12,11 @@ #include <linux/clk.h> #include <linux/serial_8250.h> #include <linux/platform_device.h> +#include <linux/platform_data/edma.h> #include <asm/mach/map.h> #include <mach/cputype.h> -#include <mach/edma.h> #include <mach/irqs.h> #include <mach/psc.h> #include <mach/mux.h> diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index ac7b431c4c8..6d52a321a8c 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -13,11 +13,11 @@ #include <linux/clk.h> #include <linux/serial_8250.h> #include <linux/platform_device.h> +#include <linux/platform_data/edma.h> #include <asm/mach/map.h> #include <mach/cputype.h> -#include <mach/edma.h> #include <mach/irqs.h> #include <mach/psc.h> #include <mach/mux.h> diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c deleted file mode 100644 index 45b7c71d9cc..00000000000 --- a/arch/arm/mach-davinci/dma.c +++ /dev/null @@ -1,1591 +0,0 @@ -/* - * EDMA3 support for DaVinci - * - * Copyright (C) 2006-2009 Texas Instruments. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/slab.h> - -#include <mach/edma.h> - -/* Offsets matching "struct edmacc_param" */ -#define PARM_OPT 0x00 -#define PARM_SRC 0x04 -#define PARM_A_B_CNT 0x08 -#define PARM_DST 0x0c -#define PARM_SRC_DST_BIDX 0x10 -#define PARM_LINK_BCNTRLD 0x14 -#define PARM_SRC_DST_CIDX 0x18 -#define PARM_CCNT 0x1c - -#define PARM_SIZE 0x20 - -/* Offsets for EDMA CC global channel registers and their shadows */ -#define SH_ER 0x00 /* 64 bits */ -#define SH_ECR 0x08 /* 64 bits */ -#define SH_ESR 0x10 /* 64 bits */ -#define SH_CER 0x18 /* 64 bits */ -#define SH_EER 0x20 /* 64 bits */ -#define SH_EECR 0x28 /* 64 bits */ -#define SH_EESR 0x30 /* 64 bits */ -#define SH_SER 0x38 /* 64 bits */ -#define SH_SECR 0x40 /* 64 bits */ -#define SH_IER 0x50 /* 64 bits */ -#define SH_IECR 0x58 /* 64 bits */ -#define SH_IESR 0x60 /* 64 bits */ -#define SH_IPR 0x68 /* 64 bits */ -#define SH_ICR 0x70 /* 64 bits */ -#define SH_IEVAL 0x78 -#define SH_QER 0x80 -#define SH_QEER 0x84 -#define SH_QEECR 0x88 -#define SH_QEESR 0x8c -#define SH_QSER 0x90 -#define SH_QSECR 0x94 -#define SH_SIZE 0x200 - -/* Offsets for EDMA CC global registers */ -#define EDMA_REV 0x0000 -#define EDMA_CCCFG 0x0004 -#define EDMA_QCHMAP 0x0200 /* 8 registers */ -#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */ -#define EDMA_QDMAQNUM 0x0260 -#define EDMA_QUETCMAP 0x0280 -#define EDMA_QUEPRI 0x0284 -#define EDMA_EMR 0x0300 /* 64 bits */ -#define EDMA_EMCR 0x0308 /* 64 bits */ -#define EDMA_QEMR 0x0310 -#define EDMA_QEMCR 0x0314 -#define EDMA_CCERR 0x0318 -#define EDMA_CCERRCLR 0x031c -#define EDMA_EEVAL 0x0320 -#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/ -#define EDMA_QRAE 0x0380 /* 4 registers */ -#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */ -#define EDMA_QSTAT 0x0600 /* 2 registers */ -#define EDMA_QWMTHRA 0x0620 -#define EDMA_QWMTHRB 0x0624 -#define EDMA_CCSTAT 0x0640 - -#define EDMA_M 0x1000 /* global channel registers */ -#define EDMA_ECR 0x1008 -#define EDMA_ECRH 0x100C -#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */ -#define EDMA_PARM 0x4000 /* 128 param entries */ - -#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5)) - -#define EDMA_DCHMAP 0x0100 /* 64 registers */ -#define CHMAP_EXIST BIT(24) - -#define EDMA_MAX_DMACH 64 -#define EDMA_MAX_PARAMENTRY 512 - -/*****************************************************************************/ - -static void __iomem *edmacc_regs_base[EDMA_MAX_CC]; - -static inline unsigned int edma_read(unsigned ctlr, int offset) -{ - return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset); -} - -static inline void edma_write(unsigned ctlr, int offset, int val) -{ - __raw_writel(val, edmacc_regs_base[ctlr] + offset); -} -static inline void edma_modify(unsigned ctlr, int offset, unsigned and, - unsigned or) -{ - unsigned val = edma_read(ctlr, offset); - val &= and; - val |= or; - edma_write(ctlr, offset, val); -} -static inline void edma_and(unsigned ctlr, int offset, unsigned and) -{ - unsigned val = edma_read(ctlr, offset); - val &= and; - edma_write(ctlr, offset, val); -} -static inline void edma_or(unsigned ctlr, int offset, unsigned or) -{ - unsigned val = edma_read(ctlr, offset); - val |= or; - edma_write(ctlr, offset, val); -} -static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i) -{ - return edma_read(ctlr, offset + (i << 2)); -} -static inline void edma_write_array(unsigned ctlr, int offset, int i, - unsigned val) -{ - edma_write(ctlr, offset + (i << 2), val); -} -static inline void edma_modify_array(unsigned ctlr, int offset, int i, - unsigned and, unsigned or) -{ - edma_modify(ctlr, offset + (i << 2), and, or); -} -static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or) -{ - edma_or(ctlr, offset + (i << 2), or); -} -static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j, - unsigned or) -{ - edma_or(ctlr, offset + ((i*2 + j) << 2), or); -} -static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j, - unsigned val) -{ - edma_write(ctlr, offset + ((i*2 + j) << 2), val); -} -static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset) -{ - return edma_read(ctlr, EDMA_SHADOW0 + offset); -} -static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset, - int i) -{ - return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2)); -} -static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val) -{ - edma_write(ctlr, EDMA_SHADOW0 + offset, val); -} -static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i, - unsigned val) -{ - edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val); -} -static inline unsigned int edma_parm_read(unsigned ctlr, int offset, - int param_no) -{ - return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5)); -} -static inline void edma_parm_write(unsigned ctlr, int offset, int param_no, - unsigned val) -{ - edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val); -} -static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no, - unsigned and, unsigned or) -{ - edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or); -} -static inline void edma_parm_and(unsigned ctlr, int offset, int param_no, - unsigned and) -{ - edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and); -} -static inline void edma_parm_or(unsigned ctlr, int offset, int param_no, - unsigned or) -{ - edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or); -} - -static inline void set_bits(int offset, int len, unsigned long *p) -{ - for (; len > 0; len--) - set_bit(offset + (len - 1), p); -} - -static inline void clear_bits(int offset, int len, unsigned long *p) -{ - for (; len > 0; len--) - clear_bit(offset + (len - 1), p); -} - -/*****************************************************************************/ - -/* actual number of DMA channels and slots on this silicon */ -struct edma { - /* how many dma resources of each type */ - unsigned num_channels; - unsigned num_region; - unsigned num_slots; - unsigned num_tc; - unsigned num_cc; - enum dma_event_q default_queue; - - /* list of channels with no even trigger; terminated by "-1" */ - const s8 *noevent; - - /* The edma_inuse bit for each PaRAM slot is clear unless the - * channel is in use ... by ARM or DSP, for QDMA, or whatever. - */ - DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY); - - /* The edma_unused bit for each channel is clear unless - * it is not being used on this platform. It uses a bit - * of SOC-specific initialization code. - */ - DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH); - - unsigned irq_res_start; - unsigned irq_res_end; - - struct dma_interrupt_data { - void (*callback)(unsigned channel, unsigned short ch_status, - void *data); - void *data; - } intr_data[EDMA_MAX_DMACH]; -}; - -static struct edma *edma_cc[EDMA_MAX_CC]; -static int arch_num_cc; - -/* dummy param set used to (re)initialize parameter RAM slots */ -static const struct edmacc_param dummy_paramset = { - .link_bcntrld = 0xffff, - .ccnt = 1, -}; - -/*****************************************************************************/ - -static void map_dmach_queue(unsigned ctlr, unsigned ch_no, - enum dma_event_q queue_no) -{ - int bit = (ch_no & 0x7) * 4; - - /* default to low priority queue */ - if (queue_no == EVENTQ_DEFAULT) - queue_no = edma_cc[ctlr]->default_queue; - - queue_no &= 7; - edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3), - ~(0x7 << bit), queue_no << bit); -} - -static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no) -{ - int bit = queue_no * 4; - edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit)); -} - -static void __init assign_priority_to_queue(unsigned ctlr, int queue_no, - int priority) -{ - int bit = queue_no * 4; - edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit), - ((priority & 0x7) << bit)); -} - -/** - * map_dmach_param - Maps channel number to param entry number - * - * This maps the dma channel number to param entry numberter. In - * other words using the DMA channel mapping registers a param entry - * can be mapped to any channel - * - * Callers are responsible for ensuring the channel mapping logic is - * included in that particular EDMA variant (Eg : dm646x) - * - */ -static void __init map_dmach_param(unsigned ctlr) -{ - int i; - for (i = 0; i < EDMA_MAX_DMACH; i++) - edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5)); -} - -static inline void -setup_dma_interrupt(unsigned lch, - void (*callback)(unsigned channel, u16 ch_status, void *data), - void *data) -{ - unsigned ctlr; - - ctlr = EDMA_CTLR(lch); - lch = EDMA_CHAN_SLOT(lch); - - if (!callback) - edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5, - BIT(lch & 0x1f)); - - edma_cc[ctlr]->intr_data[lch].callback = callback; - edma_cc[ctlr]->intr_data[lch].data = data; - - if (callback) { - edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5, - BIT(lch & 0x1f)); - edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5, - BIT(lch & 0x1f)); - } -} - -static int irq2ctlr(int irq) -{ - if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end) - return 0; - else if (irq >= edma_cc[1]->irq_res_start && - irq <= edma_cc[1]->irq_res_end) - return 1; - - return -1; -} - -/****************************************************************************** - * - * DMA interrupt handler - * - *****************************************************************************/ -static irqreturn_t dma_irq_handler(int irq, void *data) -{ - int ctlr; - u32 sh_ier; - u32 sh_ipr; - u32 bank; - - ctlr = irq2ctlr(irq); - if (ctlr < 0) - return IRQ_NONE; - - dev_dbg(data, "dma_irq_handler\n"); - - sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0); - if (!sh_ipr) { - sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1); - if (!sh_ipr) - return IRQ_NONE; - sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1); - bank = 1; - } else { - sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0); - bank = 0; - } - - do { - u32 slot; - u32 channel; - - dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr); - - slot = __ffs(sh_ipr); - sh_ipr &= ~(BIT(slot)); - - if (sh_ier & BIT(slot)) { - channel = (bank << 5) | slot; - /* Clear the corresponding IPR bits */ - edma_shadow0_write_array(ctlr, SH_ICR, bank, - BIT(slot)); - if (edma_cc[ctlr]->intr_data[channel].callback) - edma_cc[ctlr]->intr_data[channel].callback( - channel, DMA_COMPLETE, - edma_cc[ctlr]->intr_data[channel].data); - } - } while (sh_ipr); - - edma_shadow0_write(ctlr, SH_IEVAL, 1); - return IRQ_HANDLED; -} - -/****************************************************************************** - * - * DMA error interrupt handler - * - *****************************************************************************/ -static irqreturn_t dma_ccerr_handler(int irq, void *data) -{ - int i; - int ctlr; - unsigned int cnt = 0; - - ctlr = irq2ctlr(irq); - if (ctlr < 0) - return IRQ_NONE; - - dev_dbg(data, "dma_ccerr_handler\n"); - - if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) && - (edma_read_array(ctlr, EDMA_EMR, 1) == 0) && - (edma_read(ctlr, EDMA_QEMR) == 0) && - (edma_read(ctlr, EDMA_CCERR) == 0)) - return IRQ_NONE; - - while (1) { - int j = -1; - if (edma_read_array(ctlr, EDMA_EMR, 0)) - j = 0; - else if (edma_read_array(ctlr, EDMA_EMR, 1)) - j = 1; - if (j >= 0) { - dev_dbg(data, "EMR%d %08x\n", j, - edma_read_array(ctlr, EDMA_EMR, j)); - for (i = 0; i < 32; i++) { - int k = (j << 5) + i; - if (edma_read_array(ctlr, EDMA_EMR, j) & - BIT(i)) { - /* Clear the corresponding EMR bits */ - edma_write_array(ctlr, EDMA_EMCR, j, - BIT(i)); - /* Clear any SER */ - edma_shadow0_write_array(ctlr, SH_SECR, - j, BIT(i)); - if (edma_cc[ctlr]->intr_data[k]. - callback) { - edma_cc[ctlr]->intr_data[k]. - callback(k, - DMA_CC_ERROR, - edma_cc[ctlr]->intr_data - [k].data); - } - } - } - } else if (edma_read(ctlr, EDMA_QEMR)) { - dev_dbg(data, "QEMR %02x\n", - edma_read(ctlr, EDMA_QEMR)); - for (i = 0; i < 8; i++) { - if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) { - /* Clear the corresponding IPR bits */ - edma_write(ctlr, EDMA_QEMCR, BIT(i)); - edma_shadow0_write(ctlr, SH_QSECR, - BIT(i)); - - /* NOTE: not reported!! */ - } - } - } else if (edma_read(ctlr, EDMA_CCERR)) { - dev_dbg(data, "CCERR %08x\n", - edma_read(ctlr, EDMA_CCERR)); - /* FIXME: CCERR.BIT(16) ignored! much better - * to just write CCERRCLR with CCERR value... - */ - for (i = 0; i < 8; i++) { - if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) { - /* Clear the corresponding IPR bits */ - edma_write(ctlr, EDMA_CCERRCLR, BIT(i)); - - /* NOTE: not reported!! */ - } - } - } - if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) && - (edma_read_array(ctlr, EDMA_EMR, 1) == 0) && - (edma_read(ctlr, EDMA_QEMR) == 0) && - (edma_read(ctlr, EDMA_CCERR) == 0)) - break; - cnt++; - if (cnt > 10) - break; - } - edma_write(ctlr, EDMA_EEVAL, 1); - return IRQ_HANDLED; -} - -/****************************************************************************** - * - * Transfer controller error interrupt handlers - * - *****************************************************************************/ - -#define tc_errs_handled false /* disabled as long as they're NOPs */ - -static irqreturn_t dma_tc0err_handler(int irq, void *data) -{ - dev_dbg(data, "dma_tc0err_handler\n"); - return IRQ_HANDLED; -} - -static irqreturn_t dma_tc1err_handler(int irq, void *data) -{ - dev_dbg(data, "dma_tc1err_handler\n"); - return IRQ_HANDLED; -} - -static int reserve_contiguous_slots(int ctlr, unsigned int id, - unsigned int num_slots, - unsigned int start_slot) -{ - int i, j; - unsigned int count = num_slots; - int stop_slot = start_slot; - DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY); - - for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) { - j = EDMA_CHAN_SLOT(i); - if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) { - /* Record our current beginning slot */ - if (count == num_slots) - stop_slot = i; - - count--; - set_bit(j, tmp_inuse); - - if (count == 0) - break; - } else { - clear_bit(j, tmp_inuse); - - if (id == EDMA_CONT_PARAMS_FIXED_EXACT) { - stop_slot = i; - break; - } else { - count = num_slots; - } - } - } - - /* - * We have to clear any bits that we set - * if we run out parameter RAM slots, i.e we do find a set - * of contiguous parameter RAM slots but do not find the exact number - * requested as we may reach the total number of parameter RAM slots - */ - if (i == edma_cc[ctlr]->num_slots) - stop_slot = i; - - j = start_slot; - for_each_set_bit_from(j, tmp_inuse, stop_slot) - clear_bit(j, edma_cc[ctlr]->edma_inuse); - - if (count) - return -EBUSY; - - for (j = i - num_slots + 1; j <= i; ++j) - memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j), - &dummy_paramset, PARM_SIZE); - - return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1); -} - -static int prepare_unused_channel_list(struct device *dev, void *data) -{ - struct platform_device *pdev = to_platform_device(dev); - int i, ctlr; - - for (i = 0; i < pdev->num_resources; i++) { - if ((pdev->resource[i].flags & IORESOURCE_DMA) && - (int)pdev->resource[i].start >= 0) { - ctlr = EDMA_CTLR(pdev->resource[i].start); - clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start), - edma_cc[ctlr]->edma_unused); - } - } - - return 0; -} - -/*-----------------------------------------------------------------------*/ - -static bool unused_chan_list_done; - -/* Resource alloc/free: dma channels, parameter RAM slots */ - -/** - * edma_alloc_channel - allocate DMA channel and paired parameter RAM - * @channel: specific channel to allocate; negative for "any unmapped channel" - * @callback: optional; to be issued on DMA completion or errors - * @data: passed to callback - * @eventq_no: an EVENTQ_* constant, used to choose which Transfer - * Controller (TC) executes requests using this channel. Use - * EVENTQ_DEFAULT unless you really need a high priority queue. - * - * This allocates a DMA channel and its associated parameter RAM slot. - * The parameter RAM is initialized to hold a dummy transfer. - * - * Normal use is to pass a specific channel number as @channel, to make - * use of hardware events mapped to that channel. When the channel will - * be used only for software triggering or event chaining, channels not - * mapped to hardware events (or mapped to unused events) are preferable. - * - * DMA transfers start from a channel using edma_start(), or by - * chaining. When the transfer described in that channel's parameter RAM - * slot completes, that slot's data may be reloaded through a link. - * - * DMA errors are only reported to the @callback associated with the - * channel driving that transfer, but transfer completion callbacks can - * be sent to another channel under control of the TCC field in - * the option word of the transfer's parameter RAM set. Drivers must not - * use DMA transfer completion callbacks for channels they did not allocate. - * (The same applies to TCC codes used in transfer chaining.) - * - * Returns the number of the channel, else negative errno. - */ -int edma_alloc_channel(int channel, - void (*callback)(unsigned channel, u16 ch_status, void *data), - void *data, - enum dma_event_q eventq_no) -{ - unsigned i, done = 0, ctlr = 0; - int ret = 0; - - if (!unused_chan_list_done) { - /* - * Scan all the platform devices to find out the EDMA channels - * used and clear them in the unused list, making the rest - * available for ARM usage. - */ - ret = bus_for_each_dev(&platform_bus_type, NULL, NULL, - prepare_unused_channel_list); - if (ret < 0) - return ret; - - unused_chan_list_done = true; - } - - if (channel >= 0) { - ctlr = EDMA_CTLR(channel); - channel = EDMA_CHAN_SLOT(channel); - } - - if (channel < 0) { - for (i = 0; i < arch_num_cc; i++) { - channel = 0; - for (;;) { - channel = find_next_bit(edma_cc[i]->edma_unused, - edma_cc[i]->num_channels, - channel); - if (channel == edma_cc[i]->num_channels) - break; - if (!test_and_set_bit(channel, - edma_cc[i]->edma_inuse)) { - done = 1; - ctlr = i; - break; - } - channel++; - } - if (done) - break; - } - if (!done) - return -ENOMEM; - } else if (channel >= edma_cc[ctlr]->num_channels) { - return -EINVAL; - } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) { - return -EBUSY; - } - - /* ensure access through shadow region 0 */ - edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f)); - - /* ensure no events are pending */ - edma_stop(EDMA_CTLR_CHAN(ctlr, channel)); - memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel), - &dummy_paramset, PARM_SIZE); - - if (callback) - setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel), - callback, data); - - map_dmach_queue(ctlr, channel, eventq_no); - - return EDMA_CTLR_CHAN(ctlr, channel); -} -EXPORT_SYMBOL(edma_alloc_channel); - - -/** - * edma_free_channel - deallocate DMA channel - * @channel: dma channel returned from edma_alloc_channel() - * - * This deallocates the DMA channel and associated parameter RAM slot - * allocated by edma_alloc_channel(). - * - * Callers are responsible for ensuring the channel is inactive, and - * will not be reactivated by linking, chaining, or software calls to - * edma_start(). - */ -void edma_free_channel(unsigned channel) -{ - unsigned ctlr; - - ctlr = EDMA_CTLR(channel); - channel = EDMA_CHAN_SLOT(channel); - - if (channel >= edma_cc[ctlr]->num_channels) - return; - - setup_dma_interrupt(channel, NULL, NULL); - /* REVISIT should probably take out of shadow region 0 */ - - memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel), - &dummy_paramset, PARM_SIZE); - clear_bit(channel, edma_cc[ctlr]->edma_inuse); -} -EXPORT_SYMBOL(edma_free_channel); - -/** - * edma_alloc_slot - allocate DMA parameter RAM - * @slot: specific slot to allocate; negative for "any unused slot" - * - * This allocates a parameter RAM slot, initializing it to hold a - * dummy transfer. Slots allocated using this routine have not been - * mapped to a hardware DMA channel, and will normally be used by - * linking to them from a slot associated with a DMA channel. - * - * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific - * slots may be allocated on behalf of DSP firmware. - * - * Returns the number of the slot, else negative errno. - */ -int edma_alloc_slot(unsigned ctlr, int slot) -{ - if (!edma_cc[ctlr]) - return -EINVAL; - - if (slot >= 0) - slot = EDMA_CHAN_SLOT(slot); - - if (slot < 0) { - slot = edma_cc[ctlr]->num_channels; - for (;;) { - slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse, - edma_cc[ctlr]->num_slots, slot); - if (slot == edma_cc[ctlr]->num_slots) - return -ENOMEM; - if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) - break; - } - } else if (slot < edma_cc[ctlr]->num_channels || - slot > |