Merge branch 'pending' of master.kernel.org:/pub/scm/linux/kernel/git/vxy/lksctp-dev
[sfrench/cifs-2.6.git] / arch / arm / mach-pxa / gpio.c
1 /*
2  *  linux/arch/arm/mach-pxa/gpio.c
3  *
4  *  Generic PXA GPIO handling
5  *
6  *  Author:     Nicolas Pitre
7  *  Created:    Jun 15, 2001
8  *  Copyright:  MontaVista Software Inc.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2 as
12  *  published by the Free Software Foundation.
13  */
14
15 #include <linux/init.h>
16 #include <linux/module.h>
17
18 #include <asm/gpio.h>
19 #include <asm/hardware.h>
20 #include <asm/io.h>
21 #include <asm/arch/pxa-regs.h>
22
23 #include "generic.h"
24
25
26 struct pxa_gpio_chip {
27         struct gpio_chip chip;
28         void __iomem     *regbase;
29 };
30
31 int pxa_last_gpio;
32
33 /*
34  * Configure pins for GPIO or other functions
35  */
36 int pxa_gpio_mode(int gpio_mode)
37 {
38         unsigned long flags;
39         int gpio = gpio_mode & GPIO_MD_MASK_NR;
40         int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
41         int gafr;
42
43         if (gpio > pxa_last_gpio)
44                 return -EINVAL;
45
46         local_irq_save(flags);
47         if (gpio_mode & GPIO_DFLT_LOW)
48                 GPCR(gpio) = GPIO_bit(gpio);
49         else if (gpio_mode & GPIO_DFLT_HIGH)
50                 GPSR(gpio) = GPIO_bit(gpio);
51         if (gpio_mode & GPIO_MD_MASK_DIR)
52                 GPDR(gpio) |= GPIO_bit(gpio);
53         else
54                 GPDR(gpio) &= ~GPIO_bit(gpio);
55         gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
56         GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
57         local_irq_restore(flags);
58
59         return 0;
60 }
61 EXPORT_SYMBOL(pxa_gpio_mode);
62
63 static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
64 {
65         unsigned long        flags;
66         u32                  mask = 1 << offset;
67         u32                  value;
68         struct pxa_gpio_chip *pxa;
69         void __iomem         *gpdr;
70
71         pxa = container_of(chip, struct pxa_gpio_chip, chip);
72         gpdr = pxa->regbase + GPDR_OFFSET;
73         local_irq_save(flags);
74         value = __raw_readl(gpdr);
75         value &= ~mask;
76         __raw_writel(value, gpdr);
77         local_irq_restore(flags);
78
79         return 0;
80 }
81
82 static int pxa_gpio_direction_output(struct gpio_chip *chip,
83                                         unsigned offset, int value)
84 {
85         unsigned long        flags;
86         u32                  mask = 1 << offset;
87         u32                  tmp;
88         struct pxa_gpio_chip *pxa;
89         void __iomem         *gpdr;
90
91         pxa = container_of(chip, struct pxa_gpio_chip, chip);
92         __raw_writel(mask,
93                         pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
94         gpdr = pxa->regbase + GPDR_OFFSET;
95         local_irq_save(flags);
96         tmp = __raw_readl(gpdr);
97         tmp |= mask;
98         __raw_writel(tmp, gpdr);
99         local_irq_restore(flags);
100
101         return 0;
102 }
103
104 /*
105  * Return GPIO level
106  */
107 static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
108 {
109         u32                  mask = 1 << offset;
110         struct pxa_gpio_chip *pxa;
111
112         pxa = container_of(chip, struct pxa_gpio_chip, chip);
113         return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
114 }
115
116 /*
117  * Set output GPIO level
118  */
119 static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
120 {
121         u32                  mask = 1 << offset;
122         struct pxa_gpio_chip *pxa;
123
124         pxa = container_of(chip, struct pxa_gpio_chip, chip);
125
126         if (value)
127                 __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
128         else
129                 __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
130 }
131
132 static struct pxa_gpio_chip pxa_gpio_chip[] = {
133         [0] = {
134                 .regbase = GPIO0_BASE,
135                 .chip = {
136                         .label            = "gpio-0",
137                         .direction_input  = pxa_gpio_direction_input,
138                         .direction_output = pxa_gpio_direction_output,
139                         .get              = pxa_gpio_get,
140                         .set              = pxa_gpio_set,
141                         .base             = 0,
142                         .ngpio            = 32,
143                 },
144         },
145         [1] = {
146                 .regbase = GPIO1_BASE,
147                 .chip = {
148                         .label            = "gpio-1",
149                         .direction_input  = pxa_gpio_direction_input,
150                         .direction_output = pxa_gpio_direction_output,
151                         .get              = pxa_gpio_get,
152                         .set              = pxa_gpio_set,
153                         .base             = 32,
154                         .ngpio            = 32,
155                 },
156         },
157         [2] = {
158                 .regbase = GPIO2_BASE,
159                 .chip = {
160                         .label            = "gpio-2",
161                         .direction_input  = pxa_gpio_direction_input,
162                         .direction_output = pxa_gpio_direction_output,
163                         .get              = pxa_gpio_get,
164                         .set              = pxa_gpio_set,
165                         .base             = 64,
166                         .ngpio            = 32, /* 21 for PXA25x */
167                 },
168         },
169 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
170         [3] = {
171                 .regbase = GPIO3_BASE,
172                 .chip = {
173                         .label            = "gpio-3",
174                         .direction_input  = pxa_gpio_direction_input,
175                         .direction_output = pxa_gpio_direction_output,
176                         .get              = pxa_gpio_get,
177                         .set              = pxa_gpio_set,
178                         .base             = 96,
179                         .ngpio            = 32,
180                 },
181         },
182 #endif
183 };
184
185 void __init pxa_init_gpio(int gpio_nr)
186 {
187         int i;
188
189         /* add a GPIO chip for each register bank.
190          * the last PXA25x register only contains 21 GPIOs
191          */
192         for (i = 0; i < gpio_nr; i += 32) {
193                 if (i+32 > gpio_nr)
194                         pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
195                 gpiochip_add(&pxa_gpio_chip[i/32].chip);
196         }
197 }