diff options
author | Kukjin Kim <kgene.kim@samsung.com> | 2011-08-30 07:39:08 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-09-21 02:06:05 -0400 |
commit | 1b39d5f2cc5c28085bbf48db80bf704ab4dedda9 (patch) | |
tree | c75a0e8468865c3657bb2ec750a118cb4a81948b /arch/arm | |
parent | c4b3fd38dfb677d7a3997527c9cbdc21b81424a3 (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 'arch/arm')
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-samsung/gpio-config.c | 431 | ||||
-rw-r--r-- | arch/arm/plat-samsung/gpio.c | 167 |
3 files changed, 0 insertions, 600 deletions
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 853764ba8cc5..6d772d7c012b 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -15,8 +15,6 @@ obj-y += init.o | |||
15 | obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o | 15 | obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o |
16 | obj-y += clock.o | 16 | obj-y += clock.o |
17 | obj-y += pwm-clock.o | 17 | obj-y += pwm-clock.o |
18 | obj-y += gpio.o | ||
19 | obj-y += gpio-config.o | ||
20 | obj-y += dev-asocdma.o | 18 | obj-y += dev-asocdma.o |
21 | 19 | ||
22 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | 20 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c deleted file mode 100644 index 1c0b0401594b..000000000000 --- a/arch/arm/plat-samsung/gpio-config.c +++ /dev/null | |||
@@ -1,431 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio-config.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008-2010 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C series GPIO configuration core | ||
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/module.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <plat/gpio-core.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | #include <plat/gpio-cfg-helpers.h> | ||
23 | |||
24 | int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) | ||
25 | { | ||
26 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
27 | unsigned long flags; | ||
28 | int offset; | ||
29 | int ret; | ||
30 | |||
31 | if (!chip) | ||
32 | return -EINVAL; | ||
33 | |||
34 | offset = pin - chip->chip.base; | ||
35 | |||
36 | s3c_gpio_lock(chip, flags); | ||
37 | ret = s3c_gpio_do_setcfg(chip, offset, config); | ||
38 | s3c_gpio_unlock(chip, flags); | ||
39 | |||
40 | return ret; | ||
41 | } | ||
42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); | ||
43 | |||
44 | int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, | ||
45 | unsigned int cfg) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | for (; nr > 0; nr--, start++) { | ||
50 | ret = s3c_gpio_cfgpin(start, cfg); | ||
51 | if (ret != 0) | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range); | ||
58 | |||
59 | int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, | ||
60 | unsigned int cfg, s3c_gpio_pull_t pull) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | for (; nr > 0; nr--, start++) { | ||
65 | s3c_gpio_setpull(start, pull); | ||
66 | ret = s3c_gpio_cfgpin(start, cfg); | ||
67 | if (ret != 0) | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range); | ||
74 | |||
75 | unsigned s3c_gpio_getcfg(unsigned int pin) | ||
76 | { | ||
77 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
78 | unsigned long flags; | ||
79 | unsigned ret = 0; | ||
80 | int offset; | ||
81 | |||
82 | if (chip) { | ||
83 | offset = pin - chip->chip.base; | ||
84 | |||
85 | s3c_gpio_lock(chip, flags); | ||
86 | ret = s3c_gpio_do_getcfg(chip, offset); | ||
87 | s3c_gpio_unlock(chip, flags); | ||
88 | } | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | EXPORT_SYMBOL(s3c_gpio_getcfg); | ||
93 | |||
94 | |||
95 | int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | ||
96 | { | ||
97 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
98 | unsigned long flags; | ||
99 | int offset, ret; | ||
100 | |||
101 | if (!chip) | ||
102 | return -EINVAL; | ||
103 | |||
104 | offset = pin - chip->chip.base; | ||
105 | |||
106 | s3c_gpio_lock(chip, flags); | ||
107 | ret = s3c_gpio_do_setpull(chip, offset, pull); | ||
108 | s3c_gpio_unlock(chip, flags); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | EXPORT_SYMBOL(s3c_gpio_setpull); | ||
113 | |||
114 | s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin) | ||
115 | { | ||
116 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
117 | unsigned long flags; | ||
118 | int offset; | ||
119 | u32 pup = 0; | ||
120 | |||
121 | if (chip) { | ||
122 | offset = pin - chip->chip.base; | ||
123 | |||
124 | s3c_gpio_lock(chip, flags); | ||
125 | pup = s3c_gpio_do_getpull(chip, offset); | ||
126 | s3c_gpio_unlock(chip, flags); | ||
127 | } | ||
128 | |||
129 | return (__force s3c_gpio_pull_t)pup; | ||
130 | } | ||
131 | EXPORT_SYMBOL(s3c_gpio_getpull); | ||
132 | |||
133 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX | ||
134 | int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
135 | unsigned int off, unsigned int cfg) | ||
136 | { | ||
137 | void __iomem *reg = chip->base; | ||
138 | unsigned int shift = off; | ||
139 | u32 con; | ||
140 | |||
141 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
142 | cfg &= 0xf; | ||
143 | |||
144 | /* Map output to 0, and SFN2 to 1 */ | ||
145 | cfg -= 1; | ||
146 | if (cfg > 1) | ||
147 | return -EINVAL; | ||
148 | |||
149 | cfg <<= shift; | ||
150 | } | ||
151 | |||
152 | con = __raw_readl(reg); | ||
153 | con &= ~(0x1 << shift); | ||
154 | con |= cfg; | ||
155 | __raw_writel(con, reg); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
161 | unsigned int off) | ||
162 | { | ||
163 | u32 con; | ||
164 | |||
165 | con = __raw_readl(chip->base); | ||
166 | con >>= off; | ||
167 | con &= 1; | ||
168 | con++; | ||
169 | |||
170 | return S3C_GPIO_SFN(con); | ||
171 | } | ||
172 | |||
173 | int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
174 | unsigned int off, unsigned int cfg) | ||
175 | { | ||
176 | void __iomem *reg = chip->base; | ||
177 | unsigned int shift = off * 2; | ||
178 | u32 con; | ||
179 | |||
180 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
181 | cfg &= 0xf; | ||
182 | if (cfg > 3) | ||
183 | return -EINVAL; | ||
184 | |||
185 | cfg <<= shift; | ||
186 | } | ||
187 | |||
188 | con = __raw_readl(reg); | ||
189 | con &= ~(0x3 << shift); | ||
190 | con |= cfg; | ||
191 | __raw_writel(con, reg); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
197 | unsigned int off) | ||
198 | { | ||
199 | u32 con; | ||
200 | |||
201 | con = __raw_readl(chip->base); | ||
202 | con >>= off * 2; | ||
203 | con &= 3; | ||
204 | |||
205 | /* this conversion works for IN and OUT as well as special mode */ | ||
206 | return S3C_GPIO_SPECIAL(con); | ||
207 | } | ||
208 | #endif | ||
209 | |||
210 | #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX | ||
211 | int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
212 | unsigned int off, unsigned int cfg) | ||
213 | { | ||
214 | void __iomem *reg = chip->base; | ||
215 | unsigned int shift = (off & 7) * 4; | ||
216 | u32 con; | ||
217 | |||
218 | if (off < 8 && chip->chip.ngpio > 8) | ||
219 | reg -= 4; | ||
220 | |||
221 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
222 | cfg &= 0xf; | ||
223 | cfg <<= shift; | ||
224 | } | ||
225 | |||
226 | con = __raw_readl(reg); | ||
227 | con &= ~(0xf << shift); | ||
228 | con |= cfg; | ||
229 | __raw_writel(con, reg); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
235 | unsigned int off) | ||
236 | { | ||
237 | void __iomem *reg = chip->base; | ||
238 | unsigned int shift = (off & 7) * 4; | ||
239 | u32 con; | ||
240 | |||
241 | if (off < 8 && chip->chip.ngpio > 8) | ||
242 | reg -= 4; | ||
243 | |||
244 | con = __raw_readl(reg); | ||
245 | con >>= shift; | ||
246 | con &= 0xf; | ||
247 | |||
248 | /* this conversion works for IN and OUT as well as special mode */ | ||
249 | return S3C_GPIO_SPECIAL(con); | ||
250 | } | ||
251 | |||
252 | #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ | ||
253 | |||
254 | #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN | ||
255 | int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, | ||
256 | unsigned int off, s3c_gpio_pull_t pull) | ||
257 | { | ||
258 | void __iomem *reg = chip->base + 0x08; | ||
259 | int shift = off * 2; | ||
260 | u32 pup; | ||
261 | |||
262 | pup = __raw_readl(reg); | ||
263 | pup &= ~(3 << shift); | ||
264 | pup |= pull << shift; | ||
265 | __raw_writel(pup, reg); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | ||
271 | unsigned int off) | ||
272 | { | ||
273 | void __iomem *reg = chip->base + 0x08; | ||
274 | int shift = off * 2; | ||
275 | u32 pup = __raw_readl(reg); | ||
276 | |||
277 | pup >>= shift; | ||
278 | pup &= 0x3; | ||
279 | return (__force s3c_gpio_pull_t)pup; | ||
280 | } | ||
281 | |||
282 | #ifdef CONFIG_S3C_GPIO_PULL_S3C2443 | ||
283 | int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, | ||
284 | unsigned int off, s3c_gpio_pull_t pull) | ||
285 | { | ||
286 | switch (pull) { | ||
287 | case S3C_GPIO_PULL_NONE: | ||
288 | pull = 0x01; | ||
289 | break; | ||
290 | case S3C_GPIO_PULL_UP: | ||
291 | pull = 0x00; | ||
292 | break; | ||
293 | case S3C_GPIO_PULL_DOWN: | ||
294 | pull = 0x02; | ||
295 | break; | ||
296 | } | ||
297 | return s3c_gpio_setpull_updown(chip, off, pull); | ||
298 | } | ||
299 | |||
300 | s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, | ||
301 | unsigned int off) | ||
302 | { | ||
303 | s3c_gpio_pull_t pull; | ||
304 | |||
305 | pull = s3c_gpio_getpull_updown(chip, off); | ||
306 | |||
307 | switch (pull) { | ||
308 | case 0x00: | ||
309 | pull = S3C_GPIO_PULL_UP; | ||
310 | break; | ||
311 | case 0x01: | ||
312 | case 0x03: | ||
313 | pull = S3C_GPIO_PULL_NONE; | ||
314 | break; | ||
315 | case 0x02: | ||
316 | pull = S3C_GPIO_PULL_DOWN; | ||
317 | break; | ||
318 | } | ||
319 | |||
320 | return pull; | ||
321 | } | ||
322 | #endif | ||
323 | #endif | ||
324 | |||
325 | #if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN) | ||
326 | static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip, | ||
327 | unsigned int off, s3c_gpio_pull_t pull, | ||
328 | s3c_gpio_pull_t updown) | ||
329 | { | ||
330 | void __iomem *reg = chip->base + 0x08; | ||
331 | u32 pup = __raw_readl(reg); | ||
332 | |||
333 | if (pull == updown) | ||
334 | pup &= ~(1 << off); | ||
335 | else if (pull == S3C_GPIO_PULL_NONE) | ||
336 | pup |= (1 << off); | ||
337 | else | ||
338 | return -EINVAL; | ||
339 | |||
340 | __raw_writel(pup, reg); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip, | ||
345 | unsigned int off, s3c_gpio_pull_t updown) | ||
346 | { | ||
347 | void __iomem *reg = chip->base + 0x08; | ||
348 | u32 pup = __raw_readl(reg); | ||
349 | |||
350 | pup &= (1 << off); | ||
351 | return pup ? S3C_GPIO_PULL_NONE : updown; | ||
352 | } | ||
353 | #endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */ | ||
354 | |||
355 | #ifdef CONFIG_S3C_GPIO_PULL_UP | ||
356 | s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, | ||
357 | unsigned int off) | ||
358 | { | ||
359 | return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP); | ||
360 | } | ||
361 | |||
362 | int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, | ||
363 | unsigned int off, s3c_gpio_pull_t pull) | ||
364 | { | ||
365 | return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP); | ||
366 | } | ||
367 | #endif /* CONFIG_S3C_GPIO_PULL_UP */ | ||
368 | |||
369 | #ifdef CONFIG_S3C_GPIO_PULL_DOWN | ||
370 | s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip, | ||
371 | unsigned int off) | ||
372 | { | ||
373 | return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN); | ||
374 | } | ||
375 | |||
376 | int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip, | ||
377 | unsigned int off, s3c_gpio_pull_t pull) | ||
378 | { | ||
379 | return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN); | ||
380 | } | ||
381 | #endif /* CONFIG_S3C_GPIO_PULL_DOWN */ | ||
382 | |||
383 | #ifdef CONFIG_S5P_GPIO_DRVSTR | ||
384 | s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) | ||
385 | { | ||
386 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
387 | unsigned int off; | ||
388 | void __iomem *reg; | ||
389 | int shift; | ||
390 | u32 drvstr; | ||
391 | |||
392 | if (!chip) | ||
393 | return -EINVAL; | ||
394 | |||
395 | off = pin - chip->chip.base; | ||
396 | shift = off * 2; | ||
397 | reg = chip->base + 0x0C; | ||
398 | |||
399 | drvstr = __raw_readl(reg); | ||
400 | drvstr = drvstr >> shift; | ||
401 | drvstr &= 0x3; | ||
402 | |||
403 | return (__force s5p_gpio_drvstr_t)drvstr; | ||
404 | } | ||
405 | EXPORT_SYMBOL(s5p_gpio_get_drvstr); | ||
406 | |||
407 | int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) | ||
408 | { | ||
409 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
410 | unsigned int off; | ||
411 | void __iomem *reg; | ||
412 | int shift; | ||
413 | u32 tmp; | ||
414 | |||
415 | if (!chip) | ||
416 | return -EINVAL; | ||
417 | |||
418 | off = pin - chip->chip.base; | ||
419 | shift = off * 2; | ||
420 | reg = chip->base + 0x0C; | ||
421 | |||
422 | tmp = __raw_readl(reg); | ||
423 | tmp &= ~(0x3 << shift); | ||
424 | tmp |= drvstr << shift; | ||
425 | |||
426 | __raw_writel(tmp, reg); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | EXPORT_SYMBOL(s5p_gpio_set_drvstr); | ||
431 | #endif /* CONFIG_S5P_GPIO_DRVSTR */ | ||
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c deleted file mode 100644 index 7743c4b8b2fb..000000000000 --- a/arch/arm/plat-samsung/gpio.c +++ /dev/null | |||
@@ -1,167 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series GPIO core | ||
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/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include <plat/gpio-core.h> | ||
21 | |||
22 | #ifdef CONFIG_S3C_GPIO_TRACK | ||
23 | struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; | ||
24 | |||
25 | static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip) | ||
26 | { | ||
27 | unsigned int gpn; | ||
28 | int i; | ||
29 | |||
30 | gpn = chip->chip.base; | ||
31 | for (i = 0; i < chip->chip.ngpio; i++, gpn++) { | ||
32 | BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios)); | ||
33 | s3c_gpios[gpn] = chip; | ||
34 | } | ||
35 | } | ||
36 | #endif /* CONFIG_S3C_GPIO_TRACK */ | ||
37 | |||
38 | /* Default routines for controlling GPIO, based on the original S3C24XX | ||
39 | * GPIO functions which deal with the case where each gpio bank of the | ||
40 | * chip is as following: | ||
41 | * | ||
42 | * base + 0x00: Control register, 2 bits per gpio | ||
43 | * gpio n: 2 bits starting at (2*n) | ||
44 | * 00 = input, 01 = output, others mean special-function | ||
45 | * base + 0x04: Data register, 1 bit per gpio | ||
46 | * bit n: data bit n | ||
47 | */ | ||
48 | |||
49 | static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) | ||
50 | { | ||
51 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
52 | void __iomem *base = ourchip->base; | ||
53 | unsigned long flags; | ||
54 | unsigned long con; | ||
55 | |||
56 | s3c_gpio_lock(ourchip, flags); | ||
57 | |||
58 | con = __raw_readl(base + 0x00); | ||
59 | con &= ~(3 << (offset * 2)); | ||
60 | |||
61 | __raw_writel(con, base + 0x00); | ||
62 | |||
63 | s3c_gpio_unlock(ourchip, flags); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int s3c_gpiolib_output(struct gpio_chip *chip, | ||
68 | unsigned offset, int value) | ||
69 | { | ||
70 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
71 | void __iomem *base = ourchip->base; | ||
72 | unsigned long flags; | ||
73 | unsigned long dat; | ||
74 | unsigned long con; | ||
75 | |||
76 | s3c_gpio_lock(ourchip, flags); | ||
77 | |||
78 | dat = __raw_readl(base + 0x04); | ||
79 | dat &= ~(1 << offset); | ||
80 | if (value) | ||
81 | dat |= 1 << offset; | ||
82 | __raw_writel(dat, base + 0x04); | ||
83 | |||
84 | con = __raw_readl(base + 0x00); | ||
85 | con &= ~(3 << (offset * 2)); | ||
86 | con |= 1 << (offset * 2); | ||
87 | |||
88 | __raw_writel(con, base + 0x00); | ||
89 | __raw_writel(dat, base + 0x04); | ||
90 | |||
91 | s3c_gpio_unlock(ourchip, flags); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void s3c_gpiolib_set(struct gpio_chip *chip, | ||
96 | unsigned offset, int value) | ||
97 | { | ||
98 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
99 | void __iomem *base = ourchip->base; | ||
100 | unsigned long flags; | ||
101 | unsigned long dat; | ||
102 | |||
103 | s3c_gpio_lock(ourchip, flags); | ||
104 | |||
105 | dat = __raw_readl(base + 0x04); | ||
106 | dat &= ~(1 << offset); | ||
107 | if (value) | ||
108 | dat |= 1 << offset; | ||
109 | __raw_writel(dat, base + 0x04); | ||
110 | |||
111 | s3c_gpio_unlock(ourchip, flags); | ||
112 | } | ||
113 | |||
114 | static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) | ||
115 | { | ||
116 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
117 | unsigned long val; | ||
118 | |||
119 | val = __raw_readl(ourchip->base + 0x04); | ||
120 | val >>= offset; | ||
121 | val &= 1; | ||
122 | |||
123 | return val; | ||
124 | } | ||
125 | |||
126 | __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) | ||
127 | { | ||
128 | struct gpio_chip *gc = &chip->chip; | ||
129 | int ret; | ||
130 | |||
131 | BUG_ON(!chip->base); | ||
132 | BUG_ON(!gc->label); | ||
133 | BUG_ON(!gc->ngpio); | ||
134 | |||
135 | spin_lock_init(&chip->lock); | ||
136 | |||
137 | if (!gc->direction_input) | ||
138 | gc->direction_input = s3c_gpiolib_input; | ||
139 | if (!gc->direction_output) | ||
140 | gc->direction_output = s3c_gpiolib_output; | ||
141 | if (!gc->set) | ||
142 | gc->set = s3c_gpiolib_set; | ||
143 | if (!gc->get) | ||
144 | gc->get = s3c_gpiolib_get; | ||
145 | |||
146 | #ifdef CONFIG_PM | ||
147 | if (chip->pm != NULL) { | ||
148 | if (!chip->pm->save || !chip->pm->resume) | ||
149 | printk(KERN_ERR "gpio: %s has missing PM functions\n", | ||
150 | gc->label); | ||
151 | } else | ||
152 | printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); | ||
153 | #endif | ||
154 | |||
155 | /* gpiochip_add() prints own failure message on error. */ | ||
156 | ret = gpiochip_add(gc); | ||
157 | if (ret >= 0) | ||
158 | s3c_gpiolib_track(chip); | ||
159 | } | ||
160 | |||
161 | int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) | ||
162 | { | ||
163 | struct s3c_gpio_chip *s3c_chip = container_of(chip, | ||
164 | struct s3c_gpio_chip, chip); | ||
165 | |||
166 | return s3c_chip->irq_base + offset; | ||
167 | } | ||