diff options
author | Arnd Bergmann <arnd@arndb.de> | 2013-04-20 00:30:31 +0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2013-04-20 00:50:01 +0400 |
commit | 1b361942b53c33f38d55065c13785aadb5103a18 (patch) | |
tree | 07b26d32b175f27f18f1fca3d5944a58f89cd17f /arch/arm/mach-spear/pl080.c | |
parent | 61b464aef0e306f141dbc0bb3f9c58049a987a7e (diff) | |
parent | bcf3e72eff584136600a51a5b30ef7a794664d19 (diff) | |
download | linux-1b361942b53c33f38d55065c13785aadb5103a18.tar.xz |
Merge branch 'spear/multiplatform' into late/cleanup
This is a prerequisite for the spear/dwdma series.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-spear/pl080.c')
-rw-r--r-- | arch/arm/mach-spear/pl080.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/arm/mach-spear/pl080.c b/arch/arm/mach-spear/pl080.c new file mode 100644 index 000000000000..cfa1199d0f4a --- /dev/null +++ b/arch/arm/mach-spear/pl080.c @@ -0,0 +1,78 @@ +/* + * arch/arm/plat-spear/pl080.c + * + * DMAC pl080 definitions for SPEAr platform + * + * Copyright (C) 2012 ST Microelectronics + * Viresh Kumar <viresh.linux@gmail.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/amba/pl08x.h> +#include <linux/amba/bus.h> +#include <linux/bug.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/spinlock_types.h> +#include <mach/spear.h> +#include <mach/misc_regs.h> + +static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x); + +struct { + unsigned char busy; + unsigned char val; +} signals[16] = {{0, 0}, }; + +int pl080_get_signal(const struct pl08x_channel_data *cd) +{ + unsigned int signal = cd->min_signal, val; + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + + /* Return if signal is already acquired by somebody else */ + if (signals[signal].busy && + (signals[signal].val != cd->muxval)) { + spin_unlock_irqrestore(&lock, flags); + return -EBUSY; + } + + /* If acquiring for the first time, configure it */ + if (!signals[signal].busy) { + val = readl(DMA_CHN_CFG); + + /* + * Each request line has two bits in DMA_CHN_CFG register. To + * goto the bits of current request line, do left shift of + * value by 2 * signal number. + */ + val &= ~(0x3 << (signal * 2)); + val |= cd->muxval << (signal * 2); + writel(val, DMA_CHN_CFG); + } + + signals[signal].busy++; + signals[signal].val = cd->muxval; + spin_unlock_irqrestore(&lock, flags); + + return signal; +} + +void pl080_put_signal(const struct pl08x_channel_data *cd, int signal) +{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + + /* if signal is not used */ + if (!signals[signal].busy) + BUG(); + + signals[signal].busy--; + + spin_unlock_irqrestore(&lock, flags); +} |