]> Pileus Git - ~andy/linux/blob - arch/arm/plat-spear/pl080.c
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy...
[~andy/linux] / arch / arm / plat-spear / pl080.c
1 /*
2  * arch/arm/plat-spear/pl080.c
3  *
4  * DMAC pl080 definitions for SPEAr platform
5  *
6  * Copyright (C) 2012 ST Microelectronics
7  * Viresh Kumar <viresh.kumar@st.com>
8  *
9  * This file is licensed under the terms of the GNU General Public
10  * License version 2. This program is licensed "as is" without any
11  * warranty of any kind, whether express or implied.
12  */
13
14 #include <linux/amba/pl08x.h>
15 #include <linux/amba/bus.h>
16 #include <linux/bug.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19 #include <linux/spinlock_types.h>
20 #include <mach/spear.h>
21 #include <mach/misc_regs.h>
22
23 static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
24
25 struct {
26         unsigned char busy;
27         unsigned char val;
28 } signals[16] = {{0, 0}, };
29
30 int pl080_get_signal(struct pl08x_dma_chan *ch)
31 {
32         const struct pl08x_channel_data *cd = ch->cd;
33         unsigned int signal = cd->min_signal, val;
34         unsigned long flags;
35
36         spin_lock_irqsave(&lock, flags);
37
38         /* Return if signal is already acquired by somebody else */
39         if (signals[signal].busy &&
40                         (signals[signal].val != cd->muxval)) {
41                 spin_unlock_irqrestore(&lock, flags);
42                 return -EBUSY;
43         }
44
45         /* If acquiring for the first time, configure it */
46         if (!signals[signal].busy) {
47                 val = readl(DMA_CHN_CFG);
48
49                 /*
50                  * Each request line has two bits in DMA_CHN_CFG register. To
51                  * goto the bits of current request line, do left shift of
52                  * value by 2 * signal number.
53                  */
54                 val &= ~(0x3 << (signal * 2));
55                 val |= cd->muxval << (signal * 2);
56                 writel(val, DMA_CHN_CFG);
57         }
58
59         signals[signal].busy++;
60         signals[signal].val = cd->muxval;
61         spin_unlock_irqrestore(&lock, flags);
62
63         return signal;
64 }
65
66 void pl080_put_signal(struct pl08x_dma_chan *ch)
67 {
68         const struct pl08x_channel_data *cd = ch->cd;
69         unsigned long flags;
70
71         spin_lock_irqsave(&lock, flags);
72
73         /* if signal is not used */
74         if (!signals[cd->min_signal].busy)
75                 BUG();
76
77         signals[cd->min_signal].busy--;
78
79         spin_unlock_irqrestore(&lock, flags);
80 }