Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / arch / arm / mach-s3c64xx / gpiolib.c
1 /* arch/arm/plat-s3c64xx/gpiolib.c
2  *
3  * Copyright 2008 Openmoko, Inc.
4  * Copyright 2008 Simtec Electronics
5  *      Ben Dooks <ben@simtec.co.uk>
6  *      http://armlinux.simtec.co.uk/
7  *
8  * S3C64XX - GPIOlib support 
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/kernel.h>
16 #include <linux/irq.h>
17 #include <linux/io.h>
18
19 #include <mach/map.h>
20 #include <mach/gpio.h>
21
22 #include <plat/gpio-core.h>
23 #include <plat/gpio-cfg.h>
24 #include <plat/gpio-cfg-helpers.h>
25 #include <mach/regs-gpio.h>
26
27 /* GPIO bank summary:
28  *
29  * Bank GPIOs   Style   SlpCon  ExtInt Group
30  * A    8       4Bit    Yes     1
31  * B    7       4Bit    Yes     1
32  * C    8       4Bit    Yes     2
33  * D    5       4Bit    Yes     3
34  * E    5       4Bit    Yes     None
35  * F    16      2Bit    Yes     4 [1]
36  * G    7       4Bit    Yes     5
37  * H    10      4Bit[2] Yes     6
38  * I    16      2Bit    Yes     None
39  * J    12      2Bit    Yes     None
40  * K    16      4Bit[2] No      None
41  * L    15      4Bit[2] No      None
42  * M    6       4Bit    No      IRQ_EINT
43  * N    16      2Bit    No      IRQ_EINT
44  * O    16      2Bit    Yes     7
45  * P    15      2Bit    Yes     8
46  * Q    9       2Bit    Yes     9
47  *
48  * [1] BANKF pins 14,15 do not form part of the external interrupt sources
49  * [2] BANK has two control registers, GPxCON0 and GPxCON1
50  */
51
52 static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
53         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
54         .set_pull       = s3c_gpio_setpull_updown,
55         .get_pull       = s3c_gpio_getpull_updown,
56 };
57
58 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
59         .cfg_eint       = 7,
60         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
61         .set_pull       = s3c_gpio_setpull_updown,
62         .get_pull       = s3c_gpio_getpull_updown,
63 };
64
65 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
66         .cfg_eint       = 3,
67         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
68         .set_pull       = s3c_gpio_setpull_updown,
69         .get_pull       = s3c_gpio_getpull_updown,
70 };
71
72 int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
73 {
74         return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
75 }
76
77 static struct s3c_gpio_chip gpio_4bit[] = {
78         {
79                 .base   = S3C64XX_GPA_BASE,
80                 .config = &gpio_4bit_cfg_eint0111,
81                 .chip   = {
82                         .base   = S3C64XX_GPA(0),
83                         .ngpio  = S3C64XX_GPIO_A_NR,
84                         .label  = "GPA",
85                 },
86         }, {
87                 .base   = S3C64XX_GPB_BASE,
88                 .config = &gpio_4bit_cfg_eint0111,
89                 .chip   = {
90                         .base   = S3C64XX_GPB(0),
91                         .ngpio  = S3C64XX_GPIO_B_NR,
92                         .label  = "GPB",
93                 },
94         }, {
95                 .base   = S3C64XX_GPC_BASE,
96                 .config = &gpio_4bit_cfg_eint0111,
97                 .chip   = {
98                         .base   = S3C64XX_GPC(0),
99                         .ngpio  = S3C64XX_GPIO_C_NR,
100                         .label  = "GPC",
101                 },
102         }, {
103                 .base   = S3C64XX_GPD_BASE,
104                 .config = &gpio_4bit_cfg_eint0111,
105                 .chip   = {
106                         .base   = S3C64XX_GPD(0),
107                         .ngpio  = S3C64XX_GPIO_D_NR,
108                         .label  = "GPD",
109                 },
110         }, {
111                 .base   = S3C64XX_GPE_BASE,
112                 .config = &gpio_4bit_cfg_noint,
113                 .chip   = {
114                         .base   = S3C64XX_GPE(0),
115                         .ngpio  = S3C64XX_GPIO_E_NR,
116                         .label  = "GPE",
117                 },
118         }, {
119                 .base   = S3C64XX_GPG_BASE,
120                 .config = &gpio_4bit_cfg_eint0111,
121                 .chip   = {
122                         .base   = S3C64XX_GPG(0),
123                         .ngpio  = S3C64XX_GPIO_G_NR,
124                         .label  = "GPG",
125                 },
126         }, {
127                 .base   = S3C64XX_GPM_BASE,
128                 .config = &gpio_4bit_cfg_eint0011,
129                 .chip   = {
130                         .base   = S3C64XX_GPM(0),
131                         .ngpio  = S3C64XX_GPIO_M_NR,
132                         .label  = "GPM",
133                         .to_irq = s3c64xx_gpio2int_gpm,
134                 },
135         },
136 };
137
138 int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
139 {
140         return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
141 }
142
143 static struct s3c_gpio_chip gpio_4bit2[] = {
144         {
145                 .base   = S3C64XX_GPH_BASE + 0x4,
146                 .config = &gpio_4bit_cfg_eint0111,
147                 .chip   = {
148                         .base   = S3C64XX_GPH(0),
149                         .ngpio  = S3C64XX_GPIO_H_NR,
150                         .label  = "GPH",
151                 },
152         }, {
153                 .base   = S3C64XX_GPK_BASE + 0x4,
154                 .config = &gpio_4bit_cfg_noint,
155                 .chip   = {
156                         .base   = S3C64XX_GPK(0),
157                         .ngpio  = S3C64XX_GPIO_K_NR,
158                         .label  = "GPK",
159                 },
160         }, {
161                 .base   = S3C64XX_GPL_BASE + 0x4,
162                 .config = &gpio_4bit_cfg_eint0011,
163                 .chip   = {
164                         .base   = S3C64XX_GPL(0),
165                         .ngpio  = S3C64XX_GPIO_L_NR,
166                         .label  = "GPL",
167                         .to_irq = s3c64xx_gpio2int_gpl,
168                 },
169         },
170 };
171
172 static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
173         .set_config     = s3c_gpio_setcfg_s3c24xx,
174         .set_pull       = s3c_gpio_setpull_updown,
175         .get_pull       = s3c_gpio_getpull_updown,
176 };
177
178 static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
179         .cfg_eint       = 2,
180         .set_config     = s3c_gpio_setcfg_s3c24xx,
181         .set_pull       = s3c_gpio_setpull_updown,
182         .get_pull       = s3c_gpio_getpull_updown,
183 };
184
185 static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
186         .cfg_eint       = 3,
187         .set_config     = s3c_gpio_setcfg_s3c24xx,
188         .set_pull       = s3c_gpio_setpull_updown,
189         .get_pull       = s3c_gpio_getpull_updown,
190 };
191
192 int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
193 {
194         return IRQ_EINT(0) + pin;
195 }
196
197 static struct s3c_gpio_chip gpio_2bit[] = {
198         {
199                 .base   = S3C64XX_GPF_BASE,
200                 .config = &gpio_2bit_cfg_eint11,
201                 .chip   = {
202                         .base   = S3C64XX_GPF(0),
203                         .ngpio  = S3C64XX_GPIO_F_NR,
204                         .label  = "GPF",
205                 },
206         }, {
207                 .base   = S3C64XX_GPI_BASE,
208                 .config = &gpio_2bit_cfg_noint,
209                 .chip   = {
210                         .base   = S3C64XX_GPI(0),
211                         .ngpio  = S3C64XX_GPIO_I_NR,
212                         .label  = "GPI",
213                 },
214         }, {
215                 .base   = S3C64XX_GPJ_BASE,
216                 .config = &gpio_2bit_cfg_noint,
217                 .chip   = {
218                         .base   = S3C64XX_GPJ(0),
219                         .ngpio  = S3C64XX_GPIO_J_NR,
220                         .label  = "GPJ",
221                 },
222         }, {
223                 .base   = S3C64XX_GPN_BASE,
224                 .config = &gpio_2bit_cfg_eint10,
225                 .chip   = {
226                         .base   = S3C64XX_GPN(0),
227                         .ngpio  = S3C64XX_GPIO_N_NR,
228                         .label  = "GPN",
229                         .to_irq = s3c64xx_gpio2int_gpn,
230                 },
231         }, {
232                 .base   = S3C64XX_GPO_BASE,
233                 .config = &gpio_2bit_cfg_eint11,
234                 .chip   = {
235                         .base   = S3C64XX_GPO(0),
236                         .ngpio  = S3C64XX_GPIO_O_NR,
237                         .label  = "GPO",
238                 },
239         }, {
240                 .base   = S3C64XX_GPP_BASE,
241                 .config = &gpio_2bit_cfg_eint11,
242                 .chip   = {
243                         .base   = S3C64XX_GPP(0),
244                         .ngpio  = S3C64XX_GPIO_P_NR,
245                         .label  = "GPP",
246                 },
247         }, {
248                 .base   = S3C64XX_GPQ_BASE,
249                 .config = &gpio_2bit_cfg_eint11,
250                 .chip   = {
251                         .base   = S3C64XX_GPQ(0),
252                         .ngpio  = S3C64XX_GPIO_Q_NR,
253                         .label  = "GPQ",
254                 },
255         },
256 };
257
258 static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
259 {
260         chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
261 }
262
263 static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
264                                        int nr_chips,
265                                        void (*fn)(struct s3c_gpio_chip *))
266 {
267         for (; nr_chips > 0; nr_chips--, chips++) {
268                 if (fn)
269                         (fn)(chips);
270                 s3c_gpiolib_add(chips);
271         }
272 }
273
274 static __init int s3c64xx_gpiolib_init(void)
275 {
276         s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
277                             samsung_gpiolib_add_4bit);
278
279         s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
280                             samsung_gpiolib_add_4bit2);
281
282         s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
283                             s3c64xx_gpiolib_add_2bit);
284
285         return 0;
286 }
287
288 core_initcall(s3c64xx_gpiolib_init);