Merge remote-tracking branch 's5p/for-next'
[linux-2.6/next.git] / arch / arm / mach-pnx4008 / gpio.c
blobeef531b755cac3a4cebd9b8d8ffecf7b09a52e4a
1 /*
2 * arch/arm/mach-pnx4008/gpio.c
4 * PNX4008 GPIO driver
6 * Author: Dmitry Chigirev <source@mvista.com>
8 * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
9 * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
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.
16 #include <linux/gpio.h>
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>
24 /* register definitions */
25 #define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE)
27 #define PIO_INP_STATE (0x00U)
28 #define PIO_OUTP_SET (0x04U)
29 #define PIO_OUTP_CLR (0x08U)
30 #define PIO_OUTP_STATE (0x0CU)
31 #define PIO_DRV_SET (0x10U)
32 #define PIO_DRV_CLR (0x14U)
33 #define PIO_DRV_STATE (0x18U)
34 #define PIO_SDINP_STATE (0x1CU)
35 #define PIO_SDOUTP_SET (0x20U)
36 #define PIO_SDOUTP_CLR (0x24U)
37 #define PIO_MUX_SET (0x28U)
38 #define PIO_MUX_CLR (0x2CU)
39 #define PIO_MUX_STATE (0x30U)
41 static inline void gpio_lock(void)
43 local_irq_disable();
46 static inline void gpio_unlock(void)
48 local_irq_enable();
51 /* Inline functions */
52 static inline int gpio_read_bit(u32 reg, int gpio)
54 u32 bit, val;
55 int ret = -EFAULT;
57 if (gpio < 0)
58 goto out;
60 bit = GPIO_BIT(gpio);
61 if (bit) {
62 val = __raw_readl(PIO_VA_BASE + reg);
63 ret = (val & bit) ? 1 : 0;
65 out:
66 return ret;
69 static inline int gpio_set_bit(u32 reg, int gpio)
71 u32 bit, val;
72 int ret = -EFAULT;
74 if (gpio < 0)
75 goto out;
77 bit = GPIO_BIT(gpio);
78 if (bit) {
79 val = __raw_readl(PIO_VA_BASE + reg);
80 val |= bit;
81 __raw_writel(val, PIO_VA_BASE + reg);
82 ret = 0;
84 out:
85 return ret;
88 /* Very simple access control, bitmap for allocated/free */
89 static unsigned long access_map[4];
90 #define INP_INDEX 0
91 #define OUTP_INDEX 1
92 #define GPIO_INDEX 2
93 #define MUX_INDEX 3
95 /*GPIO to Input Mapping */
96 static short gpio_to_inp_map[32] = {
97 -1, -1, -1, -1, -1, -1, -1, -1,
98 -1, -1, -1, -1, -1, -1, -1, -1,
99 -1, -1, -1, -1, -1, -1, -1, -1,
100 -1, 10, 11, 12, 13, 14, 24, -1
103 /*GPIO to Mux Mapping */
104 static short gpio_to_mux_map[32] = {
105 -1, -1, -1, -1, -1, -1, -1, -1,
106 -1, -1, -1, -1, -1, -1, -1, -1,
107 -1, -1, -1, -1, -1, -1, -1, -1,
108 -1, -1, -1, 0, 1, 4, 5, -1
111 /*Output to Mux Mapping */
112 static short outp_to_mux_map[32] = {
113 -1, -1, -1, 6, -1, -1, -1, -1,
114 -1, -1, -1, -1, -1, -1, -1, -1,
115 -1, -1, -1, -1, -1, 2, -1, -1,
116 -1, -1, -1, -1, -1, -1, -1, -1
119 int pnx4008_gpio_register_pin(unsigned short pin)
121 unsigned long bit = GPIO_BIT(pin);
122 int ret = -EBUSY; /* Already in use */
124 gpio_lock();
126 if (GPIO_ISBID(pin)) {
127 if (access_map[GPIO_INDEX] & bit)
128 goto out;
129 access_map[GPIO_INDEX] |= bit;
131 } else if (GPIO_ISRAM(pin)) {
132 if (access_map[GPIO_INDEX] & bit)
133 goto out;
134 access_map[GPIO_INDEX] |= bit;
136 } else if (GPIO_ISMUX(pin)) {
137 if (access_map[MUX_INDEX] & bit)
138 goto out;
139 access_map[MUX_INDEX] |= bit;
141 } else if (GPIO_ISOUT(pin)) {
142 if (access_map[OUTP_INDEX] & bit)
143 goto out;
144 access_map[OUTP_INDEX] |= bit;
146 } else if (GPIO_ISIN(pin)) {
147 if (access_map[INP_INDEX] & bit)
148 goto out;
149 access_map[INP_INDEX] |= bit;
150 } else
151 goto out;
152 ret = 0;
154 out:
155 gpio_unlock();
156 return ret;
159 EXPORT_SYMBOL(pnx4008_gpio_register_pin);
161 int pnx4008_gpio_unregister_pin(unsigned short pin)
163 unsigned long bit = GPIO_BIT(pin);
164 int ret = -EFAULT; /* Not registered */
166 gpio_lock();
168 if (GPIO_ISBID(pin)) {
169 if (~access_map[GPIO_INDEX] & bit)
170 goto out;
171 access_map[GPIO_INDEX] &= ~bit;
172 } else if (GPIO_ISRAM(pin)) {
173 if (~access_map[GPIO_INDEX] & bit)
174 goto out;
175 access_map[GPIO_INDEX] &= ~bit;
176 } else if (GPIO_ISMUX(pin)) {
177 if (~access_map[MUX_INDEX] & bit)
178 goto out;
179 access_map[MUX_INDEX] &= ~bit;
180 } else if (GPIO_ISOUT(pin)) {
181 if (~access_map[OUTP_INDEX] & bit)
182 goto out;
183 access_map[OUTP_INDEX] &= ~bit;
184 } else if (GPIO_ISIN(pin)) {
185 if (~access_map[INP_INDEX] & bit)
186 goto out;
187 access_map[INP_INDEX] &= ~bit;
188 } else
189 goto out;
190 ret = 0;
192 out:
193 gpio_unlock();
194 return ret;
197 EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
199 unsigned long pnx4008_gpio_read_pin(unsigned short pin)
201 unsigned long ret = -EFAULT;
202 int gpio = GPIO_BIT_MASK(pin);
203 gpio_lock();
204 if (GPIO_ISOUT(pin)) {
205 ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
206 } else if (GPIO_ISRAM(pin)) {
207 if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
208 ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
210 } else if (GPIO_ISBID(pin)) {
211 ret = gpio_read_bit(PIO_DRV_STATE, gpio);
212 if (ret > 0)
213 ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
214 else if (ret == 0)
215 ret =
216 gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
217 } else if (GPIO_ISIN(pin)) {
218 ret = gpio_read_bit(PIO_INP_STATE, gpio);
220 gpio_unlock();
221 return ret;
224 EXPORT_SYMBOL(pnx4008_gpio_read_pin);
226 /* Write Value to output */
227 int pnx4008_gpio_write_pin(unsigned short pin, int output)
229 int gpio = GPIO_BIT_MASK(pin);
230 int ret = -EFAULT;
232 gpio_lock();
233 if (GPIO_ISOUT(pin)) {
234 printk( "writing '%x' to '%x'\n",
235 gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
236 ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
237 } else if (GPIO_ISRAM(pin)) {
238 if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
239 ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
240 PIO_SDOUTP_CLR, gpio);
241 } else if (GPIO_ISBID(pin)) {
242 if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
243 ret = gpio_set_bit(output ? PIO_OUTP_SET :
244 PIO_OUTP_CLR, gpio);
246 gpio_unlock();
247 return ret;
250 EXPORT_SYMBOL(pnx4008_gpio_write_pin);
252 /* Value = 1 : Set GPIO pin as output */
253 /* Value = 0 : Set GPIO pin as input */
254 int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
256 int gpio = GPIO_BIT_MASK(pin);
257 int ret = -EFAULT;
259 gpio_lock();
260 if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
261 ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
263 gpio_unlock();
264 return ret;
267 EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
269 /* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
270 int pnx4008_gpio_read_pin_direction(unsigned short pin)
272 int gpio = GPIO_BIT_MASK(pin);
273 int ret = -EFAULT;
275 gpio_lock();
276 if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
277 ret = gpio_read_bit(PIO_DRV_STATE, gpio);
279 gpio_unlock();
280 return ret;
283 EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
285 /* Value = 1 : Set pin to muxed function */
286 /* Value = 0 : Set pin as GPIO */
287 int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
289 int gpio = GPIO_BIT_MASK(pin);
290 int ret = -EFAULT;
292 gpio_lock();
293 if (GPIO_ISBID(pin)) {
294 ret =
295 gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
296 gpio_to_mux_map[gpio]);
297 } else if (GPIO_ISOUT(pin)) {
298 ret =
299 gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
300 outp_to_mux_map[gpio]);
301 } else if (GPIO_ISMUX(pin)) {
302 ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
304 gpio_unlock();
305 return ret;
308 EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
310 /* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
311 int pnx4008_gpio_read_pin_mux(unsigned short pin)
313 int gpio = GPIO_BIT_MASK(pin);
314 int ret = -EFAULT;
316 gpio_lock();
317 if (GPIO_ISBID(pin)) {
318 ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
319 } else if (GPIO_ISOUT(pin)) {
320 ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
321 } else if (GPIO_ISMUX(pin)) {
322 ret = gpio_read_bit(PIO_MUX_STATE, gpio);
324 gpio_unlock();
325 return ret;
328 EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);