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 #include <linux/types.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/io.h>
20 #include <mach/hardware.h>
21 #include <mach/platform.h>
22 #include <mach/gpio-pnx4008.h>
23 
24 /* register definitions */
25 #define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
26 
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)
40 
gpio_lock(void)41 static inline void gpio_lock(void)
42 {
43 	local_irq_disable();
44 }
45 
gpio_unlock(void)46 static inline void gpio_unlock(void)
47 {
48 	local_irq_enable();
49 }
50 
51 /* Inline functions */
gpio_read_bit(u32 reg,int gpio)52 static inline int gpio_read_bit(u32 reg, int gpio)
53 {
54 	u32 bit, val;
55 	int ret = -EFAULT;
56 
57 	if (gpio < 0)
58 		goto out;
59 
60 	bit = GPIO_BIT(gpio);
61 	if (bit) {
62 		val = __raw_readl(PIO_VA_BASE + reg);
63 		ret = (val & bit) ? 1 : 0;
64 	}
65 out:
66 	return ret;
67 }
68 
gpio_set_bit(u32 reg,int gpio)69 static inline int gpio_set_bit(u32 reg, int gpio)
70 {
71 	u32 bit, val;
72 	int ret = -EFAULT;
73 
74 	if (gpio < 0)
75 		goto out;
76 
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;
83 	}
84 out:
85 	return ret;
86 }
87 
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
94 
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
101 };
102 
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
109 };
110 
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
117 };
118 
pnx4008_gpio_register_pin(unsigned short pin)119 int pnx4008_gpio_register_pin(unsigned short pin)
120 {
121 	unsigned long bit = GPIO_BIT(pin);
122 	int ret = -EBUSY;	/* Already in use */
123 
124 	gpio_lock();
125 
126 	if (GPIO_ISBID(pin)) {
127 		if (access_map[GPIO_INDEX] & bit)
128 			goto out;
129 		access_map[GPIO_INDEX] |= bit;
130 
131 	} else if (GPIO_ISRAM(pin)) {
132 		if (access_map[GPIO_INDEX] & bit)
133 			goto out;
134 		access_map[GPIO_INDEX] |= bit;
135 
136 	} else if (GPIO_ISMUX(pin)) {
137 		if (access_map[MUX_INDEX] & bit)
138 			goto out;
139 		access_map[MUX_INDEX] |= bit;
140 
141 	} else if (GPIO_ISOUT(pin)) {
142 		if (access_map[OUTP_INDEX] & bit)
143 			goto out;
144 		access_map[OUTP_INDEX] |= bit;
145 
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;
153 
154 out:
155 	gpio_unlock();
156 	return ret;
157 }
158 
159 EXPORT_SYMBOL(pnx4008_gpio_register_pin);
160 
pnx4008_gpio_unregister_pin(unsigned short pin)161 int pnx4008_gpio_unregister_pin(unsigned short pin)
162 {
163 	unsigned long bit = GPIO_BIT(pin);
164 	int ret = -EFAULT;	/* Not registered */
165 
166 	gpio_lock();
167 
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;
191 
192 out:
193 	gpio_unlock();
194 	return ret;
195 }
196 
197 EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
198 
pnx4008_gpio_read_pin(unsigned short pin)199 unsigned long pnx4008_gpio_read_pin(unsigned short pin)
200 {
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);
209 		}
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);
219 	}
220 	gpio_unlock();
221 	return ret;
222 }
223 
224 EXPORT_SYMBOL(pnx4008_gpio_read_pin);
225 
226 /* Write Value to output */
pnx4008_gpio_write_pin(unsigned short pin,int output)227 int pnx4008_gpio_write_pin(unsigned short pin, int output)
228 {
229 	int gpio = GPIO_BIT_MASK(pin);
230 	int ret = -EFAULT;
231 
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);
245 	}
246 	gpio_unlock();
247 	return ret;
248 }
249 
250 EXPORT_SYMBOL(pnx4008_gpio_write_pin);
251 
252 /* Value = 1 : Set GPIO pin as output */
253 /* Value = 0 : Set GPIO pin as input */
pnx4008_gpio_set_pin_direction(unsigned short pin,int output)254 int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
255 {
256 	int gpio = GPIO_BIT_MASK(pin);
257 	int ret = -EFAULT;
258 
259 	gpio_lock();
260 	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
261 		ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
262 	}
263 	gpio_unlock();
264 	return ret;
265 }
266 
267 EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
268 
269 /* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
pnx4008_gpio_read_pin_direction(unsigned short pin)270 int pnx4008_gpio_read_pin_direction(unsigned short pin)
271 {
272 	int gpio = GPIO_BIT_MASK(pin);
273 	int ret = -EFAULT;
274 
275 	gpio_lock();
276 	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
277 		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
278 	}
279 	gpio_unlock();
280 	return ret;
281 }
282 
283 EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
284 
285 /* Value = 1 : Set pin to muxed function  */
286 /* Value = 0 : Set pin as GPIO */
pnx4008_gpio_set_pin_mux(unsigned short pin,int output)287 int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
288 {
289 	int gpio = GPIO_BIT_MASK(pin);
290 	int ret = -EFAULT;
291 
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);
303 	}
304 	gpio_unlock();
305 	return ret;
306 }
307 
308 EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
309 
310 /* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
pnx4008_gpio_read_pin_mux(unsigned short pin)311 int pnx4008_gpio_read_pin_mux(unsigned short pin)
312 {
313 	int gpio = GPIO_BIT_MASK(pin);
314 	int ret = -EFAULT;
315 
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);
323 	}
324 	gpio_unlock();
325 	return ret;
326 }
327 
328 EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
329