Merge branch 'tc1100-wmi' into release
[sfrench/cifs-2.6.git] / arch / arm / plat-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 #include <mach/gpio-core.h>
22
23 #include <plat/gpio-cfg.h>
24 #include <plat/gpio-cfg-helpers.h>
25 #include <plat/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 #define OFF_GPCON       (0x00)
53 #define OFF_GPDAT       (0x04)
54
55 #define con_4bit_shift(__off) ((__off) * 4)
56
57 #if 1
58 #define gpio_dbg(x...) do { } while(0)
59 #else
60 #define gpio_dbg(x...) printk(KERN_DEBUG x)
61 #endif
62
63 /* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
64  * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
65  * following example:
66  *
67  * base + 0x00: Control register, 4 bits per gpio
68  *              gpio n: 4 bits starting at (4*n)
69  *              0000 = input, 0001 = output, others mean special-function
70  * base + 0x04: Data register, 1 bit per gpio
71  *              bit n: data bit n
72  *
73  * Note, since the data register is one bit per gpio and is at base + 0x4
74  * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
75  * the output.
76 */
77
78 static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
79 {
80         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
81         void __iomem *base = ourchip->base;
82         unsigned long con;
83
84         con = __raw_readl(base + OFF_GPCON);
85         con &= ~(0xf << con_4bit_shift(offset));
86         __raw_writel(con, base + OFF_GPCON);
87
88         gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
89
90         return 0;
91 }
92
93 static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
94                                        unsigned offset, int value)
95 {
96         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
97         void __iomem *base = ourchip->base;
98         unsigned long con;
99         unsigned long dat;
100
101         con = __raw_readl(base + OFF_GPCON);
102         con &= ~(0xf << con_4bit_shift(offset));
103         con |= 0x1 << con_4bit_shift(offset);
104
105         dat = __raw_readl(base + OFF_GPDAT);
106         if (value)
107                 dat |= 1 << offset;
108         else
109                 dat &= ~(1 << offset);
110
111         __raw_writel(dat, base + OFF_GPDAT);
112         __raw_writel(con, base + OFF_GPCON);
113         __raw_writel(dat, base + OFF_GPDAT);
114
115         gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
116
117         return 0;
118 }
119
120 /* The next set of routines are for the case where the GPIO configuration
121  * registers are 4 bits per GPIO but there is more than one register (the
122  * bank has more than 8 GPIOs.
123  *
124  * This case is the similar to the 4 bit case, but the registers are as
125  * follows:
126  *
127  * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
128  *              gpio n: 4 bits starting at (4*n)
129  *              0000 = input, 0001 = output, others mean special-function
130  * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
131  *              gpio n: 4 bits starting at (4*n)
132  *              0000 = input, 0001 = output, others mean special-function
133  * base + 0x08: Data register, 1 bit per gpio
134  *              bit n: data bit n
135  *
136  * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
137  * store the 'base + 0x4' address so that these routines see the data
138  * register at ourchip->base + 0x04.
139 */
140
141 static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
142 {
143         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
144         void __iomem *base = ourchip->base;
145         void __iomem *regcon = base;
146         unsigned long con;
147
148         if (offset > 7)
149                 offset -= 8;
150         else
151                 regcon -= 4;
152
153         con = __raw_readl(regcon);
154         con &= ~(0xf << con_4bit_shift(offset));
155         __raw_writel(con, regcon);
156
157         gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
158
159         return 0;
160
161 }
162
163 static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
164                                        unsigned offset, int value)
165 {
166         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
167         void __iomem *base = ourchip->base;
168         void __iomem *regcon = base;
169         unsigned long con;
170         unsigned long dat;
171
172         if (offset > 7)
173                 offset -= 8;
174         else
175                 regcon -= 4;
176
177         con = __raw_readl(regcon);
178         con &= ~(0xf << con_4bit_shift(offset));
179         con |= 0x1 << con_4bit_shift(offset);
180
181         dat = __raw_readl(base + OFF_GPDAT);
182         if (value)
183                 dat |= 1 << offset;
184         else
185                 dat &= ~(1 << offset);
186
187         __raw_writel(dat, base + OFF_GPDAT);
188         __raw_writel(con, regcon);
189         __raw_writel(dat, base + OFF_GPDAT);
190
191         gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
192
193         return 0;
194 }
195
196 static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
197         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
198         .set_pull       = s3c_gpio_setpull_updown,
199         .get_pull       = s3c_gpio_getpull_updown,
200 };
201
202 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
203         .cfg_eint       = 7,
204         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
205         .set_pull       = s3c_gpio_setpull_updown,
206         .get_pull       = s3c_gpio_getpull_updown,
207 };
208
209 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
210         .cfg_eint       = 3,
211         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
212         .set_pull       = s3c_gpio_setpull_updown,
213         .get_pull       = s3c_gpio_getpull_updown,
214 };
215
216 int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
217 {
218         return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
219 }
220
221 static struct s3c_gpio_chip gpio_4bit[] = {
222         {
223                 .base   = S3C64XX_GPA_BASE,
224                 .config = &gpio_4bit_cfg_eint0111,
225                 .chip   = {
226                         .base   = S3C64XX_GPA(0),
227                         .ngpio  = S3C64XX_GPIO_A_NR,
228                         .label  = "GPA",
229                 },
230         }, {
231                 .base   = S3C64XX_GPB_BASE,
232                 .config = &gpio_4bit_cfg_eint0111,
233                 .chip   = {
234                         .base   = S3C64XX_GPB(0),
235                         .ngpio  = S3C64XX_GPIO_B_NR,
236                         .label  = "GPB",
237                 },
238         }, {
239                 .base   = S3C64XX_GPC_BASE,
240                 .config = &gpio_4bit_cfg_eint0111,
241                 .chip   = {
242                         .base   = S3C64XX_GPC(0),
243                         .ngpio  = S3C64XX_GPIO_C_NR,
244                         .label  = "GPC",
245                 },
246         }, {
247                 .base   = S3C64XX_GPD_BASE,
248                 .config = &gpio_4bit_cfg_eint0111,
249                 .chip   = {
250                         .base   = S3C64XX_GPD(0),
251                         .ngpio  = S3C64XX_GPIO_D_NR,
252                         .label  = "GPD",
253                 },
254         }, {
255                 .base   = S3C64XX_GPE_BASE,
256                 .config = &gpio_4bit_cfg_noint,
257                 .chip   = {
258                         .base   = S3C64XX_GPE(0),
259                         .ngpio  = S3C64XX_GPIO_E_NR,
260                         .label  = "GPE",
261                 },
262         }, {
263                 .base   = S3C64XX_GPG_BASE,
264                 .config = &gpio_4bit_cfg_eint0111,
265                 .chip   = {
266                         .base   = S3C64XX_GPG(0),
267                         .ngpio  = S3C64XX_GPIO_G_NR,
268                         .label  = "GPG",
269                 },
270         }, {
271                 .base   = S3C64XX_GPM_BASE,
272                 .config = &gpio_4bit_cfg_eint0011,
273                 .chip   = {
274                         .base   = S3C64XX_GPM(0),
275                         .ngpio  = S3C64XX_GPIO_M_NR,
276                         .label  = "GPM",
277                         .to_irq = s3c64xx_gpio2int_gpm,
278                 },
279         },
280 };
281
282 int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
283 {
284         return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
285 }
286
287 static struct s3c_gpio_chip gpio_4bit2[] = {
288         {
289                 .base   = S3C64XX_GPH_BASE + 0x4,
290                 .config = &gpio_4bit_cfg_eint0111,
291                 .chip   = {
292                         .base   = S3C64XX_GPH(0),
293                         .ngpio  = S3C64XX_GPIO_H_NR,
294                         .label  = "GPH",
295                 },
296         }, {
297                 .base   = S3C64XX_GPK_BASE + 0x4,
298                 .config = &gpio_4bit_cfg_noint,
299                 .chip   = {
300                         .base   = S3C64XX_GPK(0),
301                         .ngpio  = S3C64XX_GPIO_K_NR,
302                         .label  = "GPK",
303                 },
304         }, {
305                 .base   = S3C64XX_GPL_BASE + 0x4,
306                 .config = &gpio_4bit_cfg_eint0011,
307                 .chip   = {
308                         .base   = S3C64XX_GPL(0),
309                         .ngpio  = S3C64XX_GPIO_L_NR,
310                         .label  = "GPL",
311                         .to_irq = s3c64xx_gpio2int_gpl,
312                 },
313         },
314 };
315
316 static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
317         .set_config     = s3c_gpio_setcfg_s3c24xx,
318         .set_pull       = s3c_gpio_setpull_updown,
319         .get_pull       = s3c_gpio_getpull_updown,
320 };
321
322 static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
323         .cfg_eint       = 2,
324         .set_config     = s3c_gpio_setcfg_s3c24xx,
325         .set_pull       = s3c_gpio_setpull_updown,
326         .get_pull       = s3c_gpio_getpull_updown,
327 };
328
329 static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
330         .cfg_eint       = 3,
331         .set_config     = s3c_gpio_setcfg_s3c24xx,
332         .set_pull       = s3c_gpio_setpull_updown,
333         .get_pull       = s3c_gpio_getpull_updown,
334 };
335
336 int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
337 {
338         return IRQ_EINT(0) + pin;
339 }
340
341 static struct s3c_gpio_chip gpio_2bit[] = {
342         {
343                 .base   = S3C64XX_GPF_BASE,
344                 .config = &gpio_2bit_cfg_eint11,
345                 .chip   = {
346                         .base   = S3C64XX_GPF(0),
347                         .ngpio  = S3C64XX_GPIO_F_NR,
348                         .label  = "GPF",
349                 },
350         }, {
351                 .base   = S3C64XX_GPI_BASE,
352                 .config = &gpio_2bit_cfg_noint,
353                 .chip   = {
354                         .base   = S3C64XX_GPI(0),
355                         .ngpio  = S3C64XX_GPIO_I_NR,
356                         .label  = "GPI",
357                 },
358         }, {
359                 .base   = S3C64XX_GPJ_BASE,
360                 .config = &gpio_2bit_cfg_noint,
361                 .chip   = {
362                         .base   = S3C64XX_GPJ(0),
363                         .ngpio  = S3C64XX_GPIO_J_NR,
364                         .label  = "GPJ",
365                 },
366         }, {
367                 .base   = S3C64XX_GPN_BASE,
368                 .config = &gpio_2bit_cfg_eint10,
369                 .chip   = {
370                         .base   = S3C64XX_GPN(0),
371                         .ngpio  = S3C64XX_GPIO_N_NR,
372                         .label  = "GPN",
373                         .to_irq = s3c64xx_gpio2int_gpn,
374                 },
375         }, {
376                 .base   = S3C64XX_GPO_BASE,
377                 .config = &gpio_2bit_cfg_eint11,
378                 .chip   = {
379                         .base   = S3C64XX_GPO(0),
380                         .ngpio  = S3C64XX_GPIO_O_NR,
381                         .label  = "GPO",
382                 },
383         }, {
384                 .base   = S3C64XX_GPP_BASE,
385                 .config = &gpio_2bit_cfg_eint11,
386                 .chip   = {
387                         .base   = S3C64XX_GPP(0),
388                         .ngpio  = S3C64XX_GPIO_P_NR,
389                         .label  = "GPP",
390                 },
391         }, {
392                 .base   = S3C64XX_GPQ_BASE,
393                 .config = &gpio_2bit_cfg_eint11,
394                 .chip   = {
395                         .base   = S3C64XX_GPQ(0),
396                         .ngpio  = S3C64XX_GPIO_Q_NR,
397                         .label  = "GPQ",
398                 },
399         },
400 };
401
402 static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
403 {
404         chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
405         chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
406         chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
407 }
408
409 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
410 {
411         chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
412         chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
413         chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
414 }
415
416 static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
417 {
418         chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
419 }
420
421 static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
422                                        int nr_chips,
423                                        void (*fn)(struct s3c_gpio_chip *))
424 {
425         for (; nr_chips > 0; nr_chips--, chips++) {
426                 if (fn)
427                         (fn)(chips);
428                 s3c_gpiolib_add(chips);
429         }
430 }
431
432 static __init int s3c64xx_gpiolib_init(void)
433 {
434         s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
435                             s3c64xx_gpiolib_add_4bit);
436
437         s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
438                             s3c64xx_gpiolib_add_4bit2);
439
440         s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
441                             s3c64xx_gpiolib_add_2bit);
442
443         return 0;
444 }
445
446 core_initcall(s3c64xx_gpiolib_init);