aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2011-08-30 07:39:08 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-09-21 02:06:05 -0400
commit1b39d5f2cc5c28085bbf48db80bf704ab4dedda9 (patch)
treec75a0e8468865c3657bb2ec750a118cb4a81948b /drivers/gpio
parentc4b3fd38dfb677d7a3997527c9cbdc21b81424a3 (diff)
gpio/samsung: gpio-samsung.c to support Samsung GPIOs
This patch adds support for Samsung GPIOs with one gpio driver and removes old GPIO drivers which are drivers/gpio-s3c24xx.c, gpio-s3c64xx.c, gpio-s5p64x0.c, gpio-s5pc100.c, gpio-s5pv210.c, gpio-exynos4.c, gpio-plat-samsung.c, plat-samsung/gpio-config.c and gpio.c to support each Samsung SoCs before. Because the gpio-samsung.c can replace old Samsung GPIO drivers. Basically, the gpio-samsung.c has been made by their merging and removing duplicated definitions. Note: gpio-samsung.c includes some SoC dependent codes and it will be replaced next time. Cc: Ben Dooks <ben-linux@fluff.org> Acked-by: Grant Likely <grant.likely@secretlab.ca> [kgene.kim@samsung.com: squash the removing and adding patches] [kgene.kim@samsung.com: fixes bug during to register of gpio_chips] Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig28
-rw-r--r--drivers/gpio/Makefile10
-rw-r--r--drivers/gpio/gpio-exynos4.c385
-rw-r--r--drivers/gpio/gpio-plat-samsung.c205
-rw-r--r--drivers/gpio/gpio-s3c24xx.c283
-rw-r--r--drivers/gpio/gpio-s3c64xx.c289
-rw-r--r--drivers/gpio/gpio-s5p64x0.c510
-rw-r--r--drivers/gpio/gpio-s5pc100.c354
-rw-r--r--drivers/gpio/gpio-s5pv210.c287
-rw-r--r--drivers/gpio/gpio-samsung.c2686
10 files changed, 2687 insertions, 2350 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 5eb29bc18a56..ca44d2cceb02 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -95,10 +95,6 @@ config GPIO_EP93XX
95 depends on ARCH_EP93XX 95 depends on ARCH_EP93XX
96 select GPIO_GENERIC 96 select GPIO_GENERIC
97 97
98config GPIO_EXYNOS4
99 def_bool y
100 depends on CPU_EXYNOS4210
101
102config GPIO_MPC5200 98config GPIO_MPC5200
103 def_bool y 99 def_bool y
104 depends on PPC_MPC52xx 100 depends on PPC_MPC52xx
@@ -131,30 +127,6 @@ config GPIO_MXS
131 select GPIO_GENERIC 127 select GPIO_GENERIC
132 select GENERIC_IRQ_CHIP 128 select GENERIC_IRQ_CHIP
133 129
134config GPIO_PLAT_SAMSUNG
135 def_bool y
136 depends on SAMSUNG_GPIOLIB_4BIT
137
138config GPIO_S3C24XX
139 def_bool y
140 depends on PLAT_S3C24XX
141
142config GPIO_S3C64XX
143 def_bool y
144 depends on ARCH_S3C64XX
145
146config GPIO_S5P64X0
147 def_bool y
148 depends on ARCH_S5P64X0
149
150config GPIO_S5PC100
151 def_bool y
152 depends on CPU_S5PC100
153
154config GPIO_S5PV210
155 def_bool y
156 depends on CPU_S5PV210
157
158config GPIO_PL061 130config GPIO_PL061
159 bool "PrimeCell PL061 GPIO support" 131 bool "PrimeCell PL061 GPIO support"
160 depends on ARM_AMBA 132 depends on ARM_AMBA
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 10f3bbf0eceb..62db458c850d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
15obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o 15obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
17obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o 17obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
18obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
19obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o 18obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
20obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o 19obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
21obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o 20obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
@@ -38,14 +37,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
38obj-$(CONFIG_GPIO_PCH) += gpio-pch.o 37obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
39obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o 38obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
40obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o 39obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
41 40obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
42obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
43obj-$(CONFIG_GPIO_S3C24XX) += gpio-s3c24xx.o
44obj-$(CONFIG_GPIO_S3C64XX) += gpio-s3c64xx.o
45obj-$(CONFIG_GPIO_S5P64X0) += gpio-s5p64x0.o
46obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
47obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
48
49obj-$(CONFIG_GPIO_SCH) += gpio-sch.o 41obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
50obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o 42obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
51obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o 43obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
deleted file mode 100644
index d24b337cf1ac..000000000000
--- a/drivers/gpio/gpio-exynos4.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/*
2 * EXYNOS4 - GPIOlib support
3 *
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/irq.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16
17#include <mach/map.h>
18
19#include <plat/gpio-core.h>
20#include <plat/gpio-cfg.h>
21#include <plat/gpio-cfg-helpers.h>
22
23int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
24 unsigned int off, s3c_gpio_pull_t pull)
25{
26 if (pull == S3C_GPIO_PULL_UP)
27 pull = 3;
28
29 return s3c_gpio_setpull_updown(chip, off, pull);
30}
31
32s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
33 unsigned int off)
34{
35 s3c_gpio_pull_t pull;
36
37 pull = s3c_gpio_getpull_updown(chip, off);
38 if (pull == 3)
39 pull = S3C_GPIO_PULL_UP;
40
41 return pull;
42}
43
44static struct s3c_gpio_cfg gpio_cfg = {
45 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
46 .set_pull = s3c_gpio_setpull_exynos4,
47 .get_pull = s3c_gpio_getpull_exynos4,
48};
49
50static struct s3c_gpio_cfg gpio_cfg_noint = {
51 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
52 .set_pull = s3c_gpio_setpull_exynos4,
53 .get_pull = s3c_gpio_getpull_exynos4,
54};
55
56/*
57 * Following are the gpio banks in v310.
58 *
59 * The 'config' member when left to NULL, is initialized to the default
60 * structure gpio_cfg in the init function below.
61 *
62 * The 'base' member is also initialized in the init function below.
63 * Note: The initialization of 'base' member of s3c_gpio_chip structure
64 * uses the above macro and depends on the banks being listed in order here.
65 */
66static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
67 {
68 .chip = {
69 .base = EXYNOS4_GPA0(0),
70 .ngpio = EXYNOS4_GPIO_A0_NR,
71 .label = "GPA0",
72 },
73 }, {
74 .chip = {
75 .base = EXYNOS4_GPA1(0),
76 .ngpio = EXYNOS4_GPIO_A1_NR,
77 .label = "GPA1",
78 },
79 }, {
80 .chip = {
81 .base = EXYNOS4_GPB(0),
82 .ngpio = EXYNOS4_GPIO_B_NR,
83 .label = "GPB",
84 },
85 }, {
86 .chip = {
87 .base = EXYNOS4_GPC0(0),
88 .ngpio = EXYNOS4_GPIO_C0_NR,
89 .label = "GPC0",
90 },
91 }, {
92 .chip = {
93 .base = EXYNOS4_GPC1(0),
94 .ngpio = EXYNOS4_GPIO_C1_NR,
95 .label = "GPC1",
96 },
97 }, {
98 .chip = {
99 .base = EXYNOS4_GPD0(0),
100 .ngpio = EXYNOS4_GPIO_D0_NR,
101 .label = "GPD0",
102 },
103 }, {
104 .chip = {
105 .base = EXYNOS4_GPD1(0),
106 .ngpio = EXYNOS4_GPIO_D1_NR,
107 .label = "GPD1",
108 },
109 }, {
110 .chip = {
111 .base = EXYNOS4_GPE0(0),
112 .ngpio = EXYNOS4_GPIO_E0_NR,
113 .label = "GPE0",
114 },
115 }, {
116 .chip = {
117 .base = EXYNOS4_GPE1(0),
118 .ngpio = EXYNOS4_GPIO_E1_NR,
119 .label = "GPE1",
120 },
121 }, {
122 .chip = {
123 .base = EXYNOS4_GPE2(0),
124 .ngpio = EXYNOS4_GPIO_E2_NR,
125 .label = "GPE2",
126 },
127 }, {
128 .chip = {
129 .base = EXYNOS4_GPE3(0),
130 .ngpio = EXYNOS4_GPIO_E3_NR,
131 .label = "GPE3",
132 },
133 }, {
134 .chip = {
135 .base = EXYNOS4_GPE4(0),
136 .ngpio = EXYNOS4_GPIO_E4_NR,
137 .label = "GPE4",
138 },
139 }, {
140 .chip = {
141 .base = EXYNOS4_GPF0(0),
142 .ngpio = EXYNOS4_GPIO_F0_NR,
143 .label = "GPF0",
144 },
145 }, {
146 .chip = {
147 .base = EXYNOS4_GPF1(0),
148 .ngpio = EXYNOS4_GPIO_F1_NR,
149 .label = "GPF1",
150 },
151 }, {
152 .chip = {
153 .base = EXYNOS4_GPF2(0),
154 .ngpio = EXYNOS4_GPIO_F2_NR,
155 .label = "GPF2",
156 },
157 }, {
158 .chip = {
159 .base = EXYNOS4_GPF3(0),
160 .ngpio = EXYNOS4_GPIO_F3_NR,
161 .label = "GPF3",
162 },
163 },
164};
165
166static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
167 {
168 .chip = {
169 .base = EXYNOS4_GPJ0(0),
170 .ngpio = EXYNOS4_GPIO_J0_NR,
171 .label = "GPJ0",
172 },
173 }, {
174 .chip = {
175 .base = EXYNOS4_GPJ1(0),
176 .ngpio = EXYNOS4_GPIO_J1_NR,
177 .label = "GPJ1",
178 },
179 }, {
180 .chip = {
181 .base = EXYNOS4_GPK0(0),
182 .ngpio = EXYNOS4_GPIO_K0_NR,
183 .label = "GPK0",
184 },
185 }, {
186 .chip = {
187 .base = EXYNOS4_GPK1(0),
188 .ngpio = EXYNOS4_GPIO_K1_NR,
189 .label = "GPK1",
190 },
191 }, {
192 .chip = {
193 .base = EXYNOS4_GPK2(0),
194 .ngpio = EXYNOS4_GPIO_K2_NR,
195 .label = "GPK2",
196 },
197 }, {
198 .chip = {
199 .base = EXYNOS4_GPK3(0),
200 .ngpio = EXYNOS4_GPIO_K3_NR,
201 .label = "GPK3",
202 },
203 }, {
204 .chip = {
205 .base = EXYNOS4_GPL0(0),
206 .ngpio = EXYNOS4_GPIO_L0_NR,
207 .label = "GPL0",
208 },
209 }, {
210 .chip = {
211 .base = EXYNOS4_GPL1(0),
212 .ngpio = EXYNOS4_GPIO_L1_NR,
213 .label = "GPL1",
214 },
215 }, {
216 .chip = {
217 .base = EXYNOS4_GPL2(0),
218 .ngpio = EXYNOS4_GPIO_L2_NR,
219 .label = "GPL2",
220 },
221 }, {
222 .config = &gpio_cfg_noint,
223 .chip = {
224 .base = EXYNOS4_GPY0(0),
225 .ngpio = EXYNOS4_GPIO_Y0_NR,
226 .label = "GPY0",
227 },
228 }, {
229 .config = &gpio_cfg_noint,
230 .chip = {
231 .base = EXYNOS4_GPY1(0),
232 .ngpio = EXYNOS4_GPIO_Y1_NR,
233 .label = "GPY1",
234 },
235 }, {
236 .config = &gpio_cfg_noint,
237 .chip = {
238 .base = EXYNOS4_GPY2(0),
239 .ngpio = EXYNOS4_GPIO_Y2_NR,
240 .label = "GPY2",
241 },
242 }, {
243 .config = &gpio_cfg_noint,
244 .chip = {
245 .base = EXYNOS4_GPY3(0),
246 .ngpio = EXYNOS4_GPIO_Y3_NR,
247 .label = "GPY3",
248 },
249 }, {
250 .config = &gpio_cfg_noint,
251 .chip = {
252 .base = EXYNOS4_GPY4(0),
253 .ngpio = EXYNOS4_GPIO_Y4_NR,
254 .label = "GPY4",
255 },
256 }, {
257 .config = &gpio_cfg_noint,
258 .chip = {
259 .base = EXYNOS4_GPY5(0),
260 .ngpio = EXYNOS4_GPIO_Y5_NR,
261 .label = "GPY5",
262 },
263 }, {
264 .config = &gpio_cfg_noint,
265 .chip = {
266 .base = EXYNOS4_GPY6(0),
267 .ngpio = EXYNOS4_GPIO_Y6_NR,
268 .label = "GPY6",
269 },
270 }, {
271 .base = (S5P_VA_GPIO2 + 0xC00),
272 .config = &gpio_cfg_noint,
273 .irq_base = IRQ_EINT(0),
274 .chip = {
275 .base = EXYNOS4_GPX0(0),
276 .ngpio = EXYNOS4_GPIO_X0_NR,
277 .label = "GPX0",
278 .to_irq = samsung_gpiolib_to_irq,
279 },
280 }, {
281 .base = (S5P_VA_GPIO2 + 0xC20),
282 .config = &gpio_cfg_noint,
283 .irq_base = IRQ_EINT(8),
284 .chip = {
285 .base = EXYNOS4_GPX1(0),
286 .ngpio = EXYNOS4_GPIO_X1_NR,
287 .label = "GPX1",
288 .to_irq = samsung_gpiolib_to_irq,
289 },
290 }, {
291 .base = (S5P_VA_GPIO2 + 0xC40),
292 .config = &gpio_cfg_noint,
293 .irq_base = IRQ_EINT(16),
294 .chip = {
295 .base = EXYNOS4_GPX2(0),
296 .ngpio = EXYNOS4_GPIO_X2_NR,
297 .label = "GPX2",
298 .to_irq = samsung_gpiolib_to_irq,
299 },
300 }, {
301 .base = (S5P_VA_GPIO2 + 0xC60),
302 .config = &gpio_cfg_noint,
303 .irq_base = IRQ_EINT(24),
304 .chip = {
305 .base = EXYNOS4_GPX3(0),
306 .ngpio = EXYNOS4_GPIO_X3_NR,
307 .label = "GPX3",
308 .to_irq = samsung_gpiolib_to_irq,
309 },
310 },
311};
312
313static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
314 {
315 .chip = {
316 .base = EXYNOS4_GPZ(0),
317 .ngpio = EXYNOS4_GPIO_Z_NR,
318 .label = "GPZ",
319 },
320 },
321};
322
323static __init int exynos4_gpiolib_init(void)
324{
325 struct s3c_gpio_chip *chip;
326 int i;
327 int group = 0;
328 int nr_chips;
329
330 /* GPIO part 1 */
331
332 chip = exynos4_gpio_part1_4bit;
333 nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
334
335 for (i = 0; i < nr_chips; i++, chip++) {
336 if (chip->config == NULL) {
337 chip->config = &gpio_cfg;
338 /* Assign the GPIO interrupt group */
339 chip->group = group++;
340 }
341 if (chip->base == NULL)
342 chip->base = S5P_VA_GPIO1 + (i) * 0x20;
343 }
344
345 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
346
347 /* GPIO part 2 */
348
349 chip = exynos4_gpio_part2_4bit;
350 nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
351
352 for (i = 0; i < nr_chips; i++, chip++) {
353 if (chip->config == NULL) {
354 chip->config = &gpio_cfg;
355 /* Assign the GPIO interrupt group */
356 chip->group = group++;
357 }
358 if (chip->base == NULL)
359 chip->base = S5P_VA_GPIO2 + (i) * 0x20;
360 }
361
362 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
363
364 /* GPIO part 3 */
365
366 chip = exynos4_gpio_part3_4bit;
367 nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
368
369 for (i = 0; i < nr_chips; i++, chip++) {
370 if (chip->config == NULL) {
371 chip->config = &gpio_cfg;
372 /* Assign the GPIO interrupt group */
373 chip->group = group++;
374 }
375 if (chip->base == NULL)
376 chip->base = S5P_VA_GPIO3 + (i) * 0x20;
377 }
378
379 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
380 s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
381 s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
382
383 return 0;
384}
385core_initcall(exynos4_gpiolib_init);
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
deleted file mode 100644
index ef67f1952a72..000000000000
--- a/drivers/gpio/gpio-plat-samsung.c
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * Copyright 2008 Openmoko, Inc.
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
8 * http://www.samsung.com/
9 *
10 * SAMSUNG - GPIOlib support
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/kernel.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <plat/gpio-core.h>
22#include <plat/gpio-cfg.h>
23#include <plat/gpio-cfg-helpers.h>
24
25#ifndef DEBUG_GPIO
26#define gpio_dbg(x...) do { } while (0)
27#else
28#define gpio_dbg(x...) printk(KERN_DEBUG x)
29#endif
30
31/* The samsung_gpiolib_4bit routines are to control the gpio banks where
32 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
33 * following example:
34 *
35 * base + 0x00: Control register, 4 bits per gpio
36 * gpio n: 4 bits starting at (4*n)
37 * 0000 = input, 0001 = output, others mean special-function
38 * base + 0x04: Data register, 1 bit per gpio
39 * bit n: data bit n
40 *
41 * Note, since the data register is one bit per gpio and is at base + 0x4
42 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
43 * the output.
44*/
45
46static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
47 unsigned int offset)
48{
49 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
50 void __iomem *base = ourchip->base;
51 unsigned long con;
52
53 con = __raw_readl(base + GPIOCON_OFF);
54 con &= ~(0xf << con_4bit_shift(offset));
55 __raw_writel(con, base + GPIOCON_OFF);
56
57 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
58
59 return 0;
60}
61
62static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
63 unsigned int offset, int value)
64{
65 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
66 void __iomem *base = ourchip->base;
67 unsigned long con;
68 unsigned long dat;
69
70 con = __raw_readl(base + GPIOCON_OFF);
71 con &= ~(0xf << con_4bit_shift(offset));
72 con |= 0x1 << con_4bit_shift(offset);
73
74 dat = __raw_readl(base + GPIODAT_OFF);
75
76 if (value)
77 dat |= 1 << offset;
78 else
79 dat &= ~(1 << offset);
80
81 __raw_writel(dat, base + GPIODAT_OFF);
82 __raw_writel(con, base + GPIOCON_OFF);
83 __raw_writel(dat, base + GPIODAT_OFF);
84
85 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
86
87 return 0;
88}
89
90/* The next set of routines are for the case where the GPIO configuration
91 * registers are 4 bits per GPIO but there is more than one register (the
92 * bank has more than 8 GPIOs.
93 *
94 * This case is the similar to the 4 bit case, but the registers are as
95 * follows:
96 *
97 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
98 * gpio n: 4 bits starting at (4*n)
99 * 0000 = input, 0001 = output, others mean special-function
100 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
101 * gpio n: 4 bits starting at (4*n)
102 * 0000 = input, 0001 = output, others mean special-function
103 * base + 0x08: Data register, 1 bit per gpio
104 * bit n: data bit n
105 *
106 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
107 * store the 'base + 0x4' address so that these routines see the data
108 * register at ourchip->base + 0x04.
109 */
110
111static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
112 unsigned int offset)
113{
114 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
115 void __iomem *base = ourchip->base;
116 void __iomem *regcon = base;
117 unsigned long con;
118
119 if (offset > 7)
120 offset -= 8;
121 else
122 regcon -= 4;
123
124 con = __raw_readl(regcon);
125 con &= ~(0xf << con_4bit_shift(offset));
126 __raw_writel(con, regcon);
127
128 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
129
130 return 0;
131}
132
133static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
134 unsigned int offset, int value)
135{
136 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
137 void __iomem *base = ourchip->base;
138 void __iomem *regcon = base;
139 unsigned long con;
140 unsigned long dat;
141 unsigned con_offset = offset;
142
143 if (con_offset > 7)
144 con_offset -= 8;
145 else
146 regcon -= 4;
147
148 con = __raw_readl(regcon);
149 con &= ~(0xf << con_4bit_shift(con_offset));
150 con |= 0x1 << con_4bit_shift(con_offset);
151
152 dat = __raw_readl(base + GPIODAT_OFF);
153
154 if (value)
155 dat |= 1 << offset;
156 else
157 dat &= ~(1 << offset);
158
159 __raw_writel(dat, base + GPIODAT_OFF);
160 __raw_writel(con, regcon);
161 __raw_writel(dat, base + GPIODAT_OFF);
162
163 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
164
165 return 0;
166}
167
168void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
169{
170 chip->chip.direction_input = samsung_gpiolib_4bit_input;
171 chip->chip.direction_output = samsung_gpiolib_4bit_output;
172 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
173}
174
175void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
176{
177 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
178 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
179 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
180}
181
182void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
183 int nr_chips)
184{
185 for (; nr_chips > 0; nr_chips--, chip++) {
186 samsung_gpiolib_add_4bit(chip);
187 s3c_gpiolib_add(chip);
188 }
189}
190
191void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
192 int nr_chips)
193{
194 for (; nr_chips > 0; nr_chips--, chip++) {
195 samsung_gpiolib_add_4bit2(chip);
196 s3c_gpiolib_add(chip);
197 }
198}
199
200void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
201 int nr_chips)
202{
203 for (; nr_chips > 0; nr_chips--, chip++)
204 s3c_gpiolib_add(chip);
205}
diff --git a/drivers/gpio/gpio-s3c24xx.c b/drivers/gpio/gpio-s3c24xx.c
deleted file mode 100644
index ff6103130fe8..000000000000
--- a/drivers/gpio/gpio-s3c24xx.c
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 * Copyright (c) 2008-2010 Simtec Electronics
3 * http://armlinux.simtec.co.uk/
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C24XX GPIOlib support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License.
11*/
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/interrupt.h>
17#include <linux/sysdev.h>
18#include <linux/ioport.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <asm/irq.h>
22
23#include <mach/hardware.h>
24#include <mach/gpio-fns.h>
25#include <mach/regs-gpio.h>
26
27#include <plat/gpio-core.h>
28#include <plat/gpio-cfg.h>
29#include <plat/gpio-cfg-helpers.h>
30#include <plat/pm.h>
31
32static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
33{
34 return -EINVAL;
35}
36
37static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
38 unsigned offset, int value)
39{
40 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
41 void __iomem *base = ourchip->base;
42 unsigned long flags;
43 unsigned long dat;
44 unsigned long con;
45
46 local_irq_save(flags);
47
48 con = __raw_readl(base + 0x00);
49 dat = __raw_readl(base + 0x04);
50
51 dat &= ~(1 << offset);
52 if (value)
53 dat |= 1 << offset;
54
55 __raw_writel(dat, base + 0x04);
56
57 con &= ~(1 << offset);
58
59 __raw_writel(con, base + 0x00);
60 __raw_writel(dat, base + 0x04);
61
62 local_irq_restore(flags);
63 return 0;
64}
65
66static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
67{
68 if (offset < 4)
69 return IRQ_EINT0 + offset;
70
71 if (offset < 8)
72 return IRQ_EINT4 + offset - 4;
73
74 return -EINVAL;
75}
76
77static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
78 .set_config = s3c_gpio_setcfg_s3c24xx_a,
79 .get_config = s3c_gpio_getcfg_s3c24xx_a,
80};
81
82struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
83 .set_config = s3c_gpio_setcfg_s3c24xx,
84 .get_config = s3c_gpio_getcfg_s3c24xx,
85};
86
87struct s3c_gpio_chip s3c24xx_gpios[] = {
88 [0] = {
89 .base = S3C2410_GPACON,
90 .pm = __gpio_pm(&s3c_gpio_pm_1bit),
91 .config = &s3c24xx_gpiocfg_banka,
92 .chip = {
93 .base = S3C2410_GPA(0),
94 .owner = THIS_MODULE,
95 .label = "GPIOA",
96 .ngpio = 24,
97 .direction_input = s3c24xx_gpiolib_banka_input,
98 .direction_output = s3c24xx_gpiolib_banka_output,
99 },
100 },
101 [1] = {
102 .base = S3C2410_GPBCON,
103 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
104 .chip = {
105 .base = S3C2410_GPB(0),
106 .owner = THIS_MODULE,
107 .label = "GPIOB",
108 .ngpio = 16,
109 },
110 },
111 [2] = {
112 .base = S3C2410_GPCCON,
113 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
114 .chip = {
115 .base = S3C2410_GPC(0),
116 .owner = THIS_MODULE,
117 .label = "GPIOC",
118 .ngpio = 16,
119 },
120 },
121 [3] = {
122 .base = S3C2410_GPDCON,
123 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
124 .chip = {
125 .base = S3C2410_GPD(0),
126 .owner = THIS_MODULE,
127 .label = "GPIOD",
128 .ngpio = 16,
129 },
130 },
131 [4] = {
132 .base = S3C2410_GPECON,
133 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
134 .chip = {
135 .base = S3C2410_GPE(0),
136 .label = "GPIOE",
137 .owner = THIS_MODULE,
138 .ngpio = 16,
139 },
140 },
141 [5] = {
142 .base = S3C2410_GPFCON,
143 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
144 .chip = {
145 .base = S3C2410_GPF(0),
146 .owner = THIS_MODULE,
147 .label = "GPIOF",
148 .ngpio = 8,
149 .to_irq = s3c24xx_gpiolib_bankf_toirq,
150 },
151 },
152 [6] = {
153 .base = S3C2410_GPGCON,
154 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
155 .irq_base = IRQ_EINT8,
156 .chip = {
157 .base = S3C2410_GPG(0),
158 .owner = THIS_MODULE,
159 .label = "GPIOG",
160 .ngpio = 16,
161 .to_irq = samsung_gpiolib_to_irq,
162 },
163 }, {
164 .base = S3C2410_GPHCON,
165 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
166 .chip = {
167 .base = S3C2410_GPH(0),
168 .owner = THIS_MODULE,
169 .label = "GPIOH",
170 .ngpio = 11,
171 },
172 },
173 /* GPIOS for the S3C2443 and later devices. */
174 {
175 .base = S3C2440_GPJCON,
176 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
177 .chip = {
178 .base = S3C2410_GPJ(0),
179 .owner = THIS_MODULE,
180 .label = "GPIOJ",
181 .ngpio = 16,
182 },
183 }, {
184 .base = S3C2443_GPKCON,
185 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
186 .chip = {
187 .base = S3C2410_GPK(0),
188 .owner = THIS_MODULE,
189 .label = "GPIOK",
190 .ngpio = 16,
191 },
192 }, {
193 .base = S3C2443_GPLCON,
194 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
195 .chip = {
196 .base = S3C2410_GPL(0),
197 .owner = THIS_MODULE,
198 .label = "GPIOL",
199 .ngpio = 15,
200 },
201 }, {
202 .base = S3C2443_GPMCON,
203 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
204 .chip = {
205 .base = S3C2410_GPM(0),
206 .owner = THIS_MODULE,
207 .label = "GPIOM",
208 .ngpio = 2,
209 },
210 },
211};
212
213static __init int s3c24xx_gpiolib_init(void)
214{
215 struct s3c_gpio_chip *chip = s3c24xx_gpios;
216 int gpn;
217
218 for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
219 if (!chip->config)
220 chip->config = &s3c24xx_gpiocfg_default;
221
222 s3c_gpiolib_add(chip);
223 }
224
225 return 0;
226}
227core_initcall(s3c24xx_gpiolib_init);
228
229/* gpiolib wrappers until these are totally eliminated */
230
231void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
232{
233 int ret;
234
235 WARN_ON(to); /* should be none of these left */
236
237 if (!to) {
238 /* if pull is enabled, try first with up, and if that
239 * fails, try using down */
240
241 ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
242 if (ret)
243 s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
244 } else {
245 s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
246 }
247}
248EXPORT_SYMBOL(s3c2410_gpio_pullup);
249
250void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
251{
252 /* do this via gpiolib until all users removed */
253
254 gpio_request(pin, "temporary");
255 gpio_set_value(pin, to);
256 gpio_free(pin);
257}
258EXPORT_SYMBOL(s3c2410_gpio_setpin);
259
260unsigned int s3c2410_gpio_getpin(unsigned int pin)
261{
262 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
263 unsigned long offs = pin - chip->chip.base;
264
265 return __raw_readl(chip->base + 0x04) & (1<< offs);
266}
267EXPORT_SYMBOL(s3c2410_gpio_getpin);
268
269unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
270{
271 unsigned long flags;
272 unsigned long misccr;
273
274 local_irq_save(flags);
275 misccr = __raw_readl(S3C24XX_MISCCR);
276 misccr &= ~clear;
277 misccr ^= change;
278 __raw_writel(misccr, S3C24XX_MISCCR);
279 local_irq_restore(flags);
280
281 return misccr;
282}
283EXPORT_SYMBOL(s3c2410_modify_misccr);
diff --git a/drivers/gpio/gpio-s3c64xx.c b/drivers/gpio/gpio-s3c64xx.c
deleted file mode 100644
index b4f1c8204f03..000000000000
--- a/drivers/gpio/gpio-s3c64xx.c
+++ /dev/null
@@ -1,289 +0,0 @@
1/*
2 * Copyright 2008 Openmoko, Inc.
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C64XX - GPIOlib support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <mach/map.h>
20
21#include <plat/gpio-core.h>
22#include <plat/gpio-cfg.h>
23#include <plat/gpio-cfg-helpers.h>
24#include <mach/regs-gpio.h>
25
26/* GPIO bank summary:
27 *
28 * Bank GPIOs Style SlpCon ExtInt Group
29 * A 8 4Bit Yes 1
30 * B 7 4Bit Yes 1
31 * C 8 4Bit Yes 2
32 * D 5 4Bit Yes 3
33 * E 5 4Bit Yes None
34 * F 16 2Bit Yes 4 [1]
35 * G 7 4Bit Yes 5
36 * H 10 4Bit[2] Yes 6
37 * I 16 2Bit Yes None
38 * J 12 2Bit Yes None
39 * K 16 4Bit[2] No None
40 * L 15 4Bit[2] No None
41 * M 6 4Bit No IRQ_EINT
42 * N 16 2Bit No IRQ_EINT
43 * O 16 2Bit Yes 7
44 * P 15 2Bit Yes 8
45 * Q 9 2Bit Yes 9
46 *
47 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
48 * [2] BANK has two control registers, GPxCON0 and GPxCON1
49 */
50
51static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
52 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
53 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
54 .set_pull = s3c_gpio_setpull_updown,
55 .get_pull = s3c_gpio_getpull_updown,
56};
57
58static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
59 .cfg_eint = 7,
60 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
61 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
62 .set_pull = s3c_gpio_setpull_updown,
63 .get_pull = s3c_gpio_getpull_updown,
64};
65
66static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
67 .cfg_eint = 3,
68 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
69 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
70 .set_pull = s3c_gpio_setpull_updown,
71 .get_pull = s3c_gpio_getpull_updown,
72};
73
74static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
75{
76 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
77}
78
79static struct s3c_gpio_chip gpio_4bit[] = {
80 {
81 .base = S3C64XX_GPA_BASE,
82 .config = &gpio_4bit_cfg_eint0111,
83 .chip = {
84 .base = S3C64XX_GPA(0),
85 .ngpio = S3C64XX_GPIO_A_NR,
86 .label = "GPA",
87 },
88 }, {
89 .base = S3C64XX_GPB_BASE,
90 .config = &gpio_4bit_cfg_eint0111,
91 .chip = {
92 .base = S3C64XX_GPB(0),
93 .ngpio = S3C64XX_GPIO_B_NR,
94 .label = "GPB",
95 },
96 }, {
97 .base = S3C64XX_GPC_BASE,
98 .config = &gpio_4bit_cfg_eint0111,
99 .chip = {
100 .base = S3C64XX_GPC(0),
101 .ngpio = S3C64XX_GPIO_C_NR,
102 .label = "GPC",
103 },
104 }, {
105 .base = S3C64XX_GPD_BASE,
106 .config = &gpio_4bit_cfg_eint0111,
107 .chip = {
108 .base = S3C64XX_GPD(0),
109 .ngpio = S3C64XX_GPIO_D_NR,
110 .label = "GPD",
111 },
112 }, {
113 .base = S3C64XX_GPE_BASE,
114 .config = &gpio_4bit_cfg_noint,
115 .chip = {
116 .base = S3C64XX_GPE(0),
117 .ngpio = S3C64XX_GPIO_E_NR,
118 .label = "GPE",
119 },
120 }, {
121 .base = S3C64XX_GPG_BASE,
122 .config = &gpio_4bit_cfg_eint0111,
123 .chip = {
124 .base = S3C64XX_GPG(0),
125 .ngpio = S3C64XX_GPIO_G_NR,
126 .label = "GPG",
127 },
128 }, {
129 .base = S3C64XX_GPM_BASE,
130 .config = &gpio_4bit_cfg_eint0011,
131 .chip = {
132 .base = S3C64XX_GPM(0),
133 .ngpio = S3C64XX_GPIO_M_NR,
134 .label = "GPM",
135 .to_irq = s3c64xx_gpio2int_gpm,
136 },
137 },
138};
139
140static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
141{
142 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
143}
144
145static struct s3c_gpio_chip gpio_4bit2[] = {
146 {
147 .base = S3C64XX_GPH_BASE + 0x4,
148 .config = &gpio_4bit_cfg_eint0111,
149 .chip = {
150 .base = S3C64XX_GPH(0),
151 .ngpio = S3C64XX_GPIO_H_NR,
152 .label = "GPH",
153 },
154 }, {
155 .base = S3C64XX_GPK_BASE + 0x4,
156 .config = &gpio_4bit_cfg_noint,
157 .chip = {
158 .base = S3C64XX_GPK(0),
159 .ngpio = S3C64XX_GPIO_K_NR,
160 .label = "GPK",
161 },
162 }, {
163 .base = S3C64XX_GPL_BASE + 0x4,
164 .config = &gpio_4bit_cfg_eint0011,
165 .chip = {
166 .base = S3C64XX_GPL(0),
167 .ngpio = S3C64XX_GPIO_L_NR,
168 .label = "GPL",
169 .to_irq = s3c64xx_gpio2int_gpl,
170 },
171 },
172};
173
174static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
175 .set_config = s3c_gpio_setcfg_s3c24xx,
176 .get_config = s3c_gpio_getcfg_s3c24xx,
177 .set_pull = s3c_gpio_setpull_updown,
178 .get_pull = s3c_gpio_getpull_updown,
179};
180
181static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
182 .cfg_eint = 2,
183 .set_config = s3c_gpio_setcfg_s3c24xx,
184 .get_config = s3c_gpio_getcfg_s3c24xx,
185 .set_pull = s3c_gpio_setpull_updown,
186 .get_pull = s3c_gpio_getpull_updown,
187};
188
189static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
190 .cfg_eint = 3,
191 .set_config = s3c_gpio_setcfg_s3c24xx,
192 .get_config = s3c_gpio_getcfg_s3c24xx,
193 .set_pull = s3c_gpio_setpull_updown,
194 .get_pull = s3c_gpio_getpull_updown,
195};
196
197static 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 .irq_base = IRQ_EINT(0),
225 .config = &gpio_2bit_cfg_eint10,
226 .chip = {
227 .base = S3C64XX_GPN(0),
228 .ngpio = S3C64XX_GPIO_N_NR,
229 .label = "GPN",
230 .to_irq = samsung_gpiolib_to_irq,
231 },
232 }, {
233 .base = S3C64XX_GPO_BASE,
234 .config = &gpio_2bit_cfg_eint11,
235 .chip = {
236 .base = S3C64XX_GPO(0),
237 .ngpio = S3C64XX_GPIO_O_NR,
238 .label = "GPO",
239 },
240 }, {
241 .base = S3C64XX_GPP_BASE,
242 .config = &gpio_2bit_cfg_eint11,
243 .chip = {
244 .base = S3C64XX_GPP(0),
245 .ngpio = S3C64XX_GPIO_P_NR,
246 .label = "GPP",
247 },
248 }, {
249 .base = S3C64XX_GPQ_BASE,
250 .config = &gpio_2bit_cfg_eint11,
251 .chip = {
252 .base = S3C64XX_GPQ(0),
253 .ngpio = S3C64XX_GPIO_Q_NR,
254 .label = "GPQ",
255 },
256 },
257};
258
259static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
260{
261 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
262}
263
264static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
265 int nr_chips,
266 void (*fn)(struct s3c_gpio_chip *))
267{
268 for (; nr_chips > 0; nr_chips--, chips++) {
269 if (fn)
270 (fn)(chips);
271 s3c_gpiolib_add(chips);
272 }
273}
274
275static __init int s3c64xx_gpiolib_init(void)
276{
277 s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
278 samsung_gpiolib_add_4bit);
279
280 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
281 samsung_gpiolib_add_4bit2);
282
283 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
284 s3c64xx_gpiolib_add_2bit);
285
286 return 0;
287}
288
289core_initcall(s3c64xx_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5p64x0.c b/drivers/gpio/gpio-s5p64x0.c
deleted file mode 100644
index 96e816f5cc95..000000000000
--- a/drivers/gpio/gpio-s5p64x0.c
+++ /dev/null
@@ -1,510 +0,0 @@
1/*
2 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * S5P64X0 - GPIOlib support
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/irq.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16
17#include <mach/map.h>
18#include <mach/regs-gpio.h>
19#include <mach/regs-clock.h>
20
21#include <plat/gpio-core.h>
22#include <plat/gpio-cfg.h>
23#include <plat/gpio-cfg-helpers.h>
24
25/*
26 * S5P6440 GPIO bank summary:
27 *
28 * Bank GPIOs Style SlpCon ExtInt Group
29 * A 6 4Bit Yes 1
30 * B 7 4Bit Yes 1
31 * C 8 4Bit Yes 2
32 * F 2 2Bit Yes 4 [1]
33 * G 7 4Bit Yes 5
34 * H 10 4Bit[2] Yes 6
35 * I 16 2Bit Yes None
36 * J 12 2Bit Yes None
37 * N 16 2Bit No IRQ_EINT
38 * P 8 2Bit Yes 8
39 * R 15 4Bit[2] Yes 8
40 *
41 * S5P6450 GPIO bank summary:
42 *
43 * Bank GPIOs Style SlpCon ExtInt Group
44 * A 6 4Bit Yes 1
45 * B 7 4Bit Yes 1
46 * C 8 4Bit Yes 2
47 * D 8 4Bit Yes None
48 * F 2 2Bit Yes None
49 * G 14 4Bit[2] Yes 5
50 * H 10 4Bit[2] Yes 6
51 * I 16 2Bit Yes None
52 * J 12 2Bit Yes None
53 * K 5 4Bit Yes None
54 * N 16 2Bit No IRQ_EINT
55 * P 11 2Bit Yes 8
56 * Q 14 2Bit Yes None
57 * R 15 4Bit[2] Yes None
58 * S 8 2Bit Yes None
59 *
60 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
61 * [2] BANK has two control registers, GPxCON0 and GPxCON1
62 */
63
64static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
65 unsigned int offset)
66{
67 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
68 void __iomem *base = ourchip->base;
69 void __iomem *regcon = base;
70 unsigned long con;
71 unsigned long flags;
72
73 switch (offset) {
74 case 6:
75 offset += 1;
76 case 0:
77 case 1:
78 case 2:
79 case 3:
80 case 4:
81 case 5:
82 regcon -= 4;
83 break;
84 default:
85 offset -= 7;
86 break;
87 }
88
89 s3c_gpio_lock(ourchip, flags);
90
91 con = __raw_readl(regcon);
92 con &= ~(0xf << con_4bit_shift(offset));
93 __raw_writel(con, regcon);
94
95 s3c_gpio_unlock(ourchip, flags);
96
97 return 0;
98}
99
100static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
101 unsigned int offset, int value)
102{
103 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
104 void __iomem *base = ourchip->base;
105 void __iomem *regcon = base;
106 unsigned long con;
107 unsigned long dat;
108 unsigned long flags;
109 unsigned con_offset = offset;
110
111 switch (con_offset) {
112 case 6:
113 con_offset += 1;
114 case 0:
115 case 1:
116 case 2:
117 case 3:
118 case 4:
119 case 5:
120 regcon -= 4;
121 break;
122 default:
123 con_offset -= 7;
124 break;
125 }
126
127 s3c_gpio_lock(ourchip, flags);
128
129 con = __raw_readl(regcon);
130 con &= ~(0xf << con_4bit_shift(con_offset));
131 con |= 0x1 << con_4bit_shift(con_offset);
132
133 dat = __raw_readl(base + GPIODAT_OFF);
134 if (value)
135 dat |= 1 << offset;
136 else
137 dat &= ~(1 << offset);
138
139 __raw_writel(con, regcon);
140 __raw_writel(dat, base + GPIODAT_OFF);
141
142 s3c_gpio_unlock(ourchip, flags);
143
144 return 0;
145}
146
147int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
148 unsigned int off, unsigned int cfg)
149{
150 void __iomem *reg = chip->base;
151 unsigned int shift;
152 u32 con;
153
154 switch (off) {
155 case 0:
156 case 1:
157 case 2:
158 case 3:
159 case 4:
160 case 5:
161 shift = (off & 7) * 4;
162 reg -= 4;
163 break;
164 case 6:
165 shift = ((off + 1) & 7) * 4;
166 reg -= 4;
167 default:
168 shift = ((off + 1) & 7) * 4;
169 break;
170 }
171
172 if (s3c_gpio_is_cfg_special(cfg)) {
173 cfg &= 0xf;
174 cfg <<= shift;
175 }
176
177 con = __raw_readl(reg);
178 con &= ~(0xf << shift);
179 con |= cfg;
180 __raw_writel(con, reg);
181
182 return 0;
183}
184
185static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
186 {
187 .cfg_eint = 0,
188 }, {
189 .cfg_eint = 7,
190 }, {
191 .cfg_eint = 3,
192 .set_config = s5p64x0_gpio_setcfg_4bit_rbank,
193 }, {
194 .cfg_eint = 0,
195 .set_config = s3c_gpio_setcfg_s3c24xx,
196 .get_config = s3c_gpio_getcfg_s3c24xx,
197 }, {
198 .cfg_eint = 2,
199 .set_config = s3c_gpio_setcfg_s3c24xx,
200 .get_config = s3c_gpio_getcfg_s3c24xx,
201 }, {
202 .cfg_eint = 3,
203 .set_config = s3c_gpio_setcfg_s3c24xx,
204 .get_config = s3c_gpio_getcfg_s3c24xx,
205 },
206};
207
208static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
209 {
210 .base = S5P64X0_GPA_BASE,
211 .config = &s5p64x0_gpio_cfgs[1],
212 .chip = {
213 .base = S5P6440_GPA(0),
214 .ngpio = S5P6440_GPIO_A_NR,
215 .label = "GPA",
216 },
217 }, {
218 .base = S5P64X0_GPB_BASE,
219 .config = &s5p64x0_gpio_cfgs[1],
220 .chip = {
221 .base = S5P6440_GPB(0),
222 .ngpio = S5P6440_GPIO_B_NR,
223 .label = "GPB",
224 },
225 }, {
226 .base = S5P64X0_GPC_BASE,
227 .config = &s5p64x0_gpio_cfgs[1],
228 .chip = {
229 .base = S5P6440_GPC(0),
230 .ngpio = S5P6440_GPIO_C_NR,
231 .label = "GPC",
232 },
233 }, {
234 .base = S5P64X0_GPG_BASE,
235 .config = &s5p64x0_gpio_cfgs[1],
236 .chip = {
237 .base = S5P6440_GPG(0),
238 .ngpio = S5P6440_GPIO_G_NR,
239 .label = "GPG",
240 },
241 },
242};
243
244static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
245 {
246 .base = S5P64X0_GPH_BASE + 0x4,
247 .config = &s5p64x0_gpio_cfgs[1],
248 .chip = {
249 .base = S5P6440_GPH(0),
250 .ngpio = S5P6440_GPIO_H_NR,
251 .label = "GPH",
252 },
253 },
254};
255
256static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
257 {
258 .base = S5P64X0_GPR_BASE + 0x4,
259 .config = &s5p64x0_gpio_cfgs[2],
260 .chip = {
261 .base = S5P6440_GPR(0),
262 .ngpio = S5P6440_GPIO_R_NR,
263 .label = "GPR",
264 },
265 },
266};
267
268static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
269 {
270 .base = S5P64X0_GPF_BASE,
271 .config = &s5p64x0_gpio_cfgs[5],
272 .chip = {
273 .base = S5P6440_GPF(0),
274 .ngpio = S5P6440_GPIO_F_NR,
275 .label = "GPF",
276 },
277 }, {
278 .base = S5P64X0_GPI_BASE,
279 .config = &s5p64x0_gpio_cfgs[3],
280 .chip = {
281 .base = S5P6440_GPI(0),
282 .ngpio = S5P6440_GPIO_I_NR,
283 .label = "GPI",
284 },
285 }, {
286 .base = S5P64X0_GPJ_BASE,
287 .config = &s5p64x0_gpio_cfgs[3],
288 .chip = {
289 .base = S5P6440_GPJ(0),
290 .ngpio = S5P6440_GPIO_J_NR,
291 .label = "GPJ",
292 },
293 }, {
294 .base = S5P64X0_GPN_BASE,
295 .config = &s5p64x0_gpio_cfgs[4],
296 .chip = {
297 .base = S5P6440_GPN(0),
298 .ngpio = S5P6440_GPIO_N_NR,
299 .label = "GPN",
300 },
301 }, {
302 .base = S5P64X0_GPP_BASE,
303 .config = &s5p64x0_gpio_cfgs[5],
304 .chip = {
305 .base = S5P6440_GPP(0),
306 .ngpio = S5P6440_GPIO_P_NR,
307 .label = "GPP",
308 },
309 },
310};
311
312static struct s3c_gpio_chip s5p6450_gpio_4bit[] = {
313 {
314 .base = S5P64X0_GPA_BASE,
315 .config = &s5p64x0_gpio_cfgs[1],
316 .chip = {
317 .base = S5P6450_GPA(0),
318 .ngpio = S5P6450_GPIO_A_NR,
319 .label = "GPA",
320 },
321 }, {
322 .base = S5P64X0_GPB_BASE,
323 .config = &s5p64x0_gpio_cfgs[1],
324 .chip = {
325 .base = S5P6450_GPB(0),
326 .ngpio = S5P6450_GPIO_B_NR,
327 .label = "GPB",
328 },
329 }, {
330 .base = S5P64X0_GPC_BASE,
331 .config = &s5p64x0_gpio_cfgs[1],
332 .chip = {
333 .base = S5P6450_GPC(0),
334 .ngpio = S5P6450_GPIO_C_NR,
335 .label = "GPC",
336 },
337 }, {
338 .base = S5P6450_GPD_BASE,
339 .config = &s5p64x0_gpio_cfgs[1],
340 .chip = {
341 .base = S5P6450_GPD(0),
342 .ngpio = S5P6450_GPIO_D_NR,
343 .label = "GPD",
344 },
345 }, {
346 .base = S5P6450_GPK_BASE,
347 .config = &s5p64x0_gpio_cfgs[1],
348 .chip = {
349 .base = S5P6450_GPK(0),
350 .ngpio = S5P6450_GPIO_K_NR,
351 .label = "GPK",
352 },
353 },
354};
355
356static struct s3c_gpio_chip s5p6450_gpio_4bit2[] = {
357 {
358 .base = S5P64X0_GPG_BASE + 0x4,
359 .config = &s5p64x0_gpio_cfgs[1],
360 .chip = {
361 .base = S5P6450_GPG(0),
362 .ngpio = S5P6450_GPIO_G_NR,
363 .label = "GPG",
364 },
365 }, {
366 .base = S5P64X0_GPH_BASE + 0x4,
367 .config = &s5p64x0_gpio_cfgs[1],
368 .chip = {
369 .base = S5P6450_GPH(0),
370 .ngpio = S5P6450_GPIO_H_NR,
371 .label = "GPH",
372 },
373 },
374};
375
376static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2[] = {
377 {
378 .base = S5P64X0_GPR_BASE + 0x4,
379 .config = &s5p64x0_gpio_cfgs[2],
380 .chip = {
381 .base = S5P6450_GPR(0),
382 .ngpio = S5P6450_GPIO_R_NR,
383 .label = "GPR",
384 },
385 },
386};
387
388static struct s3c_gpio_chip s5p6450_gpio_2bit[] = {
389 {
390 .base = S5P64X0_GPF_BASE,
391 .config = &s5p64x0_gpio_cfgs[5],
392 .chip = {
393 .base = S5P6450_GPF(0),
394 .ngpio = S5P6450_GPIO_F_NR,
395 .label = "GPF",
396 },
397 }, {
398 .base = S5P64X0_GPI_BASE,
399 .config = &s5p64x0_gpio_cfgs[3],
400 .chip = {
401 .base = S5P6450_GPI(0),
402 .ngpio = S5P6450_GPIO_I_NR,
403 .label = "GPI",
404 },
405 }, {
406 .base = S5P64X0_GPJ_BASE,
407 .config = &s5p64x0_gpio_cfgs[3],
408 .chip = {
409 .base = S5P6450_GPJ(0),
410 .ngpio = S5P6450_GPIO_J_NR,
411 .label = "GPJ",
412 },
413 }, {
414 .base = S5P64X0_GPN_BASE,
415 .config = &s5p64x0_gpio_cfgs[4],
416 .chip = {
417 .base = S5P6450_GPN(0),
418 .ngpio = S5P6450_GPIO_N_NR,
419 .label = "GPN",
420 },
421 }, {
422 .base = S5P64X0_GPP_BASE,
423 .config = &s5p64x0_gpio_cfgs[5],
424 .chip = {
425 .base = S5P6450_GPP(0),
426 .ngpio = S5P6450_GPIO_P_NR,
427 .label = "GPP",
428 },
429 }, {
430 .base = S5P6450_GPQ_BASE,
431 .config = &s5p64x0_gpio_cfgs[4],
432 .chip = {
433 .base = S5P6450_GPQ(0),
434 .ngpio = S5P6450_GPIO_Q_NR,
435 .label = "GPQ",
436 },
437 }, {
438 .base = S5P6450_GPS_BASE,
439 .config = &s5p64x0_gpio_cfgs[5],
440 .chip = {
441 .base = S5P6450_GPS(0),
442 .ngpio = S5P6450_GPIO_S_NR,
443 .label = "GPS",
444 },
445 },
446};
447
448void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
449{
450 for (; nr_chips > 0; nr_chips--, chipcfg++) {
451 if (!chipcfg->set_config)
452 chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit;
453 if (!chipcfg->get_config)
454 chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit;
455 if (!chipcfg->set_pull)
456 chipcfg->set_pull = s3c_gpio_setpull_updown;
457 if (!chipcfg->get_pull)
458 chipcfg->get_pull = s3c_gpio_getpull_updown;
459 }
460}
461
462static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
463 int nr_chips)
464{
465 for (; nr_chips > 0; nr_chips--, chip++) {
466 chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
467 chip->chip.direction_output =
468 s5p64x0_gpiolib_rbank_4bit2_output;
469 s3c_gpiolib_add(chip);
470 }
471}
472
473static int __init s5p64x0_gpiolib_init(void)
474{
475 unsigned int chipid;
476
477 chipid = __raw_readl(S5P64X0_SYS_ID);
478
479 s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
480 ARRAY_SIZE(s5p64x0_gpio_cfgs));
481
482 if ((chipid & 0xff000) == 0x50000) {
483 samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
484 ARRAY_SIZE(s5p6450_gpio_2bit));
485
486 samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit,
487 ARRAY_SIZE(s5p6450_gpio_4bit));
488
489 samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2,
490 ARRAY_SIZE(s5p6450_gpio_4bit2));
491
492 s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2,
493 ARRAY_SIZE(s5p6450_gpio_rbank_4bit2));
494 } else {
495 samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit,
496 ARRAY_SIZE(s5p6440_gpio_2bit));
497
498 samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
499 ARRAY_SIZE(s5p6440_gpio_4bit));
500
501 samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
502 ARRAY_SIZE(s5p6440_gpio_4bit2));
503
504 s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
505 ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
506 }
507
508 return 0;
509}
510core_initcall(s5p64x0_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
deleted file mode 100644
index 7f87b0c76e0b..000000000000
--- a/drivers/gpio/gpio-s5pc100.c
+++ /dev/null
@@ -1,354 +0,0 @@
1/*
2 * S5PC100 - GPIOlib support
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * Copyright 2009 Samsung Electronics Co
8 * Kyungmin Park <kyungmin.park@samsung.com>
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#include <linux/gpio.h>
19
20#include <mach/map.h>
21#include <mach/regs-gpio.h>
22
23#include <plat/gpio-core.h>
24#include <plat/gpio-cfg.h>
25#include <plat/gpio-cfg-helpers.h>
26
27/* S5PC100 GPIO bank summary:
28 *
29 * Bank GPIOs Style INT Type
30 * A0 8 4Bit GPIO_INT0
31 * A1 5 4Bit GPIO_INT1
32 * B 8 4Bit GPIO_INT2
33 * C 5 4Bit GPIO_INT3
34 * D 7 4Bit GPIO_INT4
35 * E0 8 4Bit GPIO_INT5
36 * E1 6 4Bit GPIO_INT6
37 * F0 8 4Bit GPIO_INT7
38 * F1 8 4Bit GPIO_INT8
39 * F2 8 4Bit GPIO_INT9
40 * F3 4 4Bit GPIO_INT10
41 * G0 8 4Bit GPIO_INT11
42 * G1 3 4Bit GPIO_INT12
43 * G2 7 4Bit GPIO_INT13
44 * G3 7 4Bit GPIO_INT14
45 * H0 8 4Bit WKUP_INT
46 * H1 8 4Bit WKUP_INT
47 * H2 8 4Bit WKUP_INT
48 * H3 8 4Bit WKUP_INT
49 * I 8 4Bit GPIO_INT15
50 * J0 8 4Bit GPIO_INT16
51 * J1 5 4Bit GPIO_INT17
52 * J2 8 4Bit GPIO_INT18
53 * J3 8 4Bit GPIO_INT19
54 * J4 4 4Bit GPIO_INT20
55 * K0 8 4Bit None
56 * K1 6 4Bit None
57 * K2 8 4Bit None
58 * K3 8 4Bit None
59 * L0 8 4Bit None
60 * L1 8 4Bit None
61 * L2 8 4Bit None
62 * L3 8 4Bit None
63 */
64
65static struct s3c_gpio_cfg gpio_cfg = {
66 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
67 .set_pull = s3c_gpio_setpull_updown,
68 .get_pull = s3c_gpio_getpull_updown,
69};
70
71static struct s3c_gpio_cfg gpio_cfg_eint = {
72 .cfg_eint = 0xf,
73 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
74 .set_pull = s3c_gpio_setpull_updown,
75 .get_pull = s3c_gpio_getpull_updown,
76};
77
78static struct s3c_gpio_cfg gpio_cfg_noint = {
79 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
80 .set_pull = s3c_gpio_setpull_updown,
81 .get_pull = s3c_gpio_getpull_updown,
82};
83
84/*
85 * GPIO bank's base address given the index of the bank in the
86 * list of all gpio banks.
87 */
88#define S5PC100_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
89
90/*
91 * Following are the gpio banks in S5PC100.
92 *
93 * The 'config' member when left to NULL, is initialized to the default
94 * structure gpio_cfg in the init function below.
95 *
96 * The 'base' member is also initialized in the init function below.
97 * Note: The initialization of 'base' member of s3c_gpio_chip structure
98 * uses the above macro and depends on the banks being listed in order here.
99 */
100static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
101 {
102 .chip = {
103 .base = S5PC100_GPA0(0),
104 .ngpio = S5PC100_GPIO_A0_NR,
105 .label = "GPA0",
106 },
107 }, {
108 .chip = {
109 .base = S5PC100_GPA1(0),
110 .ngpio = S5PC100_GPIO_A1_NR,
111 .label = "GPA1",
112 },
113 }, {
114 .chip = {
115 .base = S5PC100_GPB(0),
116 .ngpio = S5PC100_GPIO_B_NR,
117 .label = "GPB",
118 },
119 }, {
120 .chip = {
121 .base = S5PC100_GPC(0),
122 .ngpio = S5PC100_GPIO_C_NR,
123 .label = "GPC",
124 },
125 }, {
126 .chip = {
127 .base = S5PC100_GPD(0),
128 .ngpio = S5PC100_GPIO_D_NR,
129 .label = "GPD",
130 },
131 }, {
132 .chip = {
133 .base = S5PC100_GPE0(0),
134 .ngpio = S5PC100_GPIO_E0_NR,
135 .label = "GPE0",
136 },
137 }, {
138 .chip = {
139 .base = S5PC100_GPE1(0),
140 .ngpio = S5PC100_GPIO_E1_NR,
141 .label = "GPE1",
142 },
143 }, {
144 .chip = {
145 .base = S5PC100_GPF0(0),
146 .ngpio = S5PC100_GPIO_F0_NR,
147 .label = "GPF0",
148 },
149 }, {
150 .chip = {
151 .base = S5PC100_GPF1(0),
152 .ngpio = S5PC100_GPIO_F1_NR,
153 .label = "GPF1",
154 },
155 }, {
156 .chip = {
157 .base = S5PC100_GPF2(0),
158 .ngpio = S5PC100_GPIO_F2_NR,
159 .label = "GPF2",
160 },
161 }, {
162 .chip = {
163 .base = S5PC100_GPF3(0),
164 .ngpio = S5PC100_GPIO_F3_NR,
165 .label = "GPF3",
166 },
167 }, {
168 .chip = {
169 .base = S5PC100_GPG0(0),
170 .ngpio = S5PC100_GPIO_G0_NR,
171 .label = "GPG0",
172 },
173 }, {
174 .chip = {
175 .base = S5PC100_GPG1(0),
176 .ngpio = S5PC100_GPIO_G1_NR,
177 .label = "GPG1",
178 },
179 }, {
180 .chip = {
181 .base = S5PC100_GPG2(0),
182 .ngpio = S5PC100_GPIO_G2_NR,
183 .label = "GPG2",
184 },
185 }, {
186 .chip = {
187 .base = S5PC100_GPG3(0),
188 .ngpio = S5PC100_GPIO_G3_NR,
189 .label = "GPG3",
190 },
191 }, {
192 .chip = {
193 .base = S5PC100_GPI(0),
194 .ngpio = S5PC100_GPIO_I_NR,
195 .label = "GPI",
196 },
197 }, {
198 .chip = {
199 .base = S5PC100_GPJ0(0),
200 .ngpio = S5PC100_GPIO_J0_NR,
201 .label = "GPJ0",
202 },
203 }, {
204 .chip = {
205 .base = S5PC100_GPJ1(0),
206 .ngpio = S5PC100_GPIO_J1_NR,
207 .label = "GPJ1",
208 },
209 }, {
210 .chip = {
211 .base = S5PC100_GPJ2(0),
212 .ngpio = S5PC100_GPIO_J2_NR,
213 .label = "GPJ2",
214 },
215 }, {
216 .chip = {
217 .base = S5PC100_GPJ3(0),
218 .ngpio = S5PC100_GPIO_J3_NR,
219 .label = "GPJ3",
220 },
221 }, {
222 .chip = {
223 .base = S5PC100_GPJ4(0),
224 .ngpio = S5PC100_GPIO_J4_NR,
225 .label = "GPJ4",
226 },
227 }, {
228 .config = &gpio_cfg_noint,
229 .chip = {
230 .base = S5PC100_GPK0(0),
231 .ngpio = S5PC100_GPIO_K0_NR,
232 .label = "GPK0",
233 },
234 }, {
235 .config = &gpio_cfg_noint,
236 .chip = {
237 .base = S5PC100_GPK1(0),
238 .ngpio = S5PC100_GPIO_K1_NR,
239 .label = "GPK1",
240 },
241 }, {
242 .config = &gpio_cfg_noint,
243 .chip = {
244 .base = S5PC100_GPK2(0),
245 .ngpio = S5PC100_GPIO_K2_NR,
246 .label = "GPK2",
247 },
248 }, {
249 .config = &gpio_cfg_noint,
250 .chip = {
251 .base = S5PC100_GPK3(0),
252 .ngpio = S5PC100_GPIO_K3_NR,
253 .label = "GPK3",
254 },
255 }, {
256 .config = &gpio_cfg_noint,
257 .chip = {
258 .base = S5PC100_GPL0(0),
259 .ngpio = S5PC100_GPIO_L0_NR,
260 .label = "GPL0",
261 },
262 }, {
263 .config = &gpio_cfg_noint,
264 .chip = {
265 .base = S5PC100_GPL1(0),
266 .ngpio = S5PC100_GPIO_L1_NR,
267 .label = "GPL1",
268 },
269 }, {
270 .config = &gpio_cfg_noint,
271 .chip = {
272 .base = S5PC100_GPL2(0),
273 .ngpio = S5PC100_GPIO_L2_NR,
274 .label = "GPL2",
275 },
276 }, {
277 .config = &gpio_cfg_noint,
278 .chip = {
279 .base = S5PC100_GPL3(0),
280 .ngpio = S5PC100_GPIO_L3_NR,
281 .label = "GPL3",
282 },
283 }, {
284 .config = &gpio_cfg_noint,
285 .chip = {
286 .base = S5PC100_GPL4(0),
287 .ngpio = S5PC100_GPIO_L4_NR,
288 .label = "GPL4",
289 },
290 }, {
291 .base = (S5P_VA_GPIO + 0xC00),
292 .config = &gpio_cfg_eint,
293 .irq_base = IRQ_EINT(0),
294 .chip = {
295 .base = S5PC100_GPH0(0),
296 .ngpio = S5PC100_GPIO_H0_NR,
297 .label = "GPH0",
298 .to_irq = samsung_gpiolib_to_irq,
299 },
300 }, {
301 .base = (S5P_VA_GPIO + 0xC20),
302 .config = &gpio_cfg_eint,
303 .irq_base = IRQ_EINT(8),
304 .chip = {
305 .base = S5PC100_GPH1(0),
306 .ngpio = S5PC100_GPIO_H1_NR,
307 .label = "GPH1",
308 .to_irq = samsung_gpiolib_to_irq,
309 },
310 }, {
311 .base = (S5P_VA_GPIO + 0xC40),
312 .config = &gpio_cfg_eint,
313 .irq_base = IRQ_EINT(16),
314 .chip = {
315 .base = S5PC100_GPH2(0),
316 .ngpio = S5PC100_GPIO_H2_NR,
317 .label = "GPH2",
318 .to_irq = samsung_gpiolib_to_irq,
319 },
320 }, {
321 .base = (S5P_VA_GPIO + 0xC60),
322 .config = &gpio_cfg_eint,
323 .irq_base = IRQ_EINT(24),
324 .chip = {
325 .base = S5PC100_GPH3(0),
326 .ngpio = S5PC100_GPIO_H3_NR,
327 .label = "GPH3",
328 .to_irq = samsung_gpiolib_to_irq,
329 },
330 },
331};
332
333static __init int s5pc100_gpiolib_init(void)
334{
335 struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
336 int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
337 int gpioint_group = 0;
338 int i;
339
340 for (i = 0; i < nr_chips; i++, chip++) {
341 if (chip->config == NULL) {
342 chip->config = &gpio_cfg;
343 chip->group = gpioint_group++;
344 }
345 if (chip->base == NULL)
346 chip->base = S5PC100_BANK_BASE(i);
347 }
348
349 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
350 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
351
352 return 0;
353}
354core_initcall(s5pc100_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
deleted file mode 100644
index eb12f1602de9..000000000000
--- a/drivers/gpio/gpio-s5pv210.c
+++ /dev/null
@@ -1,287 +0,0 @@
1/*
2 * S5PV210 - GPIOlib support
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/irq.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16#include <plat/gpio-core.h>
17#include <plat/gpio-cfg.h>
18#include <plat/gpio-cfg-helpers.h>
19#include <mach/map.h>
20
21static struct s3c_gpio_cfg gpio_cfg = {
22 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
23 .set_pull = s3c_gpio_setpull_updown,
24 .get_pull = s3c_gpio_getpull_updown,
25};
26
27static struct s3c_gpio_cfg gpio_cfg_noint = {
28 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
29 .set_pull = s3c_gpio_setpull_updown,
30 .get_pull = s3c_gpio_getpull_updown,
31};
32
33/* GPIO bank's base address given the index of the bank in the
34 * list of all gpio banks.
35 */
36#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
37
38/*
39 * Following are the gpio banks in v210.
40 *
41 * The 'config' member when left to NULL, is initialized to the default
42 * structure gpio_cfg in the init function below.
43 *
44 * The 'base' member is also initialized in the init function below.
45 * Note: The initialization of 'base' member of s3c_gpio_chip structure
46 * uses the above macro and depends on the banks being listed in order here.
47 */
48static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
49 {
50 .chip = {
51 .base = S5PV210_GPA0(0),
52 .ngpio = S5PV210_GPIO_A0_NR,
53 .label = "GPA0",
54 },
55 }, {
56 .chip = {
57 .base = S5PV210_GPA1(0),
58 .ngpio = S5PV210_GPIO_A1_NR,
59 .label = "GPA1",
60 },
61 }, {
62 .chip = {
63 .base = S5PV210_GPB(0),
64 .ngpio = S5PV210_GPIO_B_NR,
65 .label = "GPB",
66 },
67 }, {
68 .chip = {
69 .base = S5PV210_GPC0(0),
70 .ngpio = S5PV210_GPIO_C0_NR,
71 .label = "GPC0",
72 },
73 }, {
74 .chip = {
75 .base = S5PV210_GPC1(0),
76 .ngpio = S5PV210_GPIO_C1_NR,
77 .label = "GPC1",
78 },
79 }, {
80 .chip = {
81 .base = S5PV210_GPD0(0),
82 .ngpio = S5PV210_GPIO_D0_NR,
83 .label = "GPD0",
84 },
85 }, {
86 .chip = {
87 .base = S5PV210_GPD1(0),
88 .ngpio = S5PV210_GPIO_D1_NR,
89 .label = "GPD1",
90 },
91 }, {
92 .chip = {
93 .base = S5PV210_GPE0(0),
94 .ngpio = S5PV210_GPIO_E0_NR,
95 .label = "GPE0",
96 },
97 }, {
98 .chip = {
99 .base = S5PV210_GPE1(0),
100 .ngpio = S5PV210_GPIO_E1_NR,
101 .label = "GPE1",
102 },
103 }, {
104 .chip = {
105 .base = S5PV210_GPF0(0),
106 .ngpio = S5PV210_GPIO_F0_NR,
107 .label = "GPF0",
108 },
109 }, {
110 .chip = {
111 .base = S5PV210_GPF1(0),
112 .ngpio = S5PV210_GPIO_F1_NR,
113 .label = "GPF1",
114 },
115 }, {
116 .chip = {
117 .base = S5PV210_GPF2(0),
118 .ngpio = S5PV210_GPIO_F2_NR,
119 .label = "GPF2",
120 },
121 }, {
122 .chip = {
123 .base = S5PV210_GPF3(0),
124 .ngpio = S5PV210_GPIO_F3_NR,
125 .label = "GPF3",
126 },
127 }, {
128 .chip = {
129 .base = S5PV210_GPG0(0),
130 .ngpio = S5PV210_GPIO_G0_NR,
131 .label = "GPG0",
132 },
133 }, {
134 .chip = {
135 .base = S5PV210_GPG1(0),
136 .ngpio = S5PV210_GPIO_G1_NR,
137 .label = "GPG1",
138 },
139 }, {
140 .chip = {
141 .base = S5PV210_GPG2(0),
142 .ngpio = S5PV210_GPIO_G2_NR,
143 .label = "GPG2",
144 },
145 }, {
146 .chip = {
147 .base = S5PV210_GPG3(0),
148 .ngpio = S5PV210_GPIO_G3_NR,
149 .label = "GPG3",
150 },
151 }, {
152 .config = &gpio_cfg_noint,
153 .chip = {
154 .base = S5PV210_GPI(0),
155 .ngpio = S5PV210_GPIO_I_NR,
156 .label = "GPI",
157 },
158 }, {
159 .chip = {
160 .base = S5PV210_GPJ0(0),
161 .ngpio = S5PV210_GPIO_J0_NR,
162 .label = "GPJ0",
163 },
164 }, {
165 .chip = {
166 .base = S5PV210_GPJ1(0),
167 .ngpio = S5PV210_GPIO_J1_NR,
168 .label = "GPJ1",
169 },
170 }, {
171 .chip = {
172 .base = S5PV210_GPJ2(0),
173 .ngpio = S5PV210_GPIO_J2_NR,
174 .label = "GPJ2",
175 },
176 }, {
177 .chip = {
178 .base = S5PV210_GPJ3(0),
179 .ngpio = S5PV210_GPIO_J3_NR,
180 .label = "GPJ3",
181 },
182 }, {
183 .chip = {
184 .base = S5PV210_GPJ4(0),
185 .ngpio = S5PV210_GPIO_J4_NR,
186 .label = "GPJ4",
187 },
188 }, {
189 .config = &gpio_cfg_noint,
190 .chip = {
191 .base = S5PV210_MP01(0),
192 .ngpio = S5PV210_GPIO_MP01_NR,
193 .label = "MP01",
194 },
195 }, {
196 .config = &gpio_cfg_noint,
197 .chip = {
198 .base = S5PV210_MP02(0),
199 .ngpio = S5PV210_GPIO_MP02_NR,
200 .label = "MP02",
201 },
202 }, {
203 .config = &gpio_cfg_noint,
204 .chip = {
205 .base = S5PV210_MP03(0),
206 .ngpio = S5PV210_GPIO_MP03_NR,
207 .label = "MP03",
208 },
209 }, {
210 .config = &gpio_cfg_noint,
211 .chip = {
212 .base = S5PV210_MP04(0),
213 .ngpio = S5PV210_GPIO_MP04_NR,
214 .label = "MP04",
215 },
216 }, {
217 .config = &gpio_cfg_noint,
218 .chip = {
219 .base = S5PV210_MP05(0),
220 .ngpio = S5PV210_GPIO_MP05_NR,
221 .label = "MP05",
222 },
223 }, {
224 .base = (S5P_VA_GPIO + 0xC00),
225 .config = &gpio_cfg_noint,
226 .irq_base = IRQ_EINT(0),
227 .chip = {
228 .base = S5PV210_GPH0(0),
229 .ngpio = S5PV210_GPIO_H0_NR,
230 .label = "GPH0",
231 .to_irq = samsung_gpiolib_to_irq,
232 },
233 }, {
234 .base = (S5P_VA_GPIO + 0xC20),
235 .config = &gpio_cfg_noint,
236 .irq_base = IRQ_EINT(8),
237 .chip = {
238 .base = S5PV210_GPH1(0),
239 .ngpio = S5PV210_GPIO_H1_NR,
240 .label = "GPH1",
241 .to_irq = samsung_gpiolib_to_irq,
242 },
243 }, {
244 .base = (S5P_VA_GPIO + 0xC40),
245 .config = &gpio_cfg_noint,
246 .irq_base = IRQ_EINT(16),
247 .chip = {
248 .base = S5PV210_GPH2(0),
249 .ngpio = S5PV210_GPIO_H2_NR,
250 .label = "GPH2",
251 .to_irq = samsung_gpiolib_to_irq,
252 },
253 }, {
254 .base = (S5P_VA_GPIO + 0xC60),
255 .config = &gpio_cfg_noint,
256 .irq_base = IRQ_EINT(24),
257 .chip = {
258 .base = S5PV210_GPH3(0),
259 .ngpio = S5PV210_GPIO_H3_NR,
260 .label = "GPH3",
261 .to_irq = samsung_gpiolib_to_irq,
262 },
263 },
264};
265
266static __init int s5pv210_gpiolib_init(void)
267{
268 struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
269 int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
270 int gpioint_group = 0;
271 int i = 0;
272
273 for (i = 0; i < nr_chips; i++, chip++) {
274 if (chip->config == NULL) {
275 chip->config = &gpio_cfg;
276 chip->group = gpioint_group++;
277 }
278 if (chip->base == NULL)
279 chip->base = S5PV210_BANK_BASE(i);
280 }
281
282 samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
283 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
284
285 return 0;
286}
287core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
new file mode 100644
index 000000000000..36f3675e7de8
--- /dev/null
+++ b/drivers/gpio/gpio-samsung.c
@@ -0,0 +1,2686 @@
1/*
2 * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * SAMSUNG - GPIOlib support
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/kernel.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <linux/init.h>
22#include <linux/spinlock.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/sysdev.h>
26#include <linux/ioport.h>
27
28#include <asm/irq.h>
29
30#include <mach/hardware.h>
31#include <mach/map.h>
32#include <mach/regs-clock.h>
33#include <mach/regs-gpio.h>
34
35#include <plat/cpu.h>
36#include <plat/gpio-core.h>
37#include <plat/gpio-cfg.h>
38#include <plat/gpio-cfg-helpers.h>
39#include <plat/gpio-fns.h>
40#include <plat/pm.h>
41
42#ifndef DEBUG_GPIO
43#define gpio_dbg(x...) do { } while (0)
44#else
45#define gpio_dbg(x...) printk(KERN_DEBUG x)
46#endif
47
48int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
49 unsigned int off, samsung_gpio_pull_t pull)
50{
51 void __iomem *reg = chip->base + 0x08;
52 int shift = off * 2;
53 u32 pup;
54
55 pup = __raw_readl(reg);
56 pup &= ~(3 << shift);
57 pup |= pull << shift;
58 __raw_writel(pup, reg);
59
60 return 0;
61}
62
63samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
64 unsigned int off)
65{
66 void __iomem *reg = chip->base + 0x08;
67 int shift = off * 2;
68 u32 pup = __raw_readl(reg);
69
70 pup >>= shift;
71 pup &= 0x3;
72
73 return (__force samsung_gpio_pull_t)pup;
74}
75
76int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
77 unsigned int off, samsung_gpio_pull_t pull)
78{
79 switch (pull) {
80 case S3C_GPIO_PULL_NONE:
81 pull = 0x01;
82 break;
83 case S3C_GPIO_PULL_UP:
84 pull = 0x00;
85 break;
86 case S3C_GPIO_PULL_DOWN:
87 pull = 0x02;
88 break;
89 }
90 return samsung_gpio_setpull_updown(chip, off, pull);
91}
92
93samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
94 unsigned int off)
95{
96 samsung_gpio_pull_t pull;
97
98 pull = samsung_gpio_getpull_updown(chip, off);
99
100 switch (pull) {
101 case 0x00:
102 pull = S3C_GPIO_PULL_UP;
103 break;
104 case 0x01:
105 case 0x03:
106 pull = S3C_GPIO_PULL_NONE;
107 break;
108 case 0x02:
109 pull = S3C_GPIO_PULL_DOWN;
110 break;
111 }
112
113 return pull;
114}
115
116static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
117 unsigned int off, samsung_gpio_pull_t pull,
118 samsung_gpio_pull_t updown)
119{
120 void __iomem *reg = chip->base + 0x08;
121 u32 pup = __raw_readl(reg);
122
123 if (pull == updown)
124 pup &= ~(1 << off);
125 else if (pull == S3C_GPIO_PULL_NONE)
126 pup |= (1 << off);
127 else
128 return -EINVAL;
129
130 __raw_writel(pup, reg);
131 return 0;
132}
133
134static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
135 unsigned int off,
136 samsung_gpio_pull_t updown)
137{
138 void __iomem *reg = chip->base + 0x08;
139 u32 pup = __raw_readl(reg);
140
141 pup &= (1 << off);
142 return pup ? S3C_GPIO_PULL_NONE : updown;
143}
144
145samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
146 unsigned int off)
147{
148 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
149}
150
151int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
152 unsigned int off, samsung_gpio_pull_t pull)
153{
154 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
155}
156
157samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
158 unsigned int off)
159{
160 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
161}
162
163int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
164 unsigned int off, samsung_gpio_pull_t pull)
165{
166 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
167}
168
169static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
170 unsigned int off, samsung_gpio_pull_t pull)
171{
172 if (pull == S3C_GPIO_PULL_UP)
173 pull = 3;
174
175 return samsung_gpio_setpull_updown(chip, off, pull);
176}
177
178static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
179 unsigned int off)
180{
181 samsung_gpio_pull_t pull;
182
183 pull = samsung_gpio_getpull_updown(chip, off);
184
185 if (pull == 3)
186 pull = S3C_GPIO_PULL_UP;
187
188 return pull;
189}
190
191/*
192 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
193 * @chip: The gpio chip that is being configured.
194 * @off: The offset for the GPIO being configured.
195 * @cfg: The configuration value to set.
196 *
197 * This helper deal with the GPIO cases where the control register
198 * has two bits of configuration per gpio, which have the following
199 * functions:
200 * 00 = input
201 * 01 = output
202 * 1x = special function
203 */
204
205static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
206 unsigned int off, unsigned int cfg)
207{
208 void __iomem *reg = chip->base;
209 unsigned int shift = off * 2;
210 u32 con;
211
212 if (samsung_gpio_is_cfg_special(cfg)) {
213 cfg &= 0xf;
214 if (cfg > 3)
215 return -EINVAL;
216
217 cfg <<= shift;
218 }
219
220 con = __raw_readl(reg);
221 con &= ~(0x3 << shift);
222 con |= cfg;
223 __raw_writel(con, reg);
224
225 return 0;
226}
227
228/*
229 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
230 * @chip: The gpio chip that is being configured.
231 * @off: The offset for the GPIO being configured.
232 *
233 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
234 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
235 * S3C_GPIO_SPECIAL() macro.
236 */
237
238static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
239 unsigned int off)
240{
241 u32 con;
242
243 con = __raw_readl(chip->base);
244 con >>= off * 2;
245 con &= 3;
246
247 /* this conversion works for IN and OUT as well as special mode */
248 return S3C_GPIO_SPECIAL(con);
249}
250
251/*
252 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
253 * @chip: The gpio chip that is being configured.
254 * @off: The offset for the GPIO being configured.
255 * @cfg: The configuration value to set.
256 *
257 * This helper deal with the GPIO cases where the control register has 4 bits
258 * of control per GPIO, generally in the form of:
259 * 0000 = Input
260 * 0001 = Output
261 * others = Special functions (dependent on bank)
262 *
263 * Note, since the code to deal with the case where there are two control
264 * registers instead of one, we do not have a separate set of functions for
265 * each case.
266 */
267
268static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
269 unsigned int off, unsigned int cfg)
270{
271 void __iomem *reg = chip->base;
272 unsigned int shift = (off & 7) * 4;
273 u32 con;
274
275 if (off < 8 && chip->chip.ngpio > 8)
276 reg -= 4;
277
278 if (samsung_gpio_is_cfg_special(cfg)) {
279 cfg &= 0xf;
280 cfg <<= shift;
281 }
282
283 con = __raw_readl(reg);
284 con &= ~(0xf << shift);
285 con |= cfg;
286 __raw_writel(con, reg);
287
288 return 0;
289}
290
291/*
292 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
293 * @chip: The gpio chip that is being configured.
294 * @off: The offset for the GPIO being configured.
295 *
296 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
297 * register setting into a value the software can use, such as could be passed
298 * to samsung_gpio_setcfg_4bit().
299 *
300 * @sa samsung_gpio_getcfg_2bit
301 */
302
303static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
304 unsigned int off)
305{
306 void __iomem *reg = chip->base;
307 unsigned int shift = (off & 7) * 4;
308 u32 con;
309
310 if (off < 8 && chip->chip.ngpio > 8)
311 reg -= 4;
312
313 con = __raw_readl(reg);
314 con >>= shift;
315 con &= 0xf;
316
317 /* this conversion works for IN and OUT as well as special mode */
318 return S3C_GPIO_SPECIAL(con);
319}
320
321/*
322 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
323 * @chip: The gpio chip that is being configured.
324 * @off: The offset for the GPIO being configured.
325 * @cfg: The configuration value to set.
326 *
327 * This helper deal with the GPIO cases where the control register
328 * has one bit of configuration for the gpio, where setting the bit
329 * means the pin is in special function mode and unset means output.
330 */
331
332static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
333 unsigned int off, unsigned int cfg)
334{
335 void __iomem *reg = chip->base;
336 unsigned int shift = off;
337 u32 con;
338
339 if (samsung_gpio_is_cfg_special(cfg)) {
340 cfg &= 0xf;
341
342 /* Map output to 0, and SFN2 to 1 */
343 cfg -= 1;
344 if (cfg > 1)
345 return -EINVAL;
346
347 cfg <<= shift;
348 }
349
350 con = __raw_readl(reg);
351 con &= ~(0x1 << shift);
352 con |= cfg;
353 __raw_writel(con, reg);
354
355 return 0;
356}
357
358/*
359 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
360 * @chip: The gpio chip that is being configured.
361 * @off: The offset for the GPIO being configured.
362 *
363 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
364 * GPIO configuration value.
365 *
366 * @sa samsung_gpio_getcfg_2bit
367 * @sa samsung_gpio_getcfg_4bit
368 */
369
370static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
371 unsigned int off)
372{
373 u32 con;
374
375 con = __raw_readl(chip->base);
376 con >>= off;
377 con &= 1;
378 con++;
379
380 return S3C_GPIO_SFN(con);
381}
382
383static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
384 unsigned int off, unsigned int cfg)
385{
386 void __iomem *reg = chip->base;
387 unsigned int shift;
388 u32 con;
389
390 switch (off) {
391 case 0:
392 case 1:
393 case 2:
394 case 3:
395 case 4:
396 case 5:
397 shift = (off & 7) * 4;
398 reg -= 4;
399 break;
400 case 6:
401 shift = ((off + 1) & 7) * 4;
402 reg -= 4;
403 default:
404 shift = ((off + 1) & 7) * 4;
405 break;
406 }
407
408 if (samsung_gpio_is_cfg_special(cfg)) {
409 cfg &= 0xf;
410 cfg <<= shift;
411 }
412
413 con = __raw_readl(reg);
414 con &= ~(0xf << shift);
415 con |= cfg;
416 __raw_writel(con, reg);
417
418 return 0;
419}
420
421static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
422 int nr_chips)
423{
424 for (; nr_chips > 0; nr_chips--, chipcfg++) {
425 if (!chipcfg->set_config)
426 chipcfg->set_config = samsung_gpio_setcfg_4bit;
427 if (!chipcfg->get_config)
428 chipcfg->get_config = samsung_gpio_getcfg_4bit;
429 if (!chipcfg->set_pull)
430 chipcfg->set_pull = samsung_gpio_setpull_updown;
431 if (!chipcfg->get_pull)
432 chipcfg->get_pull = samsung_gpio_getpull_updown;
433 }
434}
435
436struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
437 .set_config = samsung_gpio_setcfg_2bit,
438 .get_config = samsung_gpio_getcfg_2bit,
439};
440
441static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
442 .set_config = s3c24xx_gpio_setcfg_abank,
443 .get_config = s3c24xx_gpio_getcfg_abank,
444};
445
446static struct samsung_gpio_cfg exynos4_gpio_cfg = {
447 .set_pull = exynos4_gpio_setpull,
448 .get_pull = exynos4_gpio_getpull,
449};
450
451static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
452 .cfg_eint = 0x3,
453 .set_config = s5p64x0_gpio_setcfg_rbank,
454 .get_config = samsung_gpio_getcfg_4bit,
455 .set_pull = samsung_gpio_setpull_updown,
456 .get_pull = samsung_gpio_getpull_updown,
457};
458
459static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
460 {
461 .cfg_eint = 0x0,
462 }, {
463 .cfg_eint = 0x3,
464 }, {
465 .cfg_eint = 0x7,
466 }, {
467 .cfg_eint = 0xF,
468 }, {
469 .cfg_eint = 0x0,
470 .set_config = samsung_gpio_setcfg_2bit,
471 .get_config = samsung_gpio_getcfg_2bit,
472 }, {
473 .cfg_eint = 0x2,
474 .set_config = samsung_gpio_setcfg_2bit,
475 .get_config = samsung_gpio_getcfg_2bit,
476 }, {
477 .cfg_eint = 0x3,
478 .set_config = samsung_gpio_setcfg_2bit,
479 .get_config = samsung_gpio_getcfg_2bit,
480 }, {
481 .set_config = samsung_gpio_setcfg_2bit,
482 .get_config = samsung_gpio_getcfg_2bit,
483 },
484};
485
486/*
487 * Default routines for controlling GPIO, based on the original S3C24XX
488 * GPIO functions which deal with the case where each gpio bank of the
489 * chip is as following:
490 *
491 * base + 0x00: Control register, 2 bits per gpio
492 * gpio n: 2 bits starting at (2*n)
493 * 00 = input, 01 = output, others mean special-function
494 * base + 0x04: Data register, 1 bit per gpio
495 * bit n: data bit n
496*/
497
498static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
499{
500 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
501 void __iomem *base = ourchip->base;
502 unsigned long flags;
503 unsigned long con;
504
505 samsung_gpio_lock(ourchip, flags);
506
507 con = __raw_readl(base + 0x00);
508 con &= ~(3 << (offset * 2));
509
510 __raw_writel(con, base + 0x00);
511
512 samsung_gpio_unlock(ourchip, flags);
513 return 0;
514}
515
516static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
517 unsigned offset, int value)
518{
519 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
520 void __iomem *base = ourchip->base;
521 unsigned long flags;
522 unsigned long dat;
523 unsigned long con;
524
525 samsung_gpio_lock(ourchip, flags);
526
527 dat = __raw_readl(base + 0x04);
528 dat &= ~(1 << offset);
529 if (value)
530 dat |= 1 << offset;
531 __raw_writel(dat, base + 0x04);
532
533 con = __raw_readl(base + 0x00);
534 con &= ~(3 << (offset * 2));
535 con |= 1 << (offset * 2);
536
537 __raw_writel(con, base + 0x00);
538 __raw_writel(dat, base + 0x04);
539
540 samsung_gpio_unlock(ourchip, flags);
541 return 0;
542}
543
544/*
545 * The samsung_gpiolib_4bit routines are to control the gpio banks where
546 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
547 * following example:
548 *
549 * base + 0x00: Control register, 4 bits per gpio
550 * gpio n: 4 bits starting at (4*n)
551 * 0000 = input, 0001 = output, others mean special-function
552 * base + 0x04: Data register, 1 bit per gpio
553 * bit n: data bit n
554 *
555 * Note, since the data register is one bit per gpio and is at base + 0x4
556 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
557 * state of the output.
558 */
559
560static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
561 unsigned int offset)
562{
563 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
564 void __iomem *base = ourchip->base;
565 unsigned long con;
566
567 con = __raw_readl(base + GPIOCON_OFF);
568 con &= ~(0xf << con_4bit_shift(offset));
569 __raw_writel(con, base + GPIOCON_OFF);
570
571 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
572
573 return 0;
574}
575
576static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
577 unsigned int offset, int value)
578{
579 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
580 void __iomem *base = ourchip->base;
581 unsigned long con;
582 unsigned long dat;
583
584 con = __raw_readl(base + GPIOCON_OFF);
585 con &= ~(0xf << con_4bit_shift(offset));
586 con |= 0x1 << con_4bit_shift(offset);
587
588 dat = __raw_readl(base + GPIODAT_OFF);
589
590 if (value)
591 dat |= 1 << offset;
592 else
593 dat &= ~(1 << offset);
594
595 __raw_writel(dat, base + GPIODAT_OFF);
596 __raw_writel(con, base + GPIOCON_OFF);
597 __raw_writel(dat, base + GPIODAT_OFF);
598
599 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
600
601 return 0;
602}
603
604/*
605 * The next set of routines are for the case where the GPIO configuration
606 * registers are 4 bits per GPIO but there is more than one register (the
607 * bank has more than 8 GPIOs.
608 *
609 * This case is the similar to the 4 bit case, but the registers are as
610 * follows:
611 *
612 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
613 * gpio n: 4 bits starting at (4*n)
614 * 0000 = input, 0001 = output, others mean special-function
615 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
616 * gpio n: 4 bits starting at (4*n)
617 * 0000 = input, 0001 = output, others mean special-function
618 * base + 0x08: Data register, 1 bit per gpio
619 * bit n: data bit n
620 *
621 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
622 * routines we store the 'base + 0x4' address so that these routines see
623 * the data register at ourchip->base + 0x04.
624 */
625
626static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
627 unsigned int offset)
628{
629 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
630 void __iomem *base = ourchip->base;
631 void __iomem *regcon = base;
632 unsigned long con;
633
634 if (offset > 7)
635 offset -= 8;
636 else
637 regcon -= 4;
638
639 con = __raw_readl(regcon);
640 con &= ~(0xf << con_4bit_shift(offset));
641 __raw_writel(con, regcon);
642
643 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
644
645 return 0;
646}
647
648static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
649 unsigned int offset, int value)
650{
651 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
652 void __iomem *base = ourchip->base;
653 void __iomem *regcon = base;
654 unsigned long con;
655 unsigned long dat;
656 unsigned con_offset = offset;
657
658 if (con_offset > 7)
659 con_offset -= 8;
660 else
661 regcon -= 4;
662
663 con = __raw_readl(regcon);
664 con &= ~(0xf << con_4bit_shift(con_offset));
665 con |= 0x1 << con_4bit_shift(con_offset);
666
667 dat = __raw_readl(base + GPIODAT_OFF);
668
669 if (value)
670 dat |= 1 << offset;
671 else
672 dat &= ~(1 << offset);
673
674 __raw_writel(dat, base + GPIODAT_OFF);
675 __raw_writel(con, regcon);
676 __raw_writel(dat, base + GPIODAT_OFF);
677
678 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
679
680 return 0;
681}
682
683/* The next set of routines are for the case of s3c24xx bank a */
684
685static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
686{
687 return -EINVAL;
688}
689
690static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
691 unsigned offset, int value)
692{
693 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
694 void __iomem *base = ourchip->base;
695 unsigned long flags;
696 unsigned long dat;
697 unsigned long con;
698
699 local_irq_save(flags);
700
701 con = __raw_readl(base + 0x00);
702 dat = __raw_readl(base + 0x04);
703
704 dat &= ~(1 << offset);
705 if (value)
706 dat |= 1 << offset;
707
708 __raw_writel(dat, base + 0x04);
709
710 con &= ~(1 << offset);
711
712 __raw_writel(con, base + 0x00);
713 __raw_writel(dat, base + 0x04);
714
715 local_irq_restore(flags);
716 return 0;
717}
718
719/* The next set of routines are for the case of s5p64x0 bank r */
720
721static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
722 unsigned int offset)
723{
724 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
725 void __iomem *base = ourchip->base;
726 void __iomem *regcon = base;
727 unsigned long con;
728 unsigned long flags;
729
730 switch (offset) {
731 case 6:
732 offset += 1;
733 case 0:
734 case 1:
735 case 2:
736 case 3:
737 case 4:
738 case 5:
739 regcon -= 4;
740 break;
741 default:
742 offset -= 7;
743 break;
744 }
745
746 samsung_gpio_lock(ourchip, flags);
747
748 con = __raw_readl(regcon);
749 con &= ~(0xf << con_4bit_shift(offset));
750 __raw_writel(con, regcon);
751
752 samsung_gpio_unlock(ourchip, flags);
753
754 return 0;
755}
756
757static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
758 unsigned int offset, int value)
759{
760 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
761 void __iomem *base = ourchip->base;
762 void __iomem *regcon = base;
763 unsigned long con;
764 unsigned long dat;
765 unsigned long flags;
766 unsigned con_offset = offset;
767
768 switch (con_offset) {
769 case 6:
770 con_offset += 1;
771 case 0:
772 case 1:
773 case 2:
774 case 3:
775 case 4:
776 case 5:
777 regcon -= 4;
778 break;
779 default:
780 con_offset -= 7;
781 break;
782 }
783
784 samsung_gpio_lock(ourchip, flags);
785
786 con = __raw_readl(regcon);
787 con &= ~(0xf << con_4bit_shift(con_offset));
788 con |= 0x1 << con_4bit_shift(con_offset);
789
790 dat = __raw_readl(base + GPIODAT_OFF);
791 if (value)
792 dat |= 1 << offset;
793 else
794 dat &= ~(1 << offset);
795
796 __raw_writel(con, regcon);
797 __raw_writel(dat, base + GPIODAT_OFF);
798
799 samsung_gpio_unlock(ourchip, flags);
800
801 return 0;
802}
803
804static void samsung_gpiolib_set(struct gpio_chip *chip,
805 unsigned offset, int value)
806{
807 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
808 void __iomem *base = ourchip->base;
809 unsigned long flags;
810 unsigned long dat;
811
812 samsung_gpio_lock(ourchip, flags);
813
814 dat = __raw_readl(base + 0x04);
815 dat &= ~(1 << offset);
816 if (value)
817 dat |= 1 << offset;
818 __raw_writel(dat, base + 0x04);
819
820 samsung_gpio_unlock(ourchip, flags);
821}
822
823static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
824{
825 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
826 unsigned long val;
827
828 val = __raw_readl(ourchip->base + 0x04);
829 val >>= offset;
830 val &= 1;
831
832 return val;
833}
834
835/*
836 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
837 * for use with the configuration calls, and other parts of the s3c gpiolib
838 * support code.
839 *
840 * Not all s3c support code will need this, as some configurations of cpu
841 * may only support one or two different configuration options and have an
842 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
843 * the machine support file should provide its own samsung_gpiolib_getchip()
844 * and any other necessary functions.
845 */
846
847#ifdef CONFIG_S3C_GPIO_TRACK
848struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
849
850static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
851{
852 unsigned int gpn;
853 int i;
854
855 gpn = chip->chip.base;
856 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
857 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
858 s3c_gpios[gpn] = chip;
859 }
860}
861#endif /* CONFIG_S3C_GPIO_TRACK */
862
863/*
864 * samsung_gpiolib_add() - add the Samsung gpio_chip.
865 * @chip: The chip to register
866 *
867 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
868 * information and makes the necessary alterations for the platform and
869 * notes the information for use with the configuration systems and any
870 * other parts of the system.
871 */
872
873static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
874{
875 struct gpio_chip *gc = &chip->chip;
876 int ret;
877
878 BUG_ON(!chip->base);
879 BUG_ON(!gc->label);
880 BUG_ON(!gc->ngpio);
881
882 spin_lock_init(&chip->lock);
883
884 if (!gc->direction_input)
885 gc->direction_input = samsung_gpiolib_2bit_input;
886 if (!gc->direction_output)
887 gc->direction_output = samsung_gpiolib_2bit_output;
888 if (!gc->set)
889 gc->set = samsung_gpiolib_set;
890 if (!gc->get)
891 gc->get = samsung_gpiolib_get;
892
893#ifdef CONFIG_PM
894 if (chip->pm != NULL) {
895 if (!chip->pm->save || !chip->pm->resume)
896 printk(KERN_ERR "gpio: %s has missing PM functions\n",
897 gc->label);
898 } else
899 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
900#endif
901
902 /* gpiochip_add() prints own failure message on error. */
903 ret = gpiochip_add(gc);
904 if (ret >= 0)
905 s3c_gpiolib_track(chip);
906}
907
908static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
909 int nr_chips, void __iomem *base)
910{
911 int i;
912 struct gpio_chip *gc = &chip->chip;
913
914 for (i = 0 ; i < nr_chips; i++, chip++) {
915 if (!chip->config)
916 chip->config = &s3c24xx_gpiocfg_default;
917 if (!chip->pm)
918 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
919 if ((base != NULL) && (chip->base == NULL))
920 chip->base = base + ((i) * 0x10);
921
922 if (!gc->direction_input)
923 gc->direction_input = samsung_gpiolib_2bit_input;
924 if (!gc->direction_output)
925 gc->direction_output = samsung_gpiolib_2bit_output;
926
927 samsung_gpiolib_add(chip);
928 }
929}
930
931static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
932 int nr_chips, void __iomem *base,
933 unsigned int offset)
934{
935 int i;
936
937 for (i = 0 ; i < nr_chips; i++, chip++) {
938 chip->chip.direction_input = samsung_gpiolib_2bit_input;
939 chip->chip.direction_output = samsung_gpiolib_2bit_output;
940
941 if (!chip->config)
942 chip->config = &samsung_gpio_cfgs[7];
943 if (!chip->pm)
944 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
945 if ((base != NULL) && (chip->base == NULL))
946 chip->base = base + ((i) * offset);
947
948 samsung_gpiolib_add(chip);
949 }
950}
951
952/*
953 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
954 * @chip: The gpio chip that is being configured.
955 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
956 *
957 * This helper deal with the GPIO cases where the control register has 4 bits
958 * of control per GPIO, generally in the form of:
959 * 0000 = Input
960 * 0001 = Output
961 * others = Special functions (dependent on bank)
962 *
963 * Note, since the code to deal with the case where there are two control
964 * registers instead of one, we do not have a separate set of function
965 * (samsung_gpiolib_add_4bit2_chips)for each case.
966 */
967
968static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
969 int nr_chips, void __iomem *base)
970{
971 int i;
972
973 for (i = 0 ; i < nr_chips; i++, chip++) {
974 chip->chip.direction_input = samsung_gpiolib_4bit_input;
975 chip->chip.direction_output = samsung_gpiolib_4bit_output;
976
977 if (!chip->config)
978 chip->config = &samsung_gpio_cfgs[2];
979 if (!chip->pm)
980 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
981 if ((base != NULL) && (chip->base == NULL))
982 chip->base = base + ((i) * 0x20);
983
984 samsung_gpiolib_add(chip);
985 }
986}
987
988static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
989 int nr_chips)
990{
991 for (; nr_chips > 0; nr_chips--, chip++) {
992 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
993 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
994
995 if (!chip->config)
996 chip->config = &samsung_gpio_cfgs[2];
997 if (!chip->pm)
998 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
999
1000 samsung_gpiolib_add(chip);
1001 }
1002}
1003
1004static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1005 int nr_chips)
1006{
1007 for (; nr_chips > 0; nr_chips--, chip++) {
1008 chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1009 chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1010
1011 if (!chip->pm)
1012 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1013
1014 samsung_gpiolib_add(chip);
1015 }
1016}
1017
1018int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1019{
1020 struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1021
1022 return samsung_chip->irq_base + offset;
1023}
1024
1025#ifdef CONFIG_PLAT_S3C24XX
1026static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1027{
1028 if (offset < 4)
1029 return IRQ_EINT0 + offset;
1030
1031 if (offset < 8)
1032 return IRQ_EINT4 + offset - 4;
1033
1034 return -EINVAL;
1035}
1036#endif
1037
1038#ifdef CONFIG_PLAT_S3C64XX
1039static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1040{
1041 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1042}
1043
1044static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1045{
1046 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1047}
1048#endif
1049
1050struct samsung_gpio_chip s3c24xx_gpios[] = {
1051#ifdef CONFIG_PLAT_S3C24XX
1052 {
1053 .config = &s3c24xx_gpiocfg_banka,
1054 .chip = {
1055 .base = S3C2410_GPA(0),
1056 .owner = THIS_MODULE,
1057 .label = "GPIOA",
1058 .ngpio = 24,
1059 .direction_input = s3c24xx_gpiolib_banka_input,
1060 .direction_output = s3c24xx_gpiolib_banka_output,
1061 },
1062 }, {
1063 .chip = {
1064 .base = S3C2410_GPB(0),
1065 .owner = THIS_MODULE,
1066 .label = "GPIOB",
1067 .ngpio = 16,
1068 },
1069 }, {
1070 .chip = {
1071 .base = S3C2410_GPC(0),
1072 .owner = THIS_MODULE,
1073 .label = "GPIOC",
1074 .ngpio = 16,
1075 },
1076 }, {
1077 .chip = {
1078 .base = S3C2410_GPD(0),
1079 .owner = THIS_MODULE,
1080 .label = "GPIOD",
1081 .ngpio = 16,
1082 },
1083 }, {
1084 .chip = {
1085 .base = S3C2410_GPE(0),
1086 .label = "GPIOE",
1087 .owner = THIS_MODULE,
1088 .ngpio = 16,
1089 },
1090 }, {
1091 .chip = {
1092 .base = S3C2410_GPF(0),
1093 .owner = THIS_MODULE,
1094 .label = "GPIOF",
1095 .ngpio = 8,
1096 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1097 },
1098 }, {
1099 .irq_base = IRQ_EINT8,
1100 .chip = {
1101 .base = S3C2410_GPG(0),
1102 .owner = THIS_MODULE,
1103 .label = "GPIOG",
1104 .ngpio = 16,
1105 .to_irq = samsung_gpiolib_to_irq,
1106 },
1107 }, {
1108 .chip = {
1109 .base = S3C2410_GPH(0),
1110 .owner = THIS_MODULE,
1111 .label = "GPIOH",
1112 .ngpio = 11,
1113 },
1114 },
1115 /* GPIOS for the S3C2443 and later devices. */
1116 {
1117 .base = S3C2440_GPJCON,
1118 .chip = {
1119 .base = S3C2410_GPJ(0),
1120 .owner = THIS_MODULE,
1121 .label = "GPIOJ",
1122 .ngpio = 16,
1123 },
1124 }, {
1125 .base = S3C2443_GPKCON,
1126 .chip = {
1127 .base = S3C2410_GPK(0),
1128 .owner = THIS_MODULE,
1129 .label = "GPIOK",
1130 .ngpio = 16,
1131 },
1132 }, {
1133 .base = S3C2443_GPLCON,
1134 .chip = {
1135 .base = S3C2410_GPL(0),
1136 .owner = THIS_MODULE,
1137 .label = "GPIOL",
1138 .ngpio = 15,
1139 },
1140 }, {
1141 .base = S3C2443_GPMCON,
1142 .chip = {
1143 .base = S3C2410_GPM(0),
1144 .owner = THIS_MODULE,
1145 .label = "GPIOM",
1146 .ngpio = 2,
1147 },
1148 },
1149#endif
1150};
1151
1152/*
1153 * GPIO bank summary:
1154 *
1155 * Bank GPIOs Style SlpCon ExtInt Group
1156 * A 8 4Bit Yes 1
1157 * B 7 4Bit Yes 1
1158 * C 8 4Bit Yes 2
1159 * D 5 4Bit Yes 3
1160 * E 5 4Bit Yes None
1161 * F 16 2Bit Yes 4 [1]
1162 * G 7 4Bit Yes 5
1163 * H 10 4Bit[2] Yes 6
1164 * I 16 2Bit Yes None
1165 * J 12 2Bit Yes None
1166 * K 16 4Bit[2] No None
1167 * L 15 4Bit[2] No None
1168 * M 6 4Bit No IRQ_EINT
1169 * N 16 2Bit No IRQ_EINT
1170 * O 16 2Bit Yes 7
1171 * P 15 2Bit Yes 8
1172 * Q 9 2Bit Yes 9
1173 *
1174 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1175 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1176 */
1177
1178static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1179#ifdef CONFIG_PLAT_S3C64XX
1180 {
1181 .chip = {
1182 .base = S3C64XX_GPA(0),
1183 .ngpio = S3C64XX_GPIO_A_NR,
1184 .label = "GPA",
1185 },
1186 }, {
1187 .chip = {
1188 .base = S3C64XX_GPB(0),
1189 .ngpio = S3C64XX_GPIO_B_NR,
1190 .label = "GPB",
1191 },
1192 }, {
1193 .chip = {
1194 .base = S3C64XX_GPC(0),
1195 .ngpio = S3C64XX_GPIO_C_NR,
1196 .label = "GPC",
1197 },
1198 }, {
1199 .chip = {
1200 .base = S3C64XX_GPD(0),
1201 .ngpio = S3C64XX_GPIO_D_NR,
1202 .label = "GPD",
1203 },
1204 }, {
1205 .config = &samsung_gpio_cfgs[0],
1206 .chip = {
1207 .base = S3C64XX_GPE(0),
1208 .ngpio = S3C64XX_GPIO_E_NR,
1209 .label = "GPE",
1210 },
1211 }, {
1212 .base = S3C64XX_GPG_BASE,
1213 .chip = {
1214 .base = S3C64XX_GPG(0),
1215 .ngpio = S3C64XX_GPIO_G_NR,
1216 .label = "GPG",
1217 },
1218 }, {
1219 .base = S3C64XX_GPM_BASE,
1220 .config = &samsung_gpio_cfgs[1],
1221 .chip = {
1222 .base = S3C64XX_GPM(0),
1223 .ngpio = S3C64XX_GPIO_M_NR,
1224 .label = "GPM",
1225 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1226 },
1227 },
1228#endif
1229};
1230
1231static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1232#ifdef CONFIG_PLAT_S3C64XX
1233 {
1234 .base = S3C64XX_GPH_BASE + 0x4,
1235 .chip = {
1236 .base = S3C64XX_GPH(0),
1237 .ngpio = S3C64XX_GPIO_H_NR,
1238 .label = "GPH",
1239 },
1240 }, {
1241 .base = S3C64XX_GPK_BASE + 0x4,
1242 .config = &samsung_gpio_cfgs[0],
1243 .chip = {
1244 .base = S3C64XX_GPK(0),
1245 .ngpio = S3C64XX_GPIO_K_NR,
1246 .label = "GPK",
1247 },
1248 }, {
1249 .base = S3C64XX_GPL_BASE + 0x4,
1250 .config = &samsung_gpio_cfgs[1],
1251 .chip = {
1252 .base = S3C64XX_GPL(0),
1253 .ngpio = S3C64XX_GPIO_L_NR,
1254 .label = "GPL",
1255 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1256 },
1257 },
1258#endif
1259};
1260
1261static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1262#ifdef CONFIG_PLAT_S3C64XX
1263 {
1264 .base = S3C64XX_GPF_BASE,
1265 .config = &samsung_gpio_cfgs[6],
1266 .chip = {
1267 .base = S3C64XX_GPF(0),
1268 .ngpio = S3C64XX_GPIO_F_NR,
1269 .label = "GPF",
1270 },
1271 }, {
1272 .config = &samsung_gpio_cfgs[7],
1273 .chip = {
1274 .base = S3C64XX_GPI(0),
1275 .ngpio = S3C64XX_GPIO_I_NR,
1276 .label = "GPI",
1277 },
1278 }, {
1279 .config = &samsung_gpio_cfgs[7],
1280 .chip = {
1281 .base = S3C64XX_GPJ(0),
1282 .ngpio = S3C64XX_GPIO_J_NR,
1283 .label = "GPJ",
1284 },
1285 }, {
1286 .config = &samsung_gpio_cfgs[6],
1287 .chip = {
1288 .base = S3C64XX_GPO(0),
1289 .ngpio = S3C64XX_GPIO_O_NR,
1290 .label = "GPO",
1291 },
1292 }, {
1293 .config = &samsung_gpio_cfgs[6],
1294 .chip = {
1295 .base = S3C64XX_GPP(0),
1296 .ngpio = S3C64XX_GPIO_P_NR,
1297 .label = "GPP",
1298 },
1299 }, {
1300 .config = &samsung_gpio_cfgs[6],
1301 .chip = {
1302 .base = S3C64XX_GPQ(0),
1303 .ngpio = S3C64XX_GPIO_Q_NR,
1304 .label = "GPQ",
1305 },
1306 }, {
1307 .base = S3C64XX_GPN_BASE,
1308 .irq_base = IRQ_EINT(0),
1309 .config = &samsung_gpio_cfgs[5],
1310 .chip = {
1311 .base = S3C64XX_GPN(0),
1312 .ngpio = S3C64XX_GPIO_N_NR,
1313 .label = "GPN",
1314 .to_irq = samsung_gpiolib_to_irq,
1315 },
1316 },
1317#endif
1318};
1319
1320/*
1321 * S5P6440 GPIO bank summary:
1322 *
1323 * Bank GPIOs Style SlpCon ExtInt Group
1324 * A 6 4Bit Yes 1
1325 * B 7 4Bit Yes 1
1326 * C 8 4Bit Yes 2
1327 * F 2 2Bit Yes 4 [1]
1328 * G 7 4Bit Yes 5
1329 * H 10 4Bit[2] Yes 6
1330 * I 16 2Bit Yes None
1331 * J 12 2Bit Yes None
1332 * N 16 2Bit No IRQ_EINT
1333 * P 8 2Bit Yes 8
1334 * R 15 4Bit[2] Yes 8
1335 */
1336
1337static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1338#ifdef CONFIG_CPU_S5P6440
1339 {
1340 .chip = {
1341 .base = S5P6440_GPA(0),
1342 .ngpio = S5P6440_GPIO_A_NR,
1343 .label = "GPA",
1344 },
1345 }, {
1346 .chip = {
1347 .base = S5P6440_GPB(0),
1348 .ngpio = S5P6440_GPIO_B_NR,
1349 .label = "GPB",
1350 },
1351 }, {
1352 .chip = {
1353 .base = S5P6440_GPC(0),
1354 .ngpio = S5P6440_GPIO_C_NR,
1355 .label = "GPC",
1356 },
1357 }, {
1358 .base = S5P64X0_GPG_BASE,
1359 .chip = {
1360 .base = S5P6440_GPG(0),
1361 .ngpio = S5P6440_GPIO_G_NR,
1362 .label = "GPG",
1363 },
1364 },
1365#endif
1366};
1367
1368static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1369#ifdef CONFIG_CPU_S5P6440
1370 {
1371 .base = S5P64X0_GPH_BASE + 0x4,
1372 .chip = {
1373 .base = S5P6440_GPH(0),
1374 .ngpio = S5P6440_GPIO_H_NR,
1375 .label = "GPH",
1376 },
1377 },
1378#endif
1379};
1380
1381static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1382#ifdef CONFIG_CPU_S5P6440
1383 {
1384 .base = S5P64X0_GPR_BASE + 0x4,
1385 .config = &s5p64x0_gpio_cfg_rbank,
1386 .chip = {
1387 .base = S5P6440_GPR(0),
1388 .ngpio = S5P6440_GPIO_R_NR,
1389 .label = "GPR",
1390 },
1391 },
1392#endif
1393};
1394
1395static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1396#ifdef CONFIG_CPU_S5P6440
1397 {
1398 .base = S5P64X0_GPF_BASE,
1399 .config = &samsung_gpio_cfgs[6],
1400 .chip = {
1401 .base = S5P6440_GPF(0),
1402 .ngpio = S5P6440_GPIO_F_NR,
1403 .label = "GPF",
1404 },
1405 }, {
1406 .base = S5P64X0_GPI_BASE,
1407 .config = &samsung_gpio_cfgs[4],
1408 .chip = {
1409 .base = S5P6440_GPI(0),
1410 .ngpio = S5P6440_GPIO_I_NR,
1411 .label = "GPI",
1412 },
1413 }, {
1414 .base = S5P64X0_GPJ_BASE,
1415 .config = &samsung_gpio_cfgs[4],
1416 .chip = {
1417 .base = S5P6440_GPJ(0),
1418 .ngpio = S5P6440_GPIO_J_NR,
1419 .label = "GPJ",
1420 },
1421 }, {
1422 .base = S5P64X0_GPN_BASE,
1423 .config = &samsung_gpio_cfgs[5],
1424 .chip = {
1425 .base = S5P6440_GPN(0),
1426 .ngpio = S5P6440_GPIO_N_NR,
1427 .label = "GPN",
1428 },
1429 }, {
1430 .base = S5P64X0_GPP_BASE,
1431 .config = &samsung_gpio_cfgs[6],
1432 .chip = {
1433 .base = S5P6440_GPP(0),
1434 .ngpio = S5P6440_GPIO_P_NR,
1435 .label = "GPP",
1436 },
1437 },
1438#endif
1439};
1440
1441/*
1442 * S5P6450 GPIO bank summary:
1443 *
1444 * Bank GPIOs Style SlpCon ExtInt Group
1445 * A 6 4Bit Yes 1
1446 * B 7 4Bit Yes 1
1447 * C 8 4Bit Yes 2
1448 * D 8 4Bit Yes None
1449 * F 2 2Bit Yes None
1450 * G 14 4Bit[2] Yes 5
1451 * H 10 4Bit[2] Yes 6
1452 * I 16 2Bit Yes None
1453 * J 12 2Bit Yes None
1454 * K 5 4Bit Yes None
1455 * N 16 2Bit No IRQ_EINT
1456 * P 11 2Bit Yes 8
1457 * Q 14 2Bit Yes None
1458 * R 15 4Bit[2] Yes None
1459 * S 8 2Bit Yes None
1460 *
1461 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1462 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1463 */
1464
1465static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1466#ifdef CONFIG_CPU_S5P6450
1467 {
1468 .chip = {
1469 .base = S5P6450_GPA(0),
1470 .ngpio = S5P6450_GPIO_A_NR,
1471 .label = "GPA",
1472 },
1473 }, {
1474 .chip = {
1475 .base = S5P6450_GPB(0),
1476 .ngpio = S5P6450_GPIO_B_NR,
1477 .label = "GPB",
1478 },
1479 }, {
1480 .chip = {
1481 .base = S5P6450_GPC(0),
1482 .ngpio = S5P6450_GPIO_C_NR,
1483 .label = "GPC",
1484 },
1485 }, {
1486 .chip = {
1487 .base = S5P6450_GPD(0),
1488 .ngpio = S5P6450_GPIO_D_NR,
1489 .label = "GPD",
1490 },
1491 }, {
1492 .base = S5P6450_GPK_BASE,
1493 .chip = {
1494 .base = S5P6450_GPK(0),
1495 .ngpio = S5P6450_GPIO_K_NR,
1496 .label = "GPK",
1497 },
1498 },
1499#endif
1500};
1501
1502static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1503#ifdef CONFIG_CPU_S5P6450
1504 {
1505 .base = S5P64X0_GPG_BASE + 0x4,
1506 .chip = {
1507 .base = S5P6450_GPG(0),
1508 .ngpio = S5P6450_GPIO_G_NR,
1509 .label = "GPG",
1510 },
1511 }, {
1512 .base = S5P64X0_GPH_BASE + 0x4,
1513 .chip = {
1514 .base = S5P6450_GPH(0),
1515 .ngpio = S5P6450_GPIO_H_NR,
1516 .label = "GPH",
1517 },
1518 },
1519#endif
1520};
1521
1522static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1523#ifdef CONFIG_CPU_S5P6450
1524 {
1525 .base = S5P64X0_GPR_BASE + 0x4,
1526 .config = &s5p64x0_gpio_cfg_rbank,
1527 .chip = {
1528 .base = S5P6450_GPR(0),
1529 .ngpio = S5P6450_GPIO_R_NR,
1530 .label = "GPR",
1531 },
1532 },
1533#endif
1534};
1535
1536static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1537#ifdef CONFIG_CPU_S5P6450
1538 {
1539 .base = S5P64X0_GPF_BASE,
1540 .config = &samsung_gpio_cfgs[6],
1541 .chip = {
1542 .base = S5P6450_GPF(0),
1543 .ngpio = S5P6450_GPIO_F_NR,
1544 .label = "GPF",
1545 },
1546 }, {
1547 .base = S5P64X0_GPI_BASE,
1548 .config = &samsung_gpio_cfgs[4],
1549 .chip = {
1550 .base = S5P6450_GPI(0),
1551 .ngpio = S5P6450_GPIO_I_NR,
1552 .label = "GPI",
1553 },
1554 }, {
1555 .base = S5P64X0_GPJ_BASE,
1556 .config = &samsung_gpio_cfgs[4],
1557 .chip = {
1558 .base = S5P6450_GPJ(0),
1559 .ngpio = S5P6450_GPIO_J_NR,
1560 .label = "GPJ",
1561 },
1562 }, {
1563 .base = S5P64X0_GPN_BASE,
1564 .config = &samsung_gpio_cfgs[5],
1565 .chip = {
1566 .base = S5P6450_GPN(0),
1567 .ngpio = S5P6450_GPIO_N_NR,
1568 .label = "GPN",
1569 },
1570 }, {
1571 .base = S5P64X0_GPP_BASE,
1572 .config = &samsung_gpio_cfgs[6],
1573 .chip = {
1574 .base = S5P6450_GPP(0),
1575 .ngpio = S5P6450_GPIO_P_NR,
1576 .label = "GPP",
1577 },
1578 }, {
1579 .base = S5P6450_GPQ_BASE,
1580 .config = &samsung_gpio_cfgs[5],
1581 .chip = {
1582 .base = S5P6450_GPQ(0),
1583 .ngpio = S5P6450_GPIO_Q_NR,
1584 .label = "GPQ",
1585 },
1586 }, {
1587 .base = S5P6450_GPS_BASE,
1588 .config = &samsung_gpio_cfgs[6],
1589 .chip = {
1590 .base = S5P6450_GPS(0),
1591 .ngpio = S5P6450_GPIO_S_NR,
1592 .label = "GPS",
1593 },
1594 },
1595#endif
1596};
1597
1598/*
1599 * S5PC100 GPIO bank summary:
1600 *
1601 * Bank GPIOs Style INT Type
1602 * A0 8 4Bit GPIO_INT0
1603 * A1 5 4Bit GPIO_INT1
1604 * B 8 4Bit GPIO_INT2
1605 * C 5 4Bit GPIO_INT3
1606 * D 7 4Bit GPIO_INT4
1607 * E0 8 4Bit GPIO_INT5
1608 * E1 6 4Bit GPIO_INT6
1609 * F0 8 4Bit GPIO_INT7
1610 * F1 8 4Bit GPIO_INT8
1611 * F2 8 4Bit GPIO_INT9
1612 * F3 4 4Bit GPIO_INT10
1613 * G0 8 4Bit GPIO_INT11
1614 * G1 3 4Bit GPIO_INT12
1615 * G2 7 4Bit GPIO_INT13
1616 * G3 7 4Bit GPIO_INT14
1617 * H0 8 4Bit WKUP_INT
1618 * H1 8 4Bit WKUP_INT
1619 * H2 8 4Bit WKUP_INT
1620 * H3 8 4Bit WKUP_INT
1621 * I 8 4Bit GPIO_INT15
1622 * J0 8 4Bit GPIO_INT16
1623 * J1 5 4Bit GPIO_INT17
1624 * J2 8 4Bit GPIO_INT18
1625 * J3 8 4Bit GPIO_INT19
1626 * J4 4 4Bit GPIO_INT20
1627 * K0 8 4Bit None
1628 * K1 6 4Bit None
1629 * K2 8 4Bit None
1630 * K3 8 4Bit None
1631 * L0 8 4Bit None
1632 * L1 8 4Bit None
1633 * L2 8 4Bit None
1634 * L3 8 4Bit None
1635 */
1636
1637static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1638#ifdef CONFIG_CPU_S5PC100
1639 {
1640 .chip = {
1641 .base = S5PC100_GPA0(0),
1642 .ngpio = S5PC100_GPIO_A0_NR,
1643 .label = "GPA0",
1644 },
1645 }, {
1646 .chip = {
1647 .base = S5PC100_GPA1(0),
1648 .ngpio = S5PC100_GPIO_A1_NR,
1649 .label = "GPA1",
1650 },
1651 }, {
1652 .chip = {
1653 .base = S5PC100_GPB(0),
1654 .ngpio = S5PC100_GPIO_B_NR,
1655 .label = "GPB",
1656 },
1657 }, {
1658 .chip = {
1659 .base = S5PC100_GPC(0),
1660 .ngpio = S5PC100_GPIO_C_NR,
1661 .label = "GPC",
1662 },
1663 }, {
1664 .chip = {
1665 .base = S5PC100_GPD(0),
1666 .ngpio = S5PC100_GPIO_D_NR,
1667 .label = "GPD",
1668 },
1669 }, {
1670 .chip = {
1671 .base = S5PC100_GPE0(0),
1672 .ngpio = S5PC100_GPIO_E0_NR,
1673 .label = "GPE0",
1674 },
1675 }, {
1676 .chip = {
1677 .base = S5PC100_GPE1(0),
1678 .ngpio = S5PC100_GPIO_E1_NR,
1679 .label = "GPE1",
1680 },
1681 }, {
1682 .chip = {
1683 .base = S5PC100_GPF0(0),
1684 .ngpio = S5PC100_GPIO_F0_NR,
1685 .label = "GPF0",
1686 },
1687 }, {
1688 .chip = {
1689 .base = S5PC100_GPF1(0),
1690 .ngpio = S5PC100_GPIO_F1_NR,
1691 .label = "GPF1",
1692 },
1693 }, {
1694 .chip = {
1695 .base = S5PC100_GPF2(0),
1696 .ngpio = S5PC100_GPIO_F2_NR,
1697 .label = "GPF2",
1698 },
1699 }, {
1700 .chip = {
1701 .base = S5PC100_GPF3(0),
1702 .ngpio = S5PC100_GPIO_F3_NR,
1703 .label = "GPF3",
1704 },
1705 }, {
1706 .chip = {
1707 .base = S5PC100_GPG0(0),
1708 .ngpio = S5PC100_GPIO_G0_NR,
1709 .label = "GPG0",
1710 },
1711 }, {
1712 .chip = {
1713 .base = S5PC100_GPG1(0),
1714 .ngpio = S5PC100_GPIO_G1_NR,
1715 .label = "GPG1",
1716 },
1717 }, {
1718 .chip = {
1719 .base = S5PC100_GPG2(0),
1720 .ngpio = S5PC100_GPIO_G2_NR,
1721 .label = "GPG2",
1722 },
1723 }, {
1724 .chip = {
1725 .base = S5PC100_GPG3(0),
1726 .ngpio = S5PC100_GPIO_G3_NR,
1727 .label = "GPG3",
1728 },
1729 }, {
1730 .chip = {
1731 .base = S5PC100_GPI(0),
1732 .ngpio = S5PC100_GPIO_I_NR,
1733 .label = "GPI",
1734 },
1735 }, {
1736 .chip = {
1737 .base = S5PC100_GPJ0(0),
1738 .ngpio = S5PC100_GPIO_J0_NR,
1739 .label = "GPJ0",
1740 },
1741 }, {
1742 .chip = {
1743 .base = S5PC100_GPJ1(0),
1744 .ngpio = S5PC100_GPIO_J1_NR,
1745 .label = "GPJ1",
1746 },
1747 }, {
1748 .chip = {
1749 .base = S5PC100_GPJ2(0),
1750 .ngpio = S5PC100_GPIO_J2_NR,
1751 .label = "GPJ2",
1752 },
1753 }, {
1754 .chip = {
1755 .base = S5PC100_GPJ3(0),
1756 .ngpio = S5PC100_GPIO_J3_NR,
1757 .label = "GPJ3",
1758 },
1759 }, {
1760 .chip = {
1761 .base = S5PC100_GPJ4(0),
1762 .ngpio = S5PC100_GPIO_J4_NR,
1763 .label = "GPJ4",
1764 },
1765 }, {
1766 .chip = {
1767 .base = S5PC100_GPK0(0),
1768 .ngpio = S5PC100_GPIO_K0_NR,
1769 .label = "GPK0",
1770 },
1771 }, {
1772 .chip = {
1773 .base = S5PC100_GPK1(0),
1774 .ngpio = S5PC100_GPIO_K1_NR,
1775 .label = "GPK1",
1776 },
1777 }, {
1778 .chip = {
1779 .base = S5PC100_GPK2(0),
1780 .ngpio = S5PC100_GPIO_K2_NR,
1781 .label = "GPK2",
1782 },
1783 }, {
1784 .chip = {
1785 .base = S5PC100_GPK3(0),
1786 .ngpio = S5PC100_GPIO_K3_NR,
1787 .label = "GPK3",
1788 },
1789 }, {
1790 .chip = {
1791 .base = S5PC100_GPL0(0),
1792 .ngpio = S5PC100_GPIO_L0_NR,
1793 .label = "GPL0",
1794 },
1795 }, {
1796 .chip = {
1797 .base = S5PC100_GPL1(0),
1798 .ngpio = S5PC100_GPIO_L1_NR,
1799 .label = "GPL1",
1800 },
1801 }, {
1802 .chip = {
1803 .base = S5PC100_GPL2(0),
1804 .ngpio = S5PC100_GPIO_L2_NR,
1805 .label = "GPL2",
1806 },
1807 }, {
1808 .chip = {
1809 .base = S5PC100_GPL3(0),
1810 .ngpio = S5PC100_GPIO_L3_NR,
1811 .label = "GPL3",
1812 },
1813 }, {
1814 .chip = {
1815 .base = S5PC100_GPL4(0),
1816 .ngpio = S5PC100_GPIO_L4_NR,
1817 .label = "GPL4",
1818 },
1819 }, {
1820 .base = (S5P_VA_GPIO + 0xC00),
1821 .irq_base = IRQ_EINT(0),
1822 .chip = {
1823 .base = S5PC100_GPH0(0),
1824 .ngpio = S5PC100_GPIO_H0_NR,
1825 .label = "GPH0",
1826 .to_irq = samsung_gpiolib_to_irq,
1827 },
1828 }, {
1829 .base = (S5P_VA_GPIO + 0xC20),
1830 .irq_base = IRQ_EINT(8),
1831 .chip = {
1832 .base = S5PC100_GPH1(0),
1833 .ngpio = S5PC100_GPIO_H1_NR,
1834 .label = "GPH1",
1835 .to_irq = samsung_gpiolib_to_irq,
1836 },
1837 }, {
1838 .base = (S5P_VA_GPIO + 0xC40),
1839 .irq_base = IRQ_EINT(16),
1840 .chip = {
1841 .base = S5PC100_GPH2(0),
1842 .ngpio = S5PC100_GPIO_H2_NR,
1843 .label = "GPH2",
1844 .to_irq = samsung_gpiolib_to_irq,
1845 },
1846 }, {
1847 .base = (S5P_VA_GPIO + 0xC60),
1848 .irq_base = IRQ_EINT(24),
1849 .chip = {
1850 .base = S5PC100_GPH3(0),
1851 .ngpio = S5PC100_GPIO_H3_NR,
1852 .label = "GPH3",
1853 .to_irq = samsung_gpiolib_to_irq,
1854 },
1855 },
1856#endif
1857};
1858
1859/*
1860 * Followings are the gpio banks in S5PV210/S5PC110
1861 *
1862 * The 'config' member when left to NULL, is initialized to the default
1863 * structure samsung_gpio_cfgs[4] in the init function below.
1864 *
1865 * The 'base' member is also initialized in the init function below.
1866 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1867 * uses the above macro and depends on the banks being listed in order here.
1868 */
1869
1870static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1871#ifdef CONFIG_CPU_S5PV210
1872 {
1873 .chip = {
1874 .base = S5PV210_GPA0(0),
1875 .ngpio = S5PV210_GPIO_A0_NR,
1876 .label = "GPA0",
1877 },
1878 }, {
1879 .chip = {
1880 .base = S5PV210_GPA1(0),
1881 .ngpio = S5PV210_GPIO_A1_NR,
1882 .label = "GPA1",
1883 },
1884 }, {
1885 .chip = {
1886 .base = S5PV210_GPB(0),
1887 .ngpio = S5PV210_GPIO_B_NR,
1888 .label = "GPB",
1889 },
1890 }, {
1891 .chip = {
1892 .base = S5PV210_GPC0(0),
1893 .ngpio = S5PV210_GPIO_C0_NR,
1894 .label = "GPC0",
1895 },
1896 }, {
1897 .chip = {
1898 .base = S5PV210_GPC1(0),
1899 .ngpio = S5PV210_GPIO_C1_NR,
1900 .label = "GPC1",
1901 },
1902 }, {
1903 .chip = {
1904 .base = S5PV210_GPD0(0),
1905 .ngpio = S5PV210_GPIO_D0_NR,
1906 .label = "GPD0",
1907 },
1908 }, {
1909 .chip = {
1910 .base = S5PV210_GPD1(0),
1911 .ngpio = S5PV210_GPIO_D1_NR,
1912 .label = "GPD1",
1913 },
1914 }, {
1915 .chip = {
1916 .base = S5PV210_GPE0(0),
1917 .ngpio = S5PV210_GPIO_E0_NR,
1918 .label = "GPE0",
1919 },
1920 }, {
1921 .chip = {
1922 .base = S5PV210_GPE1(0),
1923 .ngpio = S5PV210_GPIO_E1_NR,
1924 .label = "GPE1",
1925 },
1926 }, {
1927 .chip = {
1928 .base = S5PV210_GPF0(0),
1929 .ngpio = S5PV210_GPIO_F0_NR,
1930 .label = "GPF0",
1931 },
1932 }, {
1933 .chip = {
1934 .base = S5PV210_GPF1(0),
1935 .ngpio = S5PV210_GPIO_F1_NR,
1936 .label = "GPF1",
1937 },
1938 }, {
1939 .chip = {
1940 .base = S5PV210_GPF2(0),
1941 .ngpio = S5PV210_GPIO_F2_NR,
1942 .label = "GPF2",
1943 },
1944 }, {
1945 .chip = {
1946 .base = S5PV210_GPF3(0),
1947 .ngpio = S5PV210_GPIO_F3_NR,
1948 .label = "GPF3",
1949 },
1950 }, {
1951 .chip = {
1952 .base = S5PV210_GPG0(0),
1953 .ngpio = S5PV210_GPIO_G0_NR,
1954 .label = "GPG0",
1955 },
1956 }, {
1957 .chip = {
1958 .base = S5PV210_GPG1(0),
1959 .ngpio = S5PV210_GPIO_G1_NR,
1960 .label = "GPG1",
1961 },
1962 }, {
1963 .chip = {
1964 .base = S5PV210_GPG2(0),
1965 .ngpio = S5PV210_GPIO_G2_NR,
1966 .label = "GPG2",
1967 },
1968 }, {
1969 .chip = {
1970 .base = S5PV210_GPG3(0),
1971 .ngpio = S5PV210_GPIO_G3_NR,
1972 .label = "GPG3",
1973 },
1974 }, {
1975 .chip = {
1976 .base = S5PV210_GPI(0),
1977 .ngpio = S5PV210_GPIO_I_NR,
1978 .label = "GPI",
1979 },
1980 }, {
1981 .chip = {
1982 .base = S5PV210_GPJ0(0),
1983 .ngpio = S5PV210_GPIO_J0_NR,
1984 .label = "GPJ0",
1985 },
1986 }, {
1987 .chip = {
1988 .base = S5PV210_GPJ1(0),
1989 .ngpio = S5PV210_GPIO_J1_NR,
1990 .label = "GPJ1",
1991 },
1992 }, {
1993 .chip = {
1994 .base = S5PV210_GPJ2(0),
1995 .ngpio = S5PV210_GPIO_J2_NR,
1996 .label = "GPJ2",
1997 },
1998 }, {
1999 .chip = {
2000 .base = S5PV210_GPJ3(0),
2001 .ngpio = S5PV210_GPIO_J3_NR,
2002 .label = "GPJ3",
2003 },
2004 }, {
2005 .chip = {
2006 .base = S5PV210_GPJ4(0),
2007 .ngpio = S5PV210_GPIO_J4_NR,
2008 .label = "GPJ4",
2009 },
2010 }, {
2011 .chip = {
2012 .base = S5PV210_MP01(0),
2013 .ngpio = S5PV210_GPIO_MP01_NR,
2014 .label = "MP01",
2015 },
2016 }, {
2017 .chip = {
2018 .base = S5PV210_MP02(0),
2019 .ngpio = S5PV210_GPIO_MP02_NR,
2020 .label = "MP02",
2021 },
2022 }, {
2023 .chip = {
2024 .base = S5PV210_MP03(0),
2025 .ngpio = S5PV210_GPIO_MP03_NR,
2026 .label = "MP03",
2027 },
2028 }, {
2029 .chip = {
2030 .base = S5PV210_MP04(0),
2031 .ngpio = S5PV210_GPIO_MP04_NR,
2032 .label = "MP04",
2033 },
2034 }, {
2035 .chip = {
2036 .base = S5PV210_MP05(0),
2037 .ngpio = S5PV210_GPIO_MP05_NR,
2038 .label = "MP05",
2039 },
2040 }, {
2041 .base = (S5P_VA_GPIO + 0xC00),
2042 .irq_base = IRQ_EINT(0),
2043 .chip = {
2044 .base = S5PV210_GPH0(0),
2045 .ngpio = S5PV210_GPIO_H0_NR,
2046 .label = "GPH0",
2047 .to_irq = samsung_gpiolib_to_irq,
2048 },
2049 }, {
2050 .base = (S5P_VA_GPIO + 0xC20),
2051 .irq_base = IRQ_EINT(8),
2052 .chip = {
2053 .base = S5PV210_GPH1(0),
2054 .ngpio = S5PV210_GPIO_H1_NR,
2055 .label = "GPH1",
2056 .to_irq = samsung_gpiolib_to_irq,
2057 },
2058 }, {
2059 .base = (S5P_VA_GPIO + 0xC40),
2060 .irq_base = IRQ_EINT(16),
2061 .chip = {
2062 .base = S5PV210_GPH2(0),
2063 .ngpio = S5PV210_GPIO_H2_NR,
2064 .label = "GPH2",
2065 .to_irq = samsung_gpiolib_to_irq,
2066 },
2067 }, {
2068 .base = (S5P_VA_GPIO + 0xC60),
2069 .irq_base = IRQ_EINT(24),
2070 .chip = {
2071 .base = S5PV210_GPH3(0),
2072 .ngpio = S5PV210_GPIO_H3_NR,
2073 .label = "GPH3",
2074 .to_irq = samsung_gpiolib_to_irq,
2075 },
2076 },
2077#endif
2078};
2079
2080/*
2081 * Followings are the gpio banks in EXYNOS4210
2082 *
2083 * The 'config' member when left to NULL, is initialized to the default
2084 * structure samsung_gpio_cfgs[4] in the init function below.
2085 *
2086 * The 'base' member is also initialized in the init function below.
2087 * Note: The initialization of 'base' member of samsung_gpio_chip structure
2088 * uses the above macro and depends on the banks being listed in order here.
2089 */
2090
2091static struct samsung_gpio_chip exynos4_gpios_1[] = {
2092#ifdef CONFIG_ARCH_EXYNOS4
2093 {
2094 .chip = {
2095 .base = EXYNOS4_GPA0(0),
2096 .ngpio = EXYNOS4_GPIO_A0_NR,
2097 .label = "GPA0",
2098 },
2099 }, {
2100 .chip = {
2101 .base = EXYNOS4_GPA1(0),
2102 .ngpio = EXYNOS4_GPIO_A1_NR,
2103 .label = "GPA1",
2104 },
2105 }, {
2106 .chip = {
2107 .base = EXYNOS4_GPB(0),
2108 .ngpio = EXYNOS4_GPIO_B_NR,
2109 .label = "GPB",
2110 },
2111 }, {
2112 .chip = {
2113 .base = EXYNOS4_GPC0(0),
2114 .ngpio = EXYNOS4_GPIO_C0_NR,
2115 .label = "GPC0",
2116 },
2117 }, {
2118 .chip = {
2119 .base = EXYNOS4_GPC1(0),
2120 .ngpio = EXYNOS4_GPIO_C1_NR,
2121 .label = "GPC1",
2122 },
2123 }, {
2124 .chip = {
2125 .base = EXYNOS4_GPD0(0),
2126 .ngpio = EXYNOS4_GPIO_D0_NR,
2127 .label = "GPD0",
2128 },
2129 }, {
2130 .chip = {
2131 .base = EXYNOS4_GPD1(0),
2132 .ngpio = EXYNOS4_GPIO_D1_NR,
2133 .label = "GPD1",
2134 },
2135 }, {
2136 .chip = {
2137 .base = EXYNOS4_GPE0(0),
2138 .ngpio = EXYNOS4_GPIO_E0_NR,
2139 .label = "GPE0",
2140 },
2141 }, {
2142 .chip = {
2143 .base = EXYNOS4_GPE1(0),
2144 .ngpio = EXYNOS4_GPIO_E1_NR,
2145 .label = "GPE1",
2146 },
2147 }, {
2148 .chip = {
2149 .base = EXYNOS4_GPE2(0),
2150 .ngpio = EXYNOS4_GPIO_E2_NR,
2151 .label = "GPE2",
2152 },
2153 }, {
2154 .chip = {
2155 .base = EXYNOS4_GPE3(0),
2156 .ngpio = EXYNOS4_GPIO_E3_NR,
2157 .label = "GPE3",
2158 },
2159 }, {
2160 .chip = {
2161 .base = EXYNOS4_GPE4(0),
2162 .ngpio = EXYNOS4_GPIO_E4_NR,
2163 .label = "GPE4",
2164 },
2165 }, {
2166 .chip = {
2167 .base = EXYNOS4_GPF0(0),
2168 .ngpio = EXYNOS4_GPIO_F0_NR,
2169 .label = "GPF0",
2170 },
2171 }, {
2172 .chip = {
2173 .base = EXYNOS4_GPF1(0),
2174 .ngpio = EXYNOS4_GPIO_F1_NR,
2175 .label = "GPF1",
2176 },
2177 }, {
2178 .chip = {
2179 .base = EXYNOS4_GPF2(0),
2180 .ngpio = EXYNOS4_GPIO_F2_NR,
2181 .label = "GPF2",
2182 },
2183 }, {
2184 .chip = {
2185 .base = EXYNOS4_GPF3(0),
2186 .ngpio = EXYNOS4_GPIO_F3_NR,
2187 .label = "GPF3",
2188 },
2189 },
2190#endif
2191};
2192
2193static struct samsung_gpio_chip exynos4_gpios_2[] = {
2194#ifdef CONFIG_ARCH_EXYNOS4
2195 {
2196 .chip = {
2197 .base = EXYNOS4_GPJ0(0),
2198 .ngpio = EXYNOS4_GPIO_J0_NR,
2199 .label = "GPJ0",
2200 },
2201 }, {
2202 .chip = {
2203 .base = EXYNOS4_GPJ1(0),
2204 .ngpio = EXYNOS4_GPIO_J1_NR,
2205 .label = "GPJ1",
2206 },
2207 }, {
2208 .chip = {
2209 .base = EXYNOS4_GPK0(0),
2210 .ngpio = EXYNOS4_GPIO_K0_NR,
2211 .label = "GPK0",
2212 },
2213 }, {
2214 .chip = {
2215 .base = EXYNOS4_GPK1(0),
2216 .ngpio = EXYNOS4_GPIO_K1_NR,
2217 .label = "GPK1",
2218 },
2219 }, {
2220 .chip = {
2221 .base = EXYNOS4_GPK2(0),
2222 .ngpio = EXYNOS4_GPIO_K2_NR,
2223 .label = "GPK2",
2224 },
2225 }, {
2226 .chip = {
2227 .base = EXYNOS4_GPK3(0),
2228 .ngpio = EXYNOS4_GPIO_K3_NR,
2229 .label = "GPK3",
2230 },
2231 }, {
2232 .chip = {
2233 .base = EXYNOS4_GPL0(0),
2234 .ngpio = EXYNOS4_GPIO_L0_NR,
2235 .label = "GPL0",
2236 },
2237 }, {
2238 .chip = {
2239 .base = EXYNOS4_GPL1(0),
2240 .ngpio = EXYNOS4_GPIO_L1_NR,
2241 .label = "GPL1",
2242 },
2243 }, {
2244 .chip = {
2245 .base = EXYNOS4_GPL2(0),
2246 .ngpio = EXYNOS4_GPIO_L2_NR,
2247 .label = "GPL2",
2248 },
2249 }, {
2250 .config = &samsung_gpio_cfgs[4],
2251 .chip = {
2252 .base = EXYNOS4_GPY0(0),
2253 .ngpio = EXYNOS4_GPIO_Y0_NR,
2254 .label = "GPY0",
2255 },
2256 }, {
2257 .config = &samsung_gpio_cfgs[4],
2258 .chip = {
2259 .base = EXYNOS4_GPY1(0),
2260 .ngpio = EXYNOS4_GPIO_Y1_NR,
2261 .label = "GPY1",
2262 },
2263 }, {
2264 .config = &samsung_gpio_cfgs[4],
2265 .chip = {
2266 .base = EXYNOS4_GPY2(0),
2267 .ngpio = EXYNOS4_GPIO_Y2_NR,
2268 .label = "GPY2",
2269 },
2270 }, {
2271 .config = &samsung_gpio_cfgs[4],
2272 .chip = {
2273 .base = EXYNOS4_GPY3(0),
2274 .ngpio = EXYNOS4_GPIO_Y3_NR,
2275 .label = "GPY3",
2276 },
2277 }, {
2278 .config = &samsung_gpio_cfgs[4],
2279 .chip = {
2280 .base = EXYNOS4_GPY4(0),
2281 .ngpio = EXYNOS4_GPIO_Y4_NR,
2282 .label = "GPY4",
2283 },
2284 }, {
2285 .config = &samsung_gpio_cfgs[4],
2286 .chip = {
2287 .base = EXYNOS4_GPY5(0),
2288 .ngpio = EXYNOS4_GPIO_Y5_NR,
2289 .label = "GPY5",
2290 },
2291 }, {
2292 .config = &samsung_gpio_cfgs[4],
2293 .chip = {
2294 .base = EXYNOS4_GPY6(0),
2295 .ngpio = EXYNOS4_GPIO_Y6_NR,
2296 .label = "GPY6",
2297 },
2298 }, {
2299 .base = (S5P_VA_GPIO2 + 0xC00),
2300 .config = &samsung_gpio_cfgs[4],
2301 .irq_base = IRQ_EINT(0),
2302 .chip = {
2303 .base = EXYNOS4_GPX0(0),
2304 .ngpio = EXYNOS4_GPIO_X0_NR,
2305 .label = "GPX0",
2306 .to_irq = samsung_gpiolib_to_irq,
2307 },
2308 }, {
2309 .base = (S5P_VA_GPIO2 + 0xC20),
2310 .config = &samsung_gpio_cfgs[4],
2311 .irq_base = IRQ_EINT(8),
2312 .chip = {
2313 .base = EXYNOS4_GPX1(0),
2314 .ngpio = EXYNOS4_GPIO_X1_NR,
2315 .label = "GPX1",
2316 .to_irq = samsung_gpiolib_to_irq,
2317 },
2318 }, {
2319 .base = (S5P_VA_GPIO2 + 0xC40),
2320 .config = &samsung_gpio_cfgs[4],
2321 .irq_base = IRQ_EINT(16),
2322 .chip = {
2323 .base = EXYNOS4_GPX2(0),
2324 .ngpio = EXYNOS4_GPIO_X2_NR,
2325 .label = "GPX2",
2326 .to_irq = samsung_gpiolib_to_irq,
2327 },
2328 }, {
2329 .base = (S5P_VA_GPIO2 + 0xC60),
2330 .config = &samsung_gpio_cfgs[4],
2331 .irq_base = IRQ_EINT(24),
2332 .chip = {
2333 .base = EXYNOS4_GPX3(0),
2334 .ngpio = EXYNOS4_GPIO_X3_NR,
2335 .label = "GPX3",
2336 .to_irq = samsung_gpiolib_to_irq,
2337 },
2338 },
2339#endif
2340};
2341
2342static struct samsung_gpio_chip exynos4_gpios_3[] = {
2343#ifdef CONFIG_ARCH_EXYNOS4
2344 {
2345 .chip = {
2346 .base = EXYNOS4_GPZ(0),
2347 .ngpio = EXYNOS4_GPIO_Z_NR,
2348 .label = "GPZ",
2349 },
2350 },
2351#endif
2352};
2353
2354/* TODO: cleanup soc_is_* */
2355static __init int samsung_gpiolib_init(void)
2356{
2357 struct samsung_gpio_chip *chip;
2358 int i, nr_chips;
2359 int group = 0;
2360
2361 samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2362
2363 if (soc_is_s3c24xx()) {
2364 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2365 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2366 } else if (soc_is_s3c64xx()) {
2367 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2368 ARRAY_SIZE(s3c64xx_gpios_2bit),
2369 S3C64XX_VA_GPIO + 0xE0, 0x20);
2370 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2371 ARRAY_SIZE(s3c64xx_gpios_4bit),
2372 S3C64XX_VA_GPIO);
2373 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2374 ARRAY_SIZE(s3c64xx_gpios_4bit2));
2375 } else if (soc_is_s5p6440()) {
2376 samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2377 ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2378 samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2379 ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2380 samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2381 ARRAY_SIZE(s5p6440_gpios_4bit2));
2382 s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2383 ARRAY_SIZE(s5p6440_gpios_rbank));
2384 } else if (soc_is_s5p6450()) {
2385 samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2386 ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2387 samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2388 ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2389 samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2390 ARRAY_SIZE(s5p6450_gpios_4bit2));
2391 s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2392 ARRAY_SIZE(s5p6450_gpios_rbank));
2393 } else if (soc_is_s5pc100()) {
2394 group = 0;
2395 chip = s5pc100_gpios_4bit;
2396 nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2397
2398 for (i = 0; i < nr_chips; i++, chip++) {
2399 if (!chip->config) {
2400 chip->config = &samsung_gpio_cfgs[4];
2401 chip->group = group++;
2402 }
2403 }
2404 samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2405#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2406 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2407#endif
2408 } else if (soc_is_s5pv210()) {
2409 group = 0;
2410 chip = s5pv210_gpios_4bit;
2411 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2412
2413 for (i = 0; i < nr_chips; i++, chip++) {
2414 if (!chip->config) {
2415 chip->config = &samsung_gpio_cfgs[4];
2416 chip->group = group++;
2417 }
2418 }
2419 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2420#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2421 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2422#endif
2423 } else if (soc_is_exynos4210()) {
2424 group = 0;
2425
2426 /* gpio part1 */
2427 chip = exynos4_gpios_1;
2428 nr_chips = ARRAY_SIZE(exynos4_gpios_1);
2429
2430 for (i = 0; i < nr_chips; i++, chip++) {
2431 if (!chip->config) {
2432 chip->config = &exynos4_gpio_cfg;
2433 chip->group = group++;
2434 }
2435 }
2436 samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
2437
2438 /* gpio part2 */
2439 chip = exynos4_gpios_2;
2440 nr_chips = ARRAY_SIZE(exynos4_gpios_2);
2441
2442 for (i = 0; i < nr_chips; i++, chip++) {
2443 if (!chip->config) {
2444 chip->config = &exynos4_gpio_cfg;
2445 chip->group = group++;
2446 }
2447 }
2448 samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
2449
2450 /* gpio part3 */
2451 chip = exynos4_gpios_3;
2452 nr_chips = ARRAY_SIZE(exynos4_gpios_3);
2453
2454 for (i = 0; i < nr_chips; i++, chip++) {
2455 if (!chip->config) {
2456 chip->config = &exynos4_gpio_cfg;
2457 chip->group = group++;
2458 }
2459 }
2460 samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
2461
2462#if defined(CONFIG_SOC_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
2463 s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
2464 s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
2465#endif
2466 }
2467
2468 return 0;
2469}
2470core_initcall(samsung_gpiolib_init);
2471
2472int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2473{
2474 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2475 unsigned long flags;
2476 int offset;
2477 int ret;
2478
2479 if (!chip)
2480 return -EINVAL;
2481
2482 offset = pin - chip->chip.base;
2483
2484 samsung_gpio_lock(chip, flags);
2485 ret = samsung_gpio_do_setcfg(chip, offset, config);
2486 samsung_gpio_unlock(chip, flags);
2487
2488 return ret;
2489}
2490EXPORT_SYMBOL(s3c_gpio_cfgpin);
2491
2492int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2493 unsigned int cfg)
2494{
2495 int ret;
2496
2497 for (; nr > 0; nr--, start++) {
2498 ret = s3c_gpio_cfgpin(start, cfg);
2499 if (ret != 0)
2500 return ret;
2501 }
2502
2503 return 0;
2504}
2505EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2506
2507int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2508 unsigned int cfg, samsung_gpio_pull_t pull)
2509{
2510 int ret;
2511
2512 for (; nr > 0; nr--, start++) {
2513 s3c_gpio_setpull(start, pull);
2514 ret = s3c_gpio_cfgpin(start, cfg);
2515 if (ret != 0)
2516 return ret;
2517 }
2518
2519 return 0;
2520}
2521EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2522
2523unsigned s3c_gpio_getcfg(unsigned int pin)
2524{
2525 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2526 unsigned long flags;
2527 unsigned ret = 0;
2528 int offset;
2529
2530 if (chip) {
2531 offset = pin - chip->chip.base;
2532
2533 samsung_gpio_lock(chip, flags);
2534 ret = samsung_gpio_do_getcfg(chip, offset);
2535 samsung_gpio_unlock(chip, flags);
2536 }
2537
2538 return ret;
2539}
2540EXPORT_SYMBOL(s3c_gpio_getcfg);
2541
2542int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2543{
2544 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2545 unsigned long flags;
2546 int offset, ret;
2547
2548 if (!chip)
2549 return -EINVAL;
2550
2551 offset = pin - chip->chip.base;
2552
2553 samsung_gpio_lock(chip, flags);
2554 ret = samsung_gpio_do_setpull(chip, offset, pull);
2555 samsung_gpio_unlock(chip, flags);
2556
2557 return ret;
2558}
2559EXPORT_SYMBOL(s3c_gpio_setpull);
2560
2561samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2562{
2563 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2564 unsigned long flags;
2565 int offset;
2566 u32 pup = 0;
2567
2568 if (chip) {
2569 offset = pin - chip->chip.base;
2570
2571 samsung_gpio_lock(chip, flags);
2572 pup = samsung_gpio_do_getpull(chip, offset);
2573 samsung_gpio_unlock(chip, flags);
2574 }
2575
2576 return (__force samsung_gpio_pull_t)pup;
2577}
2578EXPORT_SYMBOL(s3c_gpio_getpull);
2579
2580/* gpiolib wrappers until these are totally eliminated */
2581
2582void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
2583{
2584 int ret;
2585
2586 WARN_ON(to); /* should be none of these left */
2587
2588 if (!to) {
2589 /* if pull is enabled, try first with up, and if that
2590 * fails, try using down */
2591
2592 ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
2593 if (ret)
2594 s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
2595 } else {
2596 s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
2597 }
2598}
2599EXPORT_SYMBOL(s3c2410_gpio_pullup);
2600
2601void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
2602{
2603 /* do this via gpiolib until all users removed */
2604
2605 gpio_request(pin, "temporary");
2606 gpio_set_value(pin, to);
2607 gpio_free(pin);
2608}
2609EXPORT_SYMBOL(s3c2410_gpio_setpin);
2610
2611unsigned int s3c2410_gpio_getpin(unsigned int pin)
2612{
2613 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2614 unsigned long offs = pin - chip->chip.base;
2615
2616 return __raw_readl(chip->base + 0x04) & (1 << offs);
2617}
2618EXPORT_SYMBOL(s3c2410_gpio_getpin);
2619
2620#ifdef CONFIG_S5P_GPIO_DRVSTR
2621s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2622{
2623 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2624 unsigned int off;
2625 void __iomem *reg;
2626 int shift;
2627 u32 drvstr;
2628
2629 if (!chip)
2630 return -EINVAL;
2631
2632 off = pin - chip->chip.base;
2633 shift = off * 2;
2634 reg = chip->base + 0x0C;
2635
2636 drvstr = __raw_readl(reg);
2637 drvstr = drvstr >> shift;
2638 drvstr &= 0x3;
2639
2640 return (__force s5p_gpio_drvstr_t)drvstr;
2641}
2642EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2643
2644int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2645{
2646 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2647 unsigned int off;
2648 void __iomem *reg;
2649 int shift;
2650 u32 tmp;
2651
2652 if (!chip)
2653 return -EINVAL;
2654
2655 off = pin - chip->chip.base;
2656 shift = off * 2;
2657 reg = chip->base + 0x0C;
2658
2659 tmp = __raw_readl(reg);
2660 tmp &= ~(0x3 << shift);
2661 tmp |= drvstr << shift;
2662
2663 __raw_writel(tmp, reg);
2664
2665 return 0;
2666}
2667EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2668#endif /* CONFIG_S5P_GPIO_DRVSTR */
2669
2670#ifdef CONFIG_PLAT_S3C24XX
2671unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2672{
2673 unsigned long flags;
2674 unsigned long misccr;
2675
2676 local_irq_save(flags);
2677 misccr = __raw_readl(S3C24XX_MISCCR);
2678 misccr &= ~clear;
2679 misccr ^= change;
2680 __raw_writel(misccr, S3C24XX_MISCCR);
2681 local_irq_restore(flags);
2682
2683 return misccr;
2684}
2685EXPORT_SYMBOL(s3c2410_modify_misccr);
2686#endif