0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/amba/pl08x.h>
0012 #include <linux/amba/bus.h>
0013 #include <linux/bug.h>
0014 #include <linux/err.h>
0015 #include <linux/io.h>
0016 #include <linux/spinlock_types.h>
0017 #include "spear.h"
0018 #include "misc_regs.h"
0019
0020 static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
0021
0022 struct {
0023 unsigned char busy;
0024 unsigned char val;
0025 } signals[16] = {{0, 0}, };
0026
0027 int pl080_get_signal(const struct pl08x_channel_data *cd)
0028 {
0029 unsigned int signal = cd->min_signal, val;
0030 unsigned long flags;
0031
0032 spin_lock_irqsave(&lock, flags);
0033
0034
0035 if (signals[signal].busy &&
0036 (signals[signal].val != cd->muxval)) {
0037 spin_unlock_irqrestore(&lock, flags);
0038 return -EBUSY;
0039 }
0040
0041
0042 if (!signals[signal].busy) {
0043 val = readl(DMA_CHN_CFG);
0044
0045
0046
0047
0048
0049
0050 val &= ~(0x3 << (signal * 2));
0051 val |= cd->muxval << (signal * 2);
0052 writel(val, DMA_CHN_CFG);
0053 }
0054
0055 signals[signal].busy++;
0056 signals[signal].val = cd->muxval;
0057 spin_unlock_irqrestore(&lock, flags);
0058
0059 return signal;
0060 }
0061
0062 void pl080_put_signal(const struct pl08x_channel_data *cd, int signal)
0063 {
0064 unsigned long flags;
0065
0066 spin_lock_irqsave(&lock, flags);
0067
0068
0069 if (!signals[signal].busy)
0070 BUG();
0071
0072 signals[signal].busy--;
0073
0074 spin_unlock_irqrestore(&lock, flags);
0075 }