sparc64: Fix masking and shifting in VIS fpcmp emulation.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / arm / mach-s5p64x0 / gpiolib.c
blobe7fb3b004e77b6f3ce90121a41074fa075ddb489
1 /* linux/arch/arm/mach-s5p64x0/gpiolib.c
3 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * S5P64X0 - GPIOlib support
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/kernel.h>
14 #include <linux/irq.h>
15 #include <linux/io.h>
16 #include <linux/gpio.h>
18 #include <mach/map.h>
19 #include <mach/regs-gpio.h>
20 #include <mach/regs-clock.h>
22 #include <plat/gpio-core.h>
23 #include <plat/gpio-cfg.h>
24 #include <plat/gpio-cfg-helpers.h>
27 * S5P6440 GPIO bank summary:
29 * Bank GPIOs Style SlpCon ExtInt Group
30 * A 6 4Bit Yes 1
31 * B 7 4Bit Yes 1
32 * C 8 4Bit Yes 2
33 * F 2 2Bit Yes 4 [1]
34 * G 7 4Bit Yes 5
35 * H 10 4Bit[2] Yes 6
36 * I 16 2Bit Yes None
37 * J 12 2Bit Yes None
38 * N 16 2Bit No IRQ_EINT
39 * P 8 2Bit Yes 8
40 * R 15 4Bit[2] Yes 8
42 * S5P6450 GPIO bank summary:
44 * Bank GPIOs Style SlpCon ExtInt Group
45 * A 6 4Bit Yes 1
46 * B 7 4Bit Yes 1
47 * C 8 4Bit Yes 2
48 * D 8 4Bit Yes None
49 * F 2 2Bit Yes None
50 * G 14 4Bit[2] Yes 5
51 * H 10 4Bit[2] Yes 6
52 * I 16 2Bit Yes None
53 * J 12 2Bit Yes None
54 * K 5 4Bit Yes None
55 * N 16 2Bit No IRQ_EINT
56 * P 11 2Bit Yes 8
57 * Q 14 2Bit Yes None
58 * R 15 4Bit[2] Yes None
59 * S 8 2Bit Yes None
61 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
62 * [2] BANK has two control registers, GPxCON0 and GPxCON1
65 static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
66 unsigned int offset)
68 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
69 void __iomem *base = ourchip->base;
70 void __iomem *regcon = base;
71 unsigned long con;
72 unsigned long flags;
74 switch (offset) {
75 case 6:
76 offset += 1;
77 case 0:
78 case 1:
79 case 2:
80 case 3:
81 case 4:
82 case 5:
83 regcon -= 4;
84 break;
85 default:
86 offset -= 7;
87 break;
90 s3c_gpio_lock(ourchip, flags);
92 con = __raw_readl(regcon);
93 con &= ~(0xf << con_4bit_shift(offset));
94 __raw_writel(con, regcon);
96 s3c_gpio_unlock(ourchip, flags);
98 return 0;
101 static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
102 unsigned int offset, int value)
104 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
105 void __iomem *base = ourchip->base;
106 void __iomem *regcon = base;
107 unsigned long con;
108 unsigned long dat;
109 unsigned long flags;
110 unsigned con_offset = offset;
112 switch (con_offset) {
113 case 6:
114 con_offset += 1;
115 case 0:
116 case 1:
117 case 2:
118 case 3:
119 case 4:
120 case 5:
121 regcon -= 4;
122 break;
123 default:
124 con_offset -= 7;
125 break;
128 s3c_gpio_lock(ourchip, flags);
130 con = __raw_readl(regcon);
131 con &= ~(0xf << con_4bit_shift(con_offset));
132 con |= 0x1 << con_4bit_shift(con_offset);
134 dat = __raw_readl(base + GPIODAT_OFF);
135 if (value)
136 dat |= 1 << offset;
137 else
138 dat &= ~(1 << offset);
140 __raw_writel(con, regcon);
141 __raw_writel(dat, base + GPIODAT_OFF);
143 s3c_gpio_unlock(ourchip, flags);
145 return 0;
148 int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
149 unsigned int off, unsigned int cfg)
151 void __iomem *reg = chip->base;
152 unsigned int shift;
153 u32 con;
155 switch (off) {
156 case 0:
157 case 1:
158 case 2:
159 case 3:
160 case 4:
161 case 5:
162 shift = (off & 7) * 4;
163 reg -= 4;
164 break;
165 case 6:
166 shift = ((off + 1) & 7) * 4;
167 reg -= 4;
168 default:
169 shift = ((off + 1) & 7) * 4;
170 break;
173 if (s3c_gpio_is_cfg_special(cfg)) {
174 cfg &= 0xf;
175 cfg <<= shift;
178 con = __raw_readl(reg);
179 con &= ~(0xf << shift);
180 con |= cfg;
181 __raw_writel(con, reg);
183 return 0;
186 static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
188 .cfg_eint = 0,
189 }, {
190 .cfg_eint = 7,
191 }, {
192 .cfg_eint = 3,
193 .set_config = s5p64x0_gpio_setcfg_4bit_rbank,
194 }, {
195 .cfg_eint = 0,
196 .set_config = s3c_gpio_setcfg_s3c24xx,
197 .get_config = s3c_gpio_getcfg_s3c24xx,
198 }, {
199 .cfg_eint = 2,
200 .set_config = s3c_gpio_setcfg_s3c24xx,
201 .get_config = s3c_gpio_getcfg_s3c24xx,
202 }, {
203 .cfg_eint = 3,
204 .set_config = s3c_gpio_setcfg_s3c24xx,
205 .get_config = s3c_gpio_getcfg_s3c24xx,
209 static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
211 .base = S5P64X0_GPA_BASE,
212 .config = &s5p64x0_gpio_cfgs[1],
213 .chip = {
214 .base = S5P6440_GPA(0),
215 .ngpio = S5P6440_GPIO_A_NR,
216 .label = "GPA",
218 }, {
219 .base = S5P64X0_GPB_BASE,
220 .config = &s5p64x0_gpio_cfgs[1],
221 .chip = {
222 .base = S5P6440_GPB(0),
223 .ngpio = S5P6440_GPIO_B_NR,
224 .label = "GPB",
226 }, {
227 .base = S5P64X0_GPC_BASE,
228 .config = &s5p64x0_gpio_cfgs[1],
229 .chip = {
230 .base = S5P6440_GPC(0),
231 .ngpio = S5P6440_GPIO_C_NR,
232 .label = "GPC",
234 }, {
235 .base = S5P64X0_GPG_BASE,
236 .config = &s5p64x0_gpio_cfgs[1],
237 .chip = {
238 .base = S5P6440_GPG(0),
239 .ngpio = S5P6440_GPIO_G_NR,
240 .label = "GPG",
245 static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
247 .base = S5P64X0_GPH_BASE + 0x4,
248 .config = &s5p64x0_gpio_cfgs[1],
249 .chip = {
250 .base = S5P6440_GPH(0),
251 .ngpio = S5P6440_GPIO_H_NR,
252 .label = "GPH",
257 static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
259 .base = S5P64X0_GPR_BASE + 0x4,
260 .config = &s5p64x0_gpio_cfgs[2],
261 .chip = {
262 .base = S5P6440_GPR(0),
263 .ngpio = S5P6440_GPIO_R_NR,
264 .label = "GPR",
269 static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
271 .base = S5P64X0_GPF_BASE,
272 .config = &s5p64x0_gpio_cfgs[5],
273 .chip = {
274 .base = S5P6440_GPF(0),
275 .ngpio = S5P6440_GPIO_F_NR,
276 .label = "GPF",
278 }, {
279 .base = S5P64X0_GPI_BASE,
280 .config = &s5p64x0_gpio_cfgs[3],
281 .chip = {
282 .base = S5P6440_GPI(0),
283 .ngpio = S5P6440_GPIO_I_NR,
284 .label = "GPI",
286 }, {
287 .base = S5P64X0_GPJ_BASE,
288 .config = &s5p64x0_gpio_cfgs[3],
289 .chip = {
290 .base = S5P6440_GPJ(0),
291 .ngpio = S5P6440_GPIO_J_NR,
292 .label = "GPJ",
294 }, {
295 .base = S5P64X0_GPN_BASE,
296 .config = &s5p64x0_gpio_cfgs[4],
297 .chip = {
298 .base = S5P6440_GPN(0),
299 .ngpio = S5P6440_GPIO_N_NR,
300 .label = "GPN",
302 }, {
303 .base = S5P64X0_GPP_BASE,
304 .config = &s5p64x0_gpio_cfgs[5],
305 .chip = {
306 .base = S5P6440_GPP(0),
307 .ngpio = S5P6440_GPIO_P_NR,
308 .label = "GPP",
313 static struct s3c_gpio_chip s5p6450_gpio_4bit[] = {
315 .base = S5P64X0_GPA_BASE,
316 .config = &s5p64x0_gpio_cfgs[1],
317 .chip = {
318 .base = S5P6450_GPA(0),
319 .ngpio = S5P6450_GPIO_A_NR,
320 .label = "GPA",
322 }, {
323 .base = S5P64X0_GPB_BASE,
324 .config = &s5p64x0_gpio_cfgs[1],
325 .chip = {
326 .base = S5P6450_GPB(0),
327 .ngpio = S5P6450_GPIO_B_NR,
328 .label = "GPB",
330 }, {
331 .base = S5P64X0_GPC_BASE,
332 .config = &s5p64x0_gpio_cfgs[1],
333 .chip = {
334 .base = S5P6450_GPC(0),
335 .ngpio = S5P6450_GPIO_C_NR,
336 .label = "GPC",
338 }, {
339 .base = S5P6450_GPD_BASE,
340 .config = &s5p64x0_gpio_cfgs[1],
341 .chip = {
342 .base = S5P6450_GPD(0),
343 .ngpio = S5P6450_GPIO_D_NR,
344 .label = "GPD",
346 }, {
347 .base = S5P6450_GPK_BASE,
348 .config = &s5p64x0_gpio_cfgs[1],
349 .chip = {
350 .base = S5P6450_GPK(0),
351 .ngpio = S5P6450_GPIO_K_NR,
352 .label = "GPK",
357 static struct s3c_gpio_chip s5p6450_gpio_4bit2[] = {
359 .base = S5P64X0_GPG_BASE + 0x4,
360 .config = &s5p64x0_gpio_cfgs[1],
361 .chip = {
362 .base = S5P6450_GPG(0),
363 .ngpio = S5P6450_GPIO_G_NR,
364 .label = "GPG",
366 }, {
367 .base = S5P64X0_GPH_BASE + 0x4,
368 .config = &s5p64x0_gpio_cfgs[1],
369 .chip = {
370 .base = S5P6450_GPH(0),
371 .ngpio = S5P6450_GPIO_H_NR,
372 .label = "GPH",
377 static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2[] = {
379 .base = S5P64X0_GPR_BASE + 0x4,
380 .config = &s5p64x0_gpio_cfgs[2],
381 .chip = {
382 .base = S5P6450_GPR(0),
383 .ngpio = S5P6450_GPIO_R_NR,
384 .label = "GPR",
389 static struct s3c_gpio_chip s5p6450_gpio_2bit[] = {
391 .base = S5P64X0_GPF_BASE,
392 .config = &s5p64x0_gpio_cfgs[5],
393 .chip = {
394 .base = S5P6450_GPF(0),
395 .ngpio = S5P6450_GPIO_F_NR,
396 .label = "GPF",
398 }, {
399 .base = S5P64X0_GPI_BASE,
400 .config = &s5p64x0_gpio_cfgs[3],
401 .chip = {
402 .base = S5P6450_GPI(0),
403 .ngpio = S5P6450_GPIO_I_NR,
404 .label = "GPI",
406 }, {
407 .base = S5P64X0_GPJ_BASE,
408 .config = &s5p64x0_gpio_cfgs[3],
409 .chip = {
410 .base = S5P6450_GPJ(0),
411 .ngpio = S5P6450_GPIO_J_NR,
412 .label = "GPJ",
414 }, {
415 .base = S5P64X0_GPN_BASE,
416 .config = &s5p64x0_gpio_cfgs[4],
417 .chip = {
418 .base = S5P6450_GPN(0),
419 .ngpio = S5P6450_GPIO_N_NR,
420 .label = "GPN",
422 }, {
423 .base = S5P64X0_GPP_BASE,
424 .config = &s5p64x0_gpio_cfgs[5],
425 .chip = {
426 .base = S5P6450_GPP(0),
427 .ngpio = S5P6450_GPIO_P_NR,
428 .label = "GPP",
430 }, {
431 .base = S5P6450_GPQ_BASE,
432 .config = &s5p64x0_gpio_cfgs[4],
433 .chip = {
434 .base = S5P6450_GPQ(0),
435 .ngpio = S5P6450_GPIO_Q_NR,
436 .label = "GPQ",
438 }, {
439 .base = S5P6450_GPS_BASE,
440 .config = &s5p64x0_gpio_cfgs[5],
441 .chip = {
442 .base = S5P6450_GPS(0),
443 .ngpio = S5P6450_GPIO_S_NR,
444 .label = "GPS",
449 void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
451 for (; nr_chips > 0; nr_chips--, chipcfg++) {
452 if (!chipcfg->set_config)
453 chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit;
454 if (!chipcfg->get_config)
455 chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit;
456 if (!chipcfg->set_pull)
457 chipcfg->set_pull = s3c_gpio_setpull_updown;
458 if (!chipcfg->get_pull)
459 chipcfg->get_pull = s3c_gpio_getpull_updown;
463 static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
464 int nr_chips)
466 for (; nr_chips > 0; nr_chips--, chip++) {
467 chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
468 chip->chip.direction_output =
469 s5p64x0_gpiolib_rbank_4bit2_output;
470 s3c_gpiolib_add(chip);
474 static int __init s5p64x0_gpiolib_init(void)
476 unsigned int chipid;
478 chipid = __raw_readl(S5P64X0_SYS_ID);
480 s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
481 ARRAY_SIZE(s5p64x0_gpio_cfgs));
483 if ((chipid & 0xff000) == 0x50000) {
484 samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
485 ARRAY_SIZE(s5p6450_gpio_2bit));
487 samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit,
488 ARRAY_SIZE(s5p6450_gpio_4bit));
490 samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2,
491 ARRAY_SIZE(s5p6450_gpio_4bit2));
493 s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2,
494 ARRAY_SIZE(s5p6450_gpio_rbank_4bit2));
495 } else {
496 samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit,
497 ARRAY_SIZE(s5p6440_gpio_2bit));
499 samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
500 ARRAY_SIZE(s5p6440_gpio_4bit));
502 samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
503 ARRAY_SIZE(s5p6440_gpio_4bit2));
505 s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
506 ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
509 return 0;
511 core_initcall(s5p64x0_gpiolib_init);