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 
gpio_lock(void)42 static inline void gpio_lock(void)
43 {
44 	local_irq_disable();
45 }
46 
gpio_unlock(void)47 static inline void gpio_unlock(void)
48 {
49 	local_irq_enable();
50 }
51 
52 /* Inline functions */
gpio_read_bit(u32 reg,int gpio)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 
gpio_set_bit(u32 reg,int gpio)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 
pnx4008_gpio_register_pin(unsigned short pin)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 
pnx4008_gpio_unregister_pin(unsigned short pin)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 
pnx4008_gpio_read_pin(unsigned short pin)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 */
pnx4008_gpio_write_pin(unsigned short pin,int 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 */
pnx4008_gpio_set_pin_direction(unsigned short pin,int output)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*/
pnx4008_gpio_read_pin_direction(unsigned short pin)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 */
pnx4008_gpio_set_pin_mux(unsigned short pin,int output)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*/
pnx4008_gpio_read_pin_mux(unsigned short pin)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);
330