diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-05-14 15:33:42 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-05-14 15:33:42 +0200 |
commit | d2819f80d465672b09c2f4cb52303b7f951c4d0f (patch) | |
tree | aa0262703e86b97ad1460c722e78d7233e24e3bb /arch/arm/plat-spear/pl080.c | |
parent | 5df33a62c4a028d6fc7f2dcc159827d09b7334b8 (diff) | |
parent | 366695ff706669d40459174b1cbb78fca42f4e06 (diff) |
Merge branch 'spear/pinctrl' into spear/clock
Conflicts:
arch/arm/mach-spear3xx/Makefile
arch/arm/mach-spear3xx/clock.c
arch/arm/mach-spear3xx/include/mach/generic.h
arch/arm/mach-spear6xx/clock.c
arch/arm/plat-spear/Makefile
drivers/pinctrl/core.c
This resolves some annoying merge conflicts.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/plat-spear/pl080.c')
-rw-r--r-- | arch/arm/plat-spear/pl080.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/arm/plat-spear/pl080.c b/arch/arm/plat-spear/pl080.c new file mode 100644 index 00000000000..d53d75e1af5 --- /dev/null +++ b/arch/arm/plat-spear/pl080.c @@ -0,0 +1,79 @@ +/* + * arch/arm/plat-spear/pl080.c + * + * DMAC pl080 definitions for SPEAr platform + * + * Copyright (C) 2012 ST Microelectronics + * Viresh Kumar <viresh.kumar@st.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/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(struct pl08x_dma_chan *ch) +{ + const struct pl08x_channel_data *cd = ch->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(struct pl08x_dma_chan *ch) +{ + const struct pl08x_channel_data *cd = ch->cd; + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + + /* if signal is not used */ + if (!signals[cd->min_signal].busy) + BUG(); + + signals[cd->min_signal].busy--; + + spin_unlock_irqrestore(&lock, flags); +} |