Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
 42 static inline void gpio_lock(void)
 43 {
 44         local_irq_disable();
 45 }
 46 
 47 static inline void gpio_unlock(void)
 48 {
 49         local_irq_enable();
 50 }
 51 
 52 /* Inline functions */
 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 
 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 
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 
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 
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 */
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 */
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*/
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 */
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*/
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 
  This page was automatically generated by the LXR engine.