Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.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);