blob: f219914f5b291efdb9fdbe9391a26ac6c7307932 [file] [log] [blame]
Vitaly Wool78818e42006-05-16 11:54:37 +01001/*
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
Vitaly Wool78818e42006-05-16 11:54:37 +010017#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
Russell Kingfced80c2008-09-06 12:10:45 +010020#include <linux/io.h>
Russell King18b20852009-01-08 11:00:03 +000021#include <mach/hardware.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010022#include <mach/platform.h>
23#include <mach/gpio.h>
Vitaly Wool78818e42006-05-16 11:54:37 +010024
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
42static inline void gpio_lock(void)
43{
44 local_irq_disable();
45}
46
47static inline void gpio_unlock(void)
48{
49 local_irq_enable();
50}
51
52/* Inline functions */
53static 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 }
66out:
67 return ret;
68}
69
70static 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 }
85out:
86 return ret;
87}
88
89/* Very simple access control, bitmap for allocated/free */
90static 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 */
97static 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 */
105static 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 */
113static 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
120int 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
155out:
156 gpio_unlock();
157 return ret;
158}
159
160EXPORT_SYMBOL(pnx4008_gpio_register_pin);
161
162int 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
193out:
194 gpio_unlock();
195 return ret;
196}
197
198EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
199
200unsigned 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
225EXPORT_SYMBOL(pnx4008_gpio_read_pin);
226
227/* Write Value to output */
228int 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
251EXPORT_SYMBOL(pnx4008_gpio_write_pin);
252
253/* Value = 1 : Set GPIO pin as output */
254/* Value = 0 : Set GPIO pin as input */
255int 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
268EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
269
270/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
271int 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
284EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
285
286/* Value = 1 : Set pin to muxed function */
287/* Value = 0 : Set pin as GPIO */
288int 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
309EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
310
311/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
312int 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
329EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);