aboutsummaryrefslogtreecommitdiff
path: root/arch/cris/arch-v32/mach-a3/dma.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 10:01:28 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 10:01:28 -0800
commit0cf975e16927fd70f34cee20d3856246c13bb4c8 (patch)
treebb955d50f28e5d98c198701798c8341d9763299a /arch/cris/arch-v32/mach-a3/dma.c
parent03054de1e0b90b33e9974107d84dabd2509f5898 (diff)
parentbc10ac3f2fe44e65f787d6197fd5d17304bf7d83 (diff)
Merge branch 'cris' of git://www.jni.nu/cris
* 'cris' of git://www.jni.nu/cris: (158 commits) CRIS v32: Remove hwregs/timer_defs.h, it is now architecture specific. CRIS v32: Change drivers/i2c.c locking. CRIS v32: Rewrite ARTPEC-3 gpio driver to avoid volatiles and general cleanup. CRIS: Add new timerfd syscall entries. MAINTAINERS: Add my information for the CRIS port. CRIS v32: Correct spelling of bandwidth in function name. CRIS v32: Clean up nandflash.c for ARTPEC-3 and ETRAX FS. CRIS v10: Cleanup of drivers/gpio.c CRIS v10: drivers/net/cris/eth_v10.c rename LED defines to CRIS_LED to avoid name clash. CRIS: Make io_pwm_set_period members unsigned in etraxgpio.h CRIS: Move ETRAX_AXISFLASHMAP to common Kconfig file. CRIS: Drop regs parameter from call to profile_tick in kernel/time.c CRIS v32: Fix minor formatting issue in mach-a3/io.c CRIS v32: Initialize GIO even if we're rambooting in kernel/head.S CRIS v32: Remove kernel/arbiter.c, it now exists in machine dependent directory. CRIS v32: Minor changes to avoid errors in asm-cris/arch-v32/hwregs/reg_rdwr.h CRIS v32: arch-v32/hwregs/intr_vect_defs.h moved to machine dependent directory. CRIS v32: Correct offset for TASK_pid in asm-cris/arch-v32/offset.h CRIS v32: Move register map header to machine dependent directory. CRIS v32: Let compiler know that memory is clobbered after a break op. ...
Diffstat (limited to 'arch/cris/arch-v32/mach-a3/dma.c')
-rw-r--r--arch/cris/arch-v32/mach-a3/dma.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-a3/dma.c b/arch/cris/arch-v32/mach-a3/dma.c
new file mode 100644
index 00000000000..25f236ef0b8
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/dma.c
@@ -0,0 +1,185 @@
+/* Wrapper for DMA channel allocator that starts clocks etc */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/arch/mach/dma.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/marb_defs.h>
+#include <hwregs/clkgen_defs.h>
+#include <hwregs/strmux_defs.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <arbiter.h>
+
+static char used_dma_channels[MAX_DMA_CHANNELS];
+static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
+
+static DEFINE_SPINLOCK(dma_lock);
+
+int crisv32_request_dma(unsigned int dmanr, const char *device_id,
+ unsigned options, unsigned int bandwidth, enum dma_owner owner)
+{
+ unsigned long flags;
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
+ reg_strmux_rw_cfg strmux_cfg;
+
+ if (crisv32_arbiter_allocate_bandwidth(dmanr,
+ options & DMA_INT_MEM ? INT_REGION : EXT_REGION,
+ bandwidth))
+ return -ENOMEM;
+
+ spin_lock_irqsave(&dma_lock, flags);
+
+ if (used_dma_channels[dmanr]) {
+ spin_unlock_irqrestore(&dma_lock, flags);
+ if (options & DMA_VERBOSE_ON_ERROR)
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "already allocated by %s\n",
+ dmanr,
+ device_id,
+ used_dma_channels_users[dmanr]);
+
+ if (options & DMA_PANIC_ON_ERROR)
+ panic("request_dma error!");
+ spin_unlock_irqrestore(&dma_lock, flags);
+ return -EBUSY;
+ }
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+ strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg);
+
+ switch (dmanr) {
+ case 0:
+ case 1:
+ clk_ctrl.dma0_1_eth = 1;
+ break;
+ case 2:
+ case 3:
+ clk_ctrl.dma2_3_strcop = 1;
+ break;
+ case 4:
+ case 5:
+ clk_ctrl.dma4_5_iop = 1;
+ break;
+ case 6:
+ case 7:
+ clk_ctrl.sser_ser_dma6_7 = 1;
+ break;
+ case 9:
+ case 11:
+ clk_ctrl.dma9_11 = 1;
+ break;
+#if MAX_DMA_CHANNELS-1 != 11
+#error Check dma.c
+#endif
+ default:
+ spin_unlock_irqrestore(&dma_lock, flags);
+ if (options & DMA_VERBOSE_ON_ERROR)
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "only 0-%i valid)\n",
+ dmanr, device_id, MAX_DMA_CHANNELS-1);
+
+ if (options & DMA_PANIC_ON_ERROR)
+ panic("request_dma error!");
+ return -EINVAL;
+ }
+
+ switch (owner) {
+ case dma_eth:
+ if (dmanr == 0)
+ strmux_cfg.dma0 = regk_strmux_eth;
+ else if (dmanr == 1)
+ strmux_cfg.dma1 = regk_strmux_eth;
+ else
+ panic("Invalid DMA channel for eth\n");
+ break;
+ case dma_ser0:
+ if (dmanr == 0)
+ strmux_cfg.dma0 = regk_strmux_ser0;
+ else if (dmanr == 1)
+ strmux_cfg.dma1 = regk_strmux_ser0;
+ else
+ panic("Invalid DMA channel for ser0\n");
+ break;
+ case dma_ser3:
+ if (dmanr == 2)
+ strmux_cfg.dma2 = regk_strmux_ser3;
+ else if (dmanr == 3)
+ strmux_cfg.dma3 = regk_strmux_ser3;
+ else
+ panic("Invalid DMA channel for ser3\n");
+ break;
+ case dma_strp:
+ if (dmanr == 2)
+ strmux_cfg.dma2 = regk_strmux_strcop;
+ else if (dmanr == 3)
+ strmux_cfg.dma3 = regk_strmux_strcop;
+ else
+ panic("Invalid DMA channel for strp\n");
+ break;
+ case dma_ser1:
+ if (dmanr == 4)
+ strmux_cfg.dma4 = regk_strmux_ser1;
+ else if (dmanr == 5)
+ strmux_cfg.dma5 = regk_strmux_ser1;
+ else
+ panic("Invalid DMA channel for ser1\n");
+ break;
+ case dma_iop:
+ if (dmanr == 4)
+ strmux_cfg.dma4 = regk_strmux_iop;
+ else if (dmanr == 5)
+ strmux_cfg.dma5 = regk_strmux_iop;
+ else
+ panic("Invalid DMA channel for iop\n");
+ break;
+ case dma_ser2:
+ if (dmanr == 6)
+ strmux_cfg.dma6 = regk_strmux_ser2;
+ else if (dmanr == 7)
+ strmux_cfg.dma7 = regk_strmux_ser2;
+ else
+ panic("Invalid DMA channel for ser2\n");
+ break;
+ case dma_sser:
+ if (dmanr == 6)
+ strmux_cfg.dma6 = regk_strmux_sser;
+ else if (dmanr == 7)
+ strmux_cfg.dma7 = regk_strmux_sser;
+ else
+ panic("Invalid DMA channel for sser\n");
+ break;
+ case dma_ser4:
+ if (dmanr == 9)
+ strmux_cfg.dma9 = regk_strmux_ser4;
+ else
+ panic("Invalid DMA channel for ser4\n");
+ break;
+ case dma_jpeg:
+ if (dmanr == 9)
+ strmux_cfg.dma9 = regk_strmux_jpeg;
+ else
+ panic("Invalid DMA channel for JPEG\n");
+ break;
+ case dma_h264:
+ if (dmanr == 11)
+ strmux_cfg.dma11 = regk_strmux_h264;
+ else
+ panic("Invalid DMA channel for H264\n");
+ break;
+ }
+
+ used_dma_channels[dmanr] = 1;
+ used_dma_channels_users[dmanr] = device_id;
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
+ REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg);
+ spin_unlock_irqrestore(&dma_lock, flags);
+ return 0;
+}
+
+void crisv32_free_dma(unsigned int dmanr)
+{
+ spin_lock(&dma_lock);
+ used_dma_channels[dmanr] = 0;
+ spin_unlock(&dma_lock);
+}