e1ce050d8fe02a581c748afcfe2394e843303ba1
[linux-3.10.git] / arch / arm / mach-pnx4008 / gpio.c
1 /*
2  * arch/arm/mach-pnx4008/gpio.c
3  *
4  * PNX4008 GPIO driver
5  *
6  * Author: Dmitry Chigirev <source@mvista.com>
7  *
8  * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
9  * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
10  *
11  * 2005 (c) MontaVista Software, Inc. This file is licensed under
12  * the terms of the GNU General Public License version 2. This program
13  * is licensed "as is" without any warranty of any kind, whether express
14  * or implied.
15  */
16
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <asm/semaphore.h>
22 #include <asm/io.h>
23 #include <asm/arch/platform.h>
24 #include <asm/arch/gpio.h>
25
26 /* register definitions */
27 #define PIO_VA_BASE     IO_ADDRESS(PNX4008_PIO_BASE)
28
29 #define PIO_INP_STATE   (0x00U)
30 #define PIO_OUTP_SET    (0x04U)
31 #define PIO_OUTP_CLR    (0x08U)
32 #define PIO_OUTP_STATE  (0x0CU)
33 #define PIO_DRV_SET     (0x10U)
34 #define PIO_DRV_CLR     (0x14U)
35 #define PIO_DRV_STATE   (0x18U)
36 #define PIO_SDINP_STATE (0x1CU)
37 #define PIO_SDOUTP_SET  (0x20U)
38 #define PIO_SDOUTP_CLR  (0x24U)
39 #define PIO_MUX_SET     (0x28U)
40 #define PIO_MUX_CLR     (0x2CU)
41 #define PIO_MUX_STATE   (0x30U)
42
43 static inline void gpio_lock(void)
44 {
45         local_irq_disable();
46 }
47
48 static inline void gpio_unlock(void)
49 {
50         local_irq_enable();
51 }
52
53 /* Inline functions */
54 static inline int gpio_read_bit(u32 reg, int gpio)
55 {
56         u32 bit, val;
57         int ret = -EFAULT;
58
59         if (gpio < 0)
60                 goto out;
61
62         bit = GPIO_BIT(gpio);
63         if (bit) {
64                 val = __raw_readl(PIO_VA_BASE + reg);
65                 ret = (val & bit) ? 1 : 0;
66         }
67 out:
68         return ret;
69 }
70
71 static inline int gpio_set_bit(u32 reg, int gpio)
72 {
73         u32 bit, val;
74         int ret = -EFAULT;
75
76         if (gpio < 0)
77                 goto out;
78
79         bit = GPIO_BIT(gpio);
80         if (bit) {
81                 val = __raw_readl(PIO_VA_BASE + reg);
82                 val |= bit;
83                 __raw_writel(val, PIO_VA_BASE + reg);
84                 ret = 0;
85         }
86 out:
87         return ret;
88 }
89
90 /* Very simple access control, bitmap for allocated/free */
91 static unsigned long access_map[4];
92 #define INP_INDEX       0
93 #define OUTP_INDEX      1
94 #define GPIO_INDEX      2
95 #define MUX_INDEX       3
96
97 /*GPIO to Input Mapping */
98 static short gpio_to_inp_map[32] = {
99         -1, -1, -1, -1, -1, -1, -1, -1,
100         -1, -1, -1, -1, -1, -1, -1, -1,
101         -1, -1, -1, -1, -1, -1, -1, -1,
102         -1, 10, 11, 12, 13, 14, 24, -1
103 };
104
105 /*GPIO to Mux Mapping */
106 static short gpio_to_mux_map[32] = {
107         -1, -1, -1, -1, -1, -1, -1, -1,
108         -1, -1, -1, -1, -1, -1, -1, -1,
109         -1, -1, -1, -1, -1, -1, -1, -1,
110         -1, -1, -1, 0, 1, 4, 5, -1
111 };
112
113 /*Output to Mux Mapping */
114 static short outp_to_mux_map[32] = {
115         -1, -1, -1, 6, -1, -1, -1, -1,
116         -1, -1, -1, -1, -1, -1, -1, -1,
117         -1, -1, -1, -1, -1, 2, -1, -1,
118         -1, -1, -1, -1, -1, -1, -1, -1
119 };
120
121 int pnx4008_gpio_register_pin(unsigned short pin)
122 {
123         unsigned long bit = GPIO_BIT(pin);
124         int ret = -EBUSY;       /* Already in use */
125
126         gpio_lock();
127
128         if (GPIO_ISBID(pin)) {
129                 if (access_map[GPIO_INDEX] & bit)
130                         goto out;
131                 access_map[GPIO_INDEX] |= bit;
132
133         } else if (GPIO_ISRAM(pin)) {
134                 if (access_map[GPIO_INDEX] & bit)
135                         goto out;
136                 access_map[GPIO_INDEX] |= bit;
137
138         } else if (GPIO_ISMUX(pin)) {
139                 if (access_map[MUX_INDEX] & bit)
140                         goto out;
141                 access_map[MUX_INDEX] |= bit;
142
143         } else if (GPIO_ISOUT(pin)) {
144                 if (access_map[OUTP_INDEX] & bit)
145                         goto out;
146                 access_map[OUTP_INDEX] |= bit;
147
148         } else if (GPIO_ISIN(pin)) {
149                 if (access_map[INP_INDEX] & bit)
150                         goto out;
151                 access_map[INP_INDEX] |= bit;
152         } else
153                 goto out;
154         ret = 0;
155
156 out:
157         gpio_unlock();
158         return ret;
159 }
160
161 EXPORT_SYMBOL(pnx4008_gpio_register_pin);
162
163 int pnx4008_gpio_unregister_pin(unsigned short pin)
164 {
165         unsigned long bit = GPIO_BIT(pin);
166         int ret = -EFAULT;      /* Not registered */
167
168         gpio_lock();
169
170         if (GPIO_ISBID(pin)) {
171                 if (~access_map[GPIO_INDEX] & bit)
172                         goto out;
173                 access_map[GPIO_INDEX] &= ~bit;
174         } else if (GPIO_ISRAM(pin)) {
175                 if (~access_map[GPIO_INDEX] & bit)
176                         goto out;
177                 access_map[GPIO_INDEX] &= ~bit;
178         } else if (GPIO_ISMUX(pin)) {
179                 if (~access_map[MUX_INDEX] & bit)
180                         goto out;
181                 access_map[MUX_INDEX] &= ~bit;
182         } else if (GPIO_ISOUT(pin)) {
183                 if (~access_map[OUTP_INDEX] & bit)
184                         goto out;
185                 access_map[OUTP_INDEX] &= ~bit;
186         } else if (GPIO_ISIN(pin)) {
187                 if (~access_map[INP_INDEX] & bit)
188                         goto out;
189                 access_map[INP_INDEX] &= ~bit;
190         } else
191                 goto out;
192         ret = 0;
193
194 out:
195         gpio_unlock();
196         return ret;
197 }
198
199 EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
200
201 unsigned long pnx4008_gpio_read_pin(unsigned short pin)
202 {
203         unsigned long ret = -EFAULT;
204         int gpio = GPIO_BIT_MASK(pin);
205         gpio_lock();
206         if (GPIO_ISOUT(pin)) {
207                 ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
208         } else if (GPIO_ISRAM(pin)) {
209                 if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
210                         ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
211                 }
212         } else if (GPIO_ISBID(pin)) {
213                 ret = gpio_read_bit(PIO_DRV_STATE, gpio);
214                 if (ret > 0)
215                         ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
216                 else if (ret == 0)
217                         ret =
218                             gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
219         } else if (GPIO_ISIN(pin)) {
220                 ret = gpio_read_bit(PIO_INP_STATE, gpio);
221         }
222         gpio_unlock();
223         return ret;
224 }
225
226 EXPORT_SYMBOL(pnx4008_gpio_read_pin);
227
228 /* Write Value to output */
229 int pnx4008_gpio_write_pin(unsigned short pin, int output)
230 {
231         int gpio = GPIO_BIT_MASK(pin);
232         int ret = -EFAULT;
233
234         gpio_lock();
235         if (GPIO_ISOUT(pin)) {
236                 printk( "writing '%x' to '%x'\n",
237                                 gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
238                 ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
239         } else if (GPIO_ISRAM(pin)) {
240                 if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
241                         ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
242                                            PIO_SDOUTP_CLR, gpio);
243         } else if (GPIO_ISBID(pin)) {
244                 if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
245                         ret = gpio_set_bit(output ? PIO_OUTP_SET :
246                                            PIO_OUTP_CLR, gpio);
247         }
248         gpio_unlock();
249         return ret;
250 }
251
252 EXPORT_SYMBOL(pnx4008_gpio_write_pin);
253
254 /* Value = 1 : Set GPIO pin as output */
255 /* Value = 0 : Set GPIO pin as input */
256 int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
257 {
258         int gpio = GPIO_BIT_MASK(pin);
259         int ret = -EFAULT;
260
261         gpio_lock();
262         if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
263                 ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
264         }
265         gpio_unlock();
266         return ret;
267 }
268
269 EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
270
271 /* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
272 int pnx4008_gpio_read_pin_direction(unsigned short pin)
273 {
274         int gpio = GPIO_BIT_MASK(pin);
275         int ret = -EFAULT;
276
277         gpio_lock();
278         if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
279                 ret = gpio_read_bit(PIO_DRV_STATE, gpio);
280         }
281         gpio_unlock();
282         return ret;
283 }
284
285 EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
286
287 /* Value = 1 : Set pin to muxed function  */
288 /* Value = 0 : Set pin as GPIO */
289 int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
290 {
291         int gpio = GPIO_BIT_MASK(pin);
292         int ret = -EFAULT;
293
294         gpio_lock();
295         if (GPIO_ISBID(pin)) {
296                 ret =
297                     gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
298                                  gpio_to_mux_map[gpio]);
299         } else if (GPIO_ISOUT(pin)) {
300                 ret =
301                     gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
302                                  outp_to_mux_map[gpio]);
303         } else if (GPIO_ISMUX(pin)) {
304                 ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
305         }
306         gpio_unlock();
307         return ret;
308 }
309
310 EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
311
312 /* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
313 int pnx4008_gpio_read_pin_mux(unsigned short pin)
314 {
315         int gpio = GPIO_BIT_MASK(pin);
316         int ret = -EFAULT;
317
318         gpio_lock();
319         if (GPIO_ISBID(pin)) {
320                 ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
321         } else if (GPIO_ISOUT(pin)) {
322                 ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
323         } else if (GPIO_ISMUX(pin)) {
324                 ret = gpio_read_bit(PIO_MUX_STATE, gpio);
325         }
326         gpio_unlock();
327         return ret;
328 }
329
330 EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);