[ARM] Orion: share GPIO handling code
[sfrench/cifs-2.6.git] / arch / arm / plat-orion / gpio.c
1 /*
2  * arch/arm/plat-orion/gpio.c
3  *
4  * Marvell Orion SoC GPIO handling.
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2.  This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/spinlock.h>
15 #include <linux/bitops.h>
16 #include <linux/io.h>
17 #include <asm/gpio.h>
18
19 static DEFINE_SPINLOCK(gpio_lock);
20 static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
21 static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
22
23 static inline void __set_direction(unsigned pin, int input)
24 {
25         u32 u;
26
27         u = readl(GPIO_IO_CONF(pin));
28         if (input)
29                 u |= 1 << (pin & 31);
30         else
31                 u &= ~(1 << (pin & 31));
32         writel(u, GPIO_IO_CONF(pin));
33 }
34
35 static void __set_level(unsigned pin, int high)
36 {
37         u32 u;
38
39         u = readl(GPIO_OUT(pin));
40         if (high)
41                 u |= 1 << (pin & 31);
42         else
43                 u &= ~(1 << (pin & 31));
44         writel(u, GPIO_OUT(pin));
45 }
46
47
48 /*
49  * GENERIC_GPIO primitives.
50  */
51 int gpio_direction_input(unsigned pin)
52 {
53         unsigned long flags;
54
55         if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
56                 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
57                 return -EINVAL;
58         }
59
60         spin_lock_irqsave(&gpio_lock, flags);
61
62         /*
63          * Some callers might not have used gpio_request(),
64          * so flag this pin as requested now.
65          */
66         if (gpio_label[pin] == NULL)
67                 gpio_label[pin] = "?";
68
69         /*
70          * Configure GPIO direction.
71          */
72         __set_direction(pin, 1);
73
74         spin_unlock_irqrestore(&gpio_lock, flags);
75
76         return 0;
77 }
78 EXPORT_SYMBOL(gpio_direction_input);
79
80 int gpio_direction_output(unsigned pin, int value)
81 {
82         unsigned long flags;
83         u32 u;
84
85         if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
86                 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
87                 return -EINVAL;
88         }
89
90         spin_lock_irqsave(&gpio_lock, flags);
91
92         /*
93          * Some callers might not have used gpio_request(),
94          * so flag this pin as requested now.
95          */
96         if (gpio_label[pin] == NULL)
97                 gpio_label[pin] = "?";
98
99         /*
100          * Disable blinking.
101          */
102         u = readl(GPIO_BLINK_EN(pin));
103         u &= ~(1 << (pin & 31));
104         writel(u, GPIO_BLINK_EN(pin));
105
106         /*
107          * Configure GPIO output value.
108          */
109         __set_level(pin, value);
110
111         /*
112          * Configure GPIO direction.
113          */
114         __set_direction(pin, 0);
115
116         spin_unlock_irqrestore(&gpio_lock, flags);
117
118         return 0;
119 }
120 EXPORT_SYMBOL(gpio_direction_output);
121
122 int gpio_get_value(unsigned pin)
123 {
124         int val;
125
126         if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
127                 val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
128         else
129                 val = readl(GPIO_OUT(pin));
130
131         return (val >> (pin & 31)) & 1;
132 }
133 EXPORT_SYMBOL(gpio_get_value);
134
135 void gpio_set_value(unsigned pin, int value)
136 {
137         unsigned long flags;
138         u32 u;
139
140         spin_lock_irqsave(&gpio_lock, flags);
141
142         /*
143          * Disable blinking.
144          */
145         u = readl(GPIO_BLINK_EN(pin));
146         u &= ~(1 << (pin & 31));
147         writel(u, GPIO_BLINK_EN(pin));
148
149         /*
150          * Configure GPIO output value.
151          */
152         __set_level(pin, value);
153
154         spin_unlock_irqrestore(&gpio_lock, flags);
155 }
156 EXPORT_SYMBOL(gpio_set_value);
157
158 int gpio_request(unsigned pin, const char *label)
159 {
160         unsigned long flags;
161         int ret;
162
163         if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
164                 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
165                 return -EINVAL;
166         }
167
168         spin_lock_irqsave(&gpio_lock, flags);
169         if (gpio_label[pin] == NULL) {
170                 gpio_label[pin] = label ? label : "?";
171                 ret = 0;
172         } else {
173                 pr_debug("%s: GPIO %d already used as %s\n",
174                          __func__, pin, gpio_label[pin]);
175                 ret = -EBUSY;
176         }
177         spin_unlock_irqrestore(&gpio_lock, flags);
178
179         return ret;
180 }
181 EXPORT_SYMBOL(gpio_request);
182
183 void gpio_free(unsigned pin)
184 {
185         if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
186                 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
187                 return;
188         }
189
190         if (gpio_label[pin] == NULL)
191                 pr_warning("%s: GPIO %d already freed\n", __func__, pin);
192         else
193                 gpio_label[pin] = NULL;
194 }
195 EXPORT_SYMBOL(gpio_free);
196
197
198 /*
199  * Orion-specific GPIO API extensions.
200  */
201 void __init orion_gpio_set_unused(unsigned pin)
202 {
203         /*
204          * Configure as output, drive low.
205          */
206         __set_level(pin, 0);
207         __set_direction(pin, 0);
208 }
209
210 void __init orion_gpio_set_valid(unsigned pin, int valid)
211 {
212         if (valid)
213                 __set_bit(pin, gpio_valid);
214         else
215                 __clear_bit(pin, gpio_valid);
216 }
217
218 void orion_gpio_set_blink(unsigned pin, int blink)
219 {
220         unsigned long flags;
221         u32 u;
222
223         spin_lock_irqsave(&gpio_lock, flags);
224
225         /*
226          * Set output value to zero.
227          */
228         __set_level(pin, 0);
229
230         u = readl(GPIO_BLINK_EN(pin));
231         if (blink)
232                 u |= 1 << (pin & 31);
233         else
234                 u &= ~(1 << (pin & 31));
235         writel(u, GPIO_BLINK_EN(pin));
236
237         spin_unlock_irqrestore(&gpio_lock, flags);
238 }
239 EXPORT_SYMBOL(orion_gpio_set_blink);