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