1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
4 // http://www.samsung.com/
5 //
6 // Copyright 2008 Openmoko, Inc.
7 // Copyright 2008 Simtec Electronics
8 // Ben Dooks <ben@simtec.co.uk>
9 // http://armlinux.simtec.co.uk/
10 //
11 // Samsung - GPIOlib support
12
13 #include <linux/kernel.h>
14 #include <linux/irq.h>
15 #include <linux/io.h>
16 #include <linux/gpio.h>
17 #include <linux/init.h>
18 #include <linux/spinlock.h>
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/device.h>
22 #include <linux/ioport.h>
23 #include <linux/of.h>
24 #include <linux/slab.h>
25 #include <linux/of_address.h>
26
27 #include <asm/irq.h>
28
29 #include "irqs.h"
30 #include "map.h"
31 #include "regs-gpio.h"
32 #include "gpio-samsung.h"
33
34 #include "cpu.h"
35 #include "gpio-core.h"
36 #include "gpio-cfg.h"
37 #include "gpio-cfg-helpers.h"
38 #include "hardware-s3c24xx.h"
39 #include "pm.h"
40
samsung_gpio_setpull_updown(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)41 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
42 unsigned int off, samsung_gpio_pull_t pull)
43 {
44 void __iomem *reg = chip->base + 0x08;
45 int shift = off * 2;
46 u32 pup;
47
48 pup = __raw_readl(reg);
49 pup &= ~(3 << shift);
50 pup |= pull << shift;
51 __raw_writel(pup, reg);
52
53 return 0;
54 }
55
samsung_gpio_getpull_updown(struct samsung_gpio_chip * chip,unsigned int off)56 samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
57 unsigned int off)
58 {
59 void __iomem *reg = chip->base + 0x08;
60 int shift = off * 2;
61 u32 pup = __raw_readl(reg);
62
63 pup >>= shift;
64 pup &= 0x3;
65
66 return (__force samsung_gpio_pull_t)pup;
67 }
68
s3c2443_gpio_setpull(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)69 int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
70 unsigned int off, samsung_gpio_pull_t pull)
71 {
72 switch (pull) {
73 case S3C_GPIO_PULL_NONE:
74 pull = 0x01;
75 break;
76 case S3C_GPIO_PULL_UP:
77 pull = 0x00;
78 break;
79 case S3C_GPIO_PULL_DOWN:
80 pull = 0x02;
81 break;
82 }
83 return samsung_gpio_setpull_updown(chip, off, pull);
84 }
85
s3c2443_gpio_getpull(struct samsung_gpio_chip * chip,unsigned int off)86 samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
87 unsigned int off)
88 {
89 samsung_gpio_pull_t pull;
90
91 pull = samsung_gpio_getpull_updown(chip, off);
92
93 switch (pull) {
94 case 0x00:
95 pull = S3C_GPIO_PULL_UP;
96 break;
97 case 0x01:
98 case 0x03:
99 pull = S3C_GPIO_PULL_NONE;
100 break;
101 case 0x02:
102 pull = S3C_GPIO_PULL_DOWN;
103 break;
104 }
105
106 return pull;
107 }
108
s3c24xx_gpio_setpull_1(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull,samsung_gpio_pull_t updown)109 static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
110 unsigned int off, samsung_gpio_pull_t pull,
111 samsung_gpio_pull_t updown)
112 {
113 void __iomem *reg = chip->base + 0x08;
114 u32 pup = __raw_readl(reg);
115
116 if (pull == updown)
117 pup &= ~(1 << off);
118 else if (pull == S3C_GPIO_PULL_NONE)
119 pup |= (1 << off);
120 else
121 return -EINVAL;
122
123 __raw_writel(pup, reg);
124 return 0;
125 }
126
s3c24xx_gpio_getpull_1(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t updown)127 static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
128 unsigned int off,
129 samsung_gpio_pull_t updown)
130 {
131 void __iomem *reg = chip->base + 0x08;
132 u32 pup = __raw_readl(reg);
133
134 pup &= (1 << off);
135 return pup ? S3C_GPIO_PULL_NONE : updown;
136 }
137
s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip * chip,unsigned int off)138 samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
139 unsigned int off)
140 {
141 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
142 }
143
s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)144 int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
145 unsigned int off, samsung_gpio_pull_t pull)
146 {
147 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
148 }
149
s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip * chip,unsigned int off)150 samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
151 unsigned int off)
152 {
153 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
154 }
155
s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip * chip,unsigned int off,samsung_gpio_pull_t pull)156 int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
157 unsigned int off, samsung_gpio_pull_t pull)
158 {
159 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
160 }
161
162 /*
163 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
164 * @chip: The gpio chip that is being configured.
165 * @off: The offset for the GPIO being configured.
166 * @cfg: The configuration value to set.
167 *
168 * This helper deal with the GPIO cases where the control register
169 * has two bits of configuration per gpio, which have the following
170 * functions:
171 * 00 = input
172 * 01 = output
173 * 1x = special function
174 */
175
samsung_gpio_setcfg_2bit(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)176 static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
177 unsigned int off, unsigned int cfg)
178 {
179 void __iomem *reg = chip->base;
180 unsigned int shift = off * 2;
181 u32 con;
182
183 if (samsung_gpio_is_cfg_special(cfg)) {
184 cfg &= 0xf;
185 if (cfg > 3)
186 return -EINVAL;
187
188 cfg <<= shift;
189 }
190
191 con = __raw_readl(reg);
192 con &= ~(0x3 << shift);
193 con |= cfg;
194 __raw_writel(con, reg);
195
196 return 0;
197 }
198
199 /*
200 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
201 * @chip: The gpio chip that is being configured.
202 * @off: The offset for the GPIO being configured.
203 *
204 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
205 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
206 * S3C_GPIO_SPECIAL() macro.
207 */
208
samsung_gpio_getcfg_2bit(struct samsung_gpio_chip * chip,unsigned int off)209 static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
210 unsigned int off)
211 {
212 u32 con;
213
214 con = __raw_readl(chip->base);
215 con >>= off * 2;
216 con &= 3;
217
218 /* this conversion works for IN and OUT as well as special mode */
219 return S3C_GPIO_SPECIAL(con);
220 }
221
222 /*
223 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
224 * @chip: The gpio chip that is being configured.
225 * @off: The offset for the GPIO being configured.
226 * @cfg: The configuration value to set.
227 *
228 * This helper deal with the GPIO cases where the control register has 4 bits
229 * of control per GPIO, generally in the form of:
230 * 0000 = Input
231 * 0001 = Output
232 * others = Special functions (dependent on bank)
233 *
234 * Note, since the code to deal with the case where there are two control
235 * registers instead of one, we do not have a separate set of functions for
236 * each case.
237 */
238
samsung_gpio_setcfg_4bit(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)239 static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
240 unsigned int off, unsigned int cfg)
241 {
242 void __iomem *reg = chip->base;
243 unsigned int shift = (off & 7) * 4;
244 u32 con;
245
246 if (off < 8 && chip->chip.ngpio > 8)
247 reg -= 4;
248
249 if (samsung_gpio_is_cfg_special(cfg)) {
250 cfg &= 0xf;
251 cfg <<= shift;
252 }
253
254 con = __raw_readl(reg);
255 con &= ~(0xf << shift);
256 con |= cfg;
257 __raw_writel(con, reg);
258
259 return 0;
260 }
261
262 /*
263 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
264 * @chip: The gpio chip that is being configured.
265 * @off: The offset for the GPIO being configured.
266 *
267 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
268 * register setting into a value the software can use, such as could be passed
269 * to samsung_gpio_setcfg_4bit().
270 *
271 * @sa samsung_gpio_getcfg_2bit
272 */
273
samsung_gpio_getcfg_4bit(struct samsung_gpio_chip * chip,unsigned int off)274 static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
275 unsigned int off)
276 {
277 void __iomem *reg = chip->base;
278 unsigned int shift = (off & 7) * 4;
279 u32 con;
280
281 if (off < 8 && chip->chip.ngpio > 8)
282 reg -= 4;
283
284 con = __raw_readl(reg);
285 con >>= shift;
286 con &= 0xf;
287
288 /* this conversion works for IN and OUT as well as special mode */
289 return S3C_GPIO_SPECIAL(con);
290 }
291
292 #ifdef CONFIG_PLAT_S3C24XX
293 /*
294 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
295 * @chip: The gpio chip that is being configured.
296 * @off: The offset for the GPIO being configured.
297 * @cfg: The configuration value to set.
298 *
299 * This helper deal with the GPIO cases where the control register
300 * has one bit of configuration for the gpio, where setting the bit
301 * means the pin is in special function mode and unset means output.
302 */
303
s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip * chip,unsigned int off,unsigned int cfg)304 static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
305 unsigned int off, unsigned int cfg)
306 {
307 void __iomem *reg = chip->base;
308 unsigned int shift = off;
309 u32 con;
310
311 if (samsung_gpio_is_cfg_special(cfg)) {
312 cfg &= 0xf;
313
314 /* Map output to 0, and SFN2 to 1 */
315 cfg -= 1;
316 if (cfg > 1)
317 return -EINVAL;
318
319 cfg <<= shift;
320 }
321
322 con = __raw_readl(reg);
323 con &= ~(0x1 << shift);
324 con |= cfg;
325 __raw_writel(con, reg);
326
327 return 0;
328 }
329
330 /*
331 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
332 * @chip: The gpio chip that is being configured.
333 * @off: The offset for the GPIO being configured.
334 *
335 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
336 * GPIO configuration value.
337 *
338 * @sa samsung_gpio_getcfg_2bit
339 * @sa samsung_gpio_getcfg_4bit
340 */
341
s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip * chip,unsigned int off)342 static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
343 unsigned int off)
344 {
345 u32 con;
346
347 con = __raw_readl(chip->base);
348 con >>= off;
349 con &= 1;
350 con++;
351
352 return S3C_GPIO_SFN(con);
353 }
354 #endif
355
samsung_gpiolib_set_cfg(struct samsung_gpio_cfg * chipcfg,int nr_chips)356 static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
357 int nr_chips)
358 {
359 for (; nr_chips > 0; nr_chips--, chipcfg++) {
360 if (!chipcfg->set_config)
361 chipcfg->set_config = samsung_gpio_setcfg_4bit;
362 if (!chipcfg->get_config)
363 chipcfg->get_config = samsung_gpio_getcfg_4bit;
364 if (!chipcfg->set_pull)
365 chipcfg->set_pull = samsung_gpio_setpull_updown;
366 if (!chipcfg->get_pull)
367 chipcfg->get_pull = samsung_gpio_getpull_updown;
368 }
369 }
370
371 struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
372 .set_config = samsung_gpio_setcfg_2bit,
373 .get_config = samsung_gpio_getcfg_2bit,
374 };
375
376 #ifdef CONFIG_PLAT_S3C24XX
377 static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
378 .set_config = s3c24xx_gpio_setcfg_abank,
379 .get_config = s3c24xx_gpio_getcfg_abank,
380 };
381 #endif
382
383 static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
384 [0] = {
385 .cfg_eint = 0x0,
386 },
387 [1] = {
388 .cfg_eint = 0x3,
389 },
390 [2] = {
391 .cfg_eint = 0x7,
392 },
393 [3] = {
394 .cfg_eint = 0xF,
395 },
396 [4] = {
397 .cfg_eint = 0x0,
398 .set_config = samsung_gpio_setcfg_2bit,
399 .get_config = samsung_gpio_getcfg_2bit,
400 },
401 [5] = {
402 .cfg_eint = 0x2,
403 .set_config = samsung_gpio_setcfg_2bit,
404 .get_config = samsung_gpio_getcfg_2bit,
405 },
406 [6] = {
407 .cfg_eint = 0x3,
408 .set_config = samsung_gpio_setcfg_2bit,
409 .get_config = samsung_gpio_getcfg_2bit,
410 },
411 [7] = {
412 .set_config = samsung_gpio_setcfg_2bit,
413 .get_config = samsung_gpio_getcfg_2bit,
414 },
415 };
416
417 /*
418 * Default routines for controlling GPIO, based on the original S3C24XX
419 * GPIO functions which deal with the case where each gpio bank of the
420 * chip is as following:
421 *
422 * base + 0x00: Control register, 2 bits per gpio
423 * gpio n: 2 bits starting at (2*n)
424 * 00 = input, 01 = output, others mean special-function
425 * base + 0x04: Data register, 1 bit per gpio
426 * bit n: data bit n
427 */
428
samsung_gpiolib_2bit_input(struct gpio_chip * chip,unsigned offset)429 static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
430 {
431 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
432 void __iomem *base = ourchip->base;
433 unsigned long flags;
434 unsigned long con;
435
436 samsung_gpio_lock(ourchip, flags);
437
438 con = __raw_readl(base + 0x00);
439 con &= ~(3 << (offset * 2));
440
441 __raw_writel(con, base + 0x00);
442
443 samsung_gpio_unlock(ourchip, flags);
444 return 0;
445 }
446
samsung_gpiolib_2bit_output(struct gpio_chip * chip,unsigned offset,int value)447 static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
448 unsigned offset, int value)
449 {
450 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
451 void __iomem *base = ourchip->base;
452 unsigned long flags;
453 unsigned long dat;
454 unsigned long con;
455
456 samsung_gpio_lock(ourchip, flags);
457
458 dat = __raw_readl(base + 0x04);
459 dat &= ~(1 << offset);
460 if (value)
461 dat |= 1 << offset;
462 __raw_writel(dat, base + 0x04);
463
464 con = __raw_readl(base + 0x00);
465 con &= ~(3 << (offset * 2));
466 con |= 1 << (offset * 2);
467
468 __raw_writel(con, base + 0x00);
469 __raw_writel(dat, base + 0x04);
470
471 samsung_gpio_unlock(ourchip, flags);
472 return 0;
473 }
474
475 /*
476 * The samsung_gpiolib_4bit routines are to control the gpio banks where
477 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
478 * following example:
479 *
480 * base + 0x00: Control register, 4 bits per gpio
481 * gpio n: 4 bits starting at (4*n)
482 * 0000 = input, 0001 = output, others mean special-function
483 * base + 0x04: Data register, 1 bit per gpio
484 * bit n: data bit n
485 *
486 * Note, since the data register is one bit per gpio and is at base + 0x4
487 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
488 * state of the output.
489 */
490
samsung_gpiolib_4bit_input(struct gpio_chip * chip,unsigned int offset)491 static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
492 unsigned int offset)
493 {
494 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
495 void __iomem *base = ourchip->base;
496 unsigned long con;
497
498 con = __raw_readl(base + GPIOCON_OFF);
499 if (ourchip->bitmap_gpio_int & BIT(offset))
500 con |= 0xf << con_4bit_shift(offset);
501 else
502 con &= ~(0xf << con_4bit_shift(offset));
503 __raw_writel(con, base + GPIOCON_OFF);
504
505 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
506
507 return 0;
508 }
509
samsung_gpiolib_4bit_output(struct gpio_chip * chip,unsigned int offset,int value)510 static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
511 unsigned int offset, int value)
512 {
513 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
514 void __iomem *base = ourchip->base;
515 unsigned long con;
516 unsigned long dat;
517
518 con = __raw_readl(base + GPIOCON_OFF);
519 con &= ~(0xf << con_4bit_shift(offset));
520 con |= 0x1 << con_4bit_shift(offset);
521
522 dat = __raw_readl(base + GPIODAT_OFF);
523
524 if (value)
525 dat |= 1 << offset;
526 else
527 dat &= ~(1 << offset);
528
529 __raw_writel(dat, base + GPIODAT_OFF);
530 __raw_writel(con, base + GPIOCON_OFF);
531 __raw_writel(dat, base + GPIODAT_OFF);
532
533 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
534
535 return 0;
536 }
537
538 /*
539 * The next set of routines are for the case where the GPIO configuration
540 * registers are 4 bits per GPIO but there is more than one register (the
541 * bank has more than 8 GPIOs.
542 *
543 * This case is the similar to the 4 bit case, but the registers are as
544 * follows:
545 *
546 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
547 * gpio n: 4 bits starting at (4*n)
548 * 0000 = input, 0001 = output, others mean special-function
549 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
550 * gpio n: 4 bits starting at (4*n)
551 * 0000 = input, 0001 = output, others mean special-function
552 * base + 0x08: Data register, 1 bit per gpio
553 * bit n: data bit n
554 *
555 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
556 * routines we store the 'base + 0x4' address so that these routines see
557 * the data register at ourchip->base + 0x04.
558 */
559
samsung_gpiolib_4bit2_input(struct gpio_chip * chip,unsigned int offset)560 static int samsung_gpiolib_4bit2_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 void __iomem *regcon = base;
566 unsigned long con;
567
568 if (offset > 7)
569 offset -= 8;
570 else
571 regcon -= 4;
572
573 con = __raw_readl(regcon);
574 con &= ~(0xf << con_4bit_shift(offset));
575 __raw_writel(con, regcon);
576
577 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
578
579 return 0;
580 }
581
samsung_gpiolib_4bit2_output(struct gpio_chip * chip,unsigned int offset,int value)582 static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
583 unsigned int offset, int value)
584 {
585 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
586 void __iomem *base = ourchip->base;
587 void __iomem *regcon = base;
588 unsigned long con;
589 unsigned long dat;
590 unsigned con_offset = offset;
591
592 if (con_offset > 7)
593 con_offset -= 8;
594 else
595 regcon -= 4;
596
597 con = __raw_readl(regcon);
598 con &= ~(0xf << con_4bit_shift(con_offset));
599 con |= 0x1 << con_4bit_shift(con_offset);
600
601 dat = __raw_readl(base + GPIODAT_OFF);
602
603 if (value)
604 dat |= 1 << offset;
605 else
606 dat &= ~(1 << offset);
607
608 __raw_writel(dat, base + GPIODAT_OFF);
609 __raw_writel(con, regcon);
610 __raw_writel(dat, base + GPIODAT_OFF);
611
612 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
613
614 return 0;
615 }
616
617 #ifdef CONFIG_PLAT_S3C24XX
618 /* The next set of routines are for the case of s3c24xx bank a */
619
s3c24xx_gpiolib_banka_input(struct gpio_chip * chip,unsigned offset)620 static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
621 {
622 return -EINVAL;
623 }
624
s3c24xx_gpiolib_banka_output(struct gpio_chip * chip,unsigned offset,int value)625 static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
626 unsigned offset, int value)
627 {
628 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
629 void __iomem *base = ourchip->base;
630 unsigned long flags;
631 unsigned long dat;
632 unsigned long con;
633
634 local_irq_save(flags);
635
636 con = __raw_readl(base + 0x00);
637 dat = __raw_readl(base + 0x04);
638
639 dat &= ~(1 << offset);
640 if (value)
641 dat |= 1 << offset;
642
643 __raw_writel(dat, base + 0x04);
644
645 con &= ~(1 << offset);
646
647 __raw_writel(con, base + 0x00);
648 __raw_writel(dat, base + 0x04);
649
650 local_irq_restore(flags);
651 return 0;
652 }
653 #endif
654
samsung_gpiolib_set(struct gpio_chip * chip,unsigned offset,int value)655 static void samsung_gpiolib_set(struct gpio_chip *chip,
656 unsigned offset, int value)
657 {
658 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
659 void __iomem *base = ourchip->base;
660 unsigned long flags;
661 unsigned long dat;
662
663 samsung_gpio_lock(ourchip, flags);
664
665 dat = __raw_readl(base + 0x04);
666 dat &= ~(1 << offset);
667 if (value)
668 dat |= 1 << offset;
669 __raw_writel(dat, base + 0x04);
670
671 samsung_gpio_unlock(ourchip, flags);
672 }
673
samsung_gpiolib_get(struct gpio_chip * chip,unsigned offset)674 static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
675 {
676 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
677 unsigned long val;
678
679 val = __raw_readl(ourchip->base + 0x04);
680 val >>= offset;
681 val &= 1;
682
683 return val;
684 }
685
686 /*
687 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
688 * for use with the configuration calls, and other parts of the s3c gpiolib
689 * support code.
690 *
691 * Not all s3c support code will need this, as some configurations of cpu
692 * may only support one or two different configuration options and have an
693 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
694 * the machine support file should provide its own samsung_gpiolib_getchip()
695 * and any other necessary functions.
696 */
697
698 #ifdef CONFIG_S3C_GPIO_TRACK
699 struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
700
s3c_gpiolib_track(struct samsung_gpio_chip * chip)701 static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
702 {
703 unsigned int gpn;
704 int i;
705
706 gpn = chip->chip.base;
707 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
708 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
709 s3c_gpios[gpn] = chip;
710 }
711 }
712 #endif /* CONFIG_S3C_GPIO_TRACK */
713
714 /*
715 * samsung_gpiolib_add() - add the Samsung gpio_chip.
716 * @chip: The chip to register
717 *
718 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
719 * information and makes the necessary alterations for the platform and
720 * notes the information for use with the configuration systems and any
721 * other parts of the system.
722 */
723
samsung_gpiolib_add(struct samsung_gpio_chip * chip)724 static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
725 {
726 struct gpio_chip *gc = &chip->chip;
727 int ret;
728
729 BUG_ON(!chip->base);
730 BUG_ON(!gc->label);
731 BUG_ON(!gc->ngpio);
732
733 spin_lock_init(&chip->lock);
734
735 if (!gc->direction_input)
736 gc->direction_input = samsung_gpiolib_2bit_input;
737 if (!gc->direction_output)
738 gc->direction_output = samsung_gpiolib_2bit_output;
739 if (!gc->set)
740 gc->set = samsung_gpiolib_set;
741 if (!gc->get)
742 gc->get = samsung_gpiolib_get;
743
744 #ifdef CONFIG_PM
745 if (chip->pm != NULL) {
746 if (!chip->pm->save || !chip->pm->resume)
747 pr_err("gpio: %s has missing PM functions\n",
748 gc->label);
749 } else
750 pr_err("gpio: %s has no PM function\n", gc->label);
751 #endif
752
753 /* gpiochip_add() prints own failure message on error. */
754 ret = gpiochip_add_data(gc, chip);
755 if (ret >= 0)
756 s3c_gpiolib_track(chip);
757 }
758
s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base)759 static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
760 int nr_chips, void __iomem *base)
761 {
762 int i;
763 struct gpio_chip *gc = &chip->chip;
764
765 for (i = 0 ; i < nr_chips; i++, chip++) {
766 /* skip banks not present on SoC */
767 if (chip->chip.base >= S3C_GPIO_END)
768 continue;
769
770 if (!chip->config)
771 chip->config = &s3c24xx_gpiocfg_default;
772 if (!chip->pm)
773 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
774 if ((base != NULL) && (chip->base == NULL))
775 chip->base = base + ((i) * 0x10);
776
777 if (!gc->direction_input)
778 gc->direction_input = samsung_gpiolib_2bit_input;
779 if (!gc->direction_output)
780 gc->direction_output = samsung_gpiolib_2bit_output;
781
782 samsung_gpiolib_add(chip);
783 }
784 }
785
samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base,unsigned int offset)786 static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
787 int nr_chips, void __iomem *base,
788 unsigned int offset)
789 {
790 int i;
791
792 for (i = 0 ; i < nr_chips; i++, chip++) {
793 chip->chip.direction_input = samsung_gpiolib_2bit_input;
794 chip->chip.direction_output = samsung_gpiolib_2bit_output;
795
796 if (!chip->config)
797 chip->config = &samsung_gpio_cfgs[7];
798 if (!chip->pm)
799 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
800 if ((base != NULL) && (chip->base == NULL))
801 chip->base = base + ((i) * offset);
802
803 samsung_gpiolib_add(chip);
804 }
805 }
806
807 /*
808 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
809 * @chip: The gpio chip that is being configured.
810 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
811 *
812 * This helper deal with the GPIO cases where the control register has 4 bits
813 * of control per GPIO, generally in the form of:
814 * 0000 = Input
815 * 0001 = Output
816 * others = Special functions (dependent on bank)
817 *
818 * Note, since the code to deal with the case where there are two control
819 * registers instead of one, we do not have a separate set of function
820 * (samsung_gpiolib_add_4bit2_chips)for each case.
821 */
822
samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip * chip,int nr_chips,void __iomem * base)823 static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
824 int nr_chips, void __iomem *base)
825 {
826 int i;
827
828 for (i = 0 ; i < nr_chips; i++, chip++) {
829 chip->chip.direction_input = samsung_gpiolib_4bit_input;
830 chip->chip.direction_output = samsung_gpiolib_4bit_output;
831
832 if (!chip->config)
833 chip->config = &samsung_gpio_cfgs[2];
834 if (!chip->pm)
835 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
836 if ((base != NULL) && (chip->base == NULL))
837 chip->base = base + ((i) * 0x20);
838
839 chip->bitmap_gpio_int = 0;
840
841 samsung_gpiolib_add(chip);
842 }
843 }
844
samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip * chip,int nr_chips)845 static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
846 int nr_chips)
847 {
848 for (; nr_chips > 0; nr_chips--, chip++) {
849 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
850 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
851
852 if (!chip->config)
853 chip->config = &samsung_gpio_cfgs[2];
854 if (!chip->pm)
855 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
856
857 samsung_gpiolib_add(chip);
858 }
859 }
860
samsung_gpiolib_to_irq(struct gpio_chip * chip,unsigned int offset)861 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
862 {
863 struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
864
865 return samsung_chip->irq_base + offset;
866 }
867
868 #ifdef CONFIG_PLAT_S3C24XX
s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip * chip,unsigned offset)869 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
870 {
871 if (offset < 4) {
872 if (soc_is_s3c2412())
873 return IRQ_EINT0_2412 + offset;
874 else
875 return IRQ_EINT0 + offset;
876 }
877
878 if (offset < 8)
879 return IRQ_EINT4 + offset - 4;
880
881 return -EINVAL;
882 }
883 #endif
884
885 #ifdef CONFIG_ARCH_S3C64XX
s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip * chip,unsigned pin)886 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
887 {
888 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
889 }
890
s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip * chip,unsigned pin)891 static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
892 {
893 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
894 }
895 #endif
896
897 struct samsung_gpio_chip s3c24xx_gpios[] = {
898 #ifdef CONFIG_PLAT_S3C24XX
899 {
900 .config = &s3c24xx_gpiocfg_banka,
901 .chip = {
902 .base = S3C2410_GPA(0),
903 .owner = THIS_MODULE,
904 .label = "GPIOA",
905 .ngpio = 27,
906 .direction_input = s3c24xx_gpiolib_banka_input,
907 .direction_output = s3c24xx_gpiolib_banka_output,
908 },
909 }, {
910 .chip = {
911 .base = S3C2410_GPB(0),
912 .owner = THIS_MODULE,
913 .label = "GPIOB",
914 .ngpio = 11,
915 },
916 }, {
917 .chip = {
918 .base = S3C2410_GPC(0),
919 .owner = THIS_MODULE,
920 .label = "GPIOC",
921 .ngpio = 16,
922 },
923 }, {
924 .chip = {
925 .base = S3C2410_GPD(0),
926 .owner = THIS_MODULE,
927 .label = "GPIOD",
928 .ngpio = 16,
929 },
930 }, {
931 .chip = {
932 .base = S3C2410_GPE(0),
933 .label = "GPIOE",
934 .owner = THIS_MODULE,
935 .ngpio = 16,
936 },
937 }, {
938 .chip = {
939 .base = S3C2410_GPF(0),
940 .owner = THIS_MODULE,
941 .label = "GPIOF",
942 .ngpio = 8,
943 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
944 },
945 }, {
946 .irq_base = IRQ_EINT8,
947 .chip = {
948 .base = S3C2410_GPG(0),
949 .owner = THIS_MODULE,
950 .label = "GPIOG",
951 .ngpio = 16,
952 .to_irq = samsung_gpiolib_to_irq,
953 },
954 }, {
955 .chip = {
956 .base = S3C2410_GPH(0),
957 .owner = THIS_MODULE,
958 .label = "GPIOH",
959 .ngpio = 15,
960 },
961 },
962 /* GPIOS for the S3C2443 and later devices. */
963 {
964 .base = S3C2440_GPJCON,
965 .chip = {
966 .base = S3C2410_GPJ(0),
967 .owner = THIS_MODULE,
968 .label = "GPIOJ",
969 .ngpio = 16,
970 },
971 }, {
972 .base = S3C2443_GPKCON,
973 .chip = {
974 .base = S3C2410_GPK(0),
975 .owner = THIS_MODULE,
976 .label = "GPIOK",
977 .ngpio = 16,
978 },
979 }, {
980 .base = S3C2443_GPLCON,
981 .chip = {
982 .base = S3C2410_GPL(0),
983 .owner = THIS_MODULE,
984 .label = "GPIOL",
985 .ngpio = 15,
986 },
987 }, {
988 .base = S3C2443_GPMCON,
989 .chip = {
990 .base = S3C2410_GPM(0),
991 .owner = THIS_MODULE,
992 .label = "GPIOM",
993 .ngpio = 2,
994 },
995 },
996 #endif
997 };
998
999 /*
1000 * GPIO bank summary:
1001 *
1002 * Bank GPIOs Style SlpCon ExtInt Group
1003 * A 8 4Bit Yes 1
1004 * B 7 4Bit Yes 1
1005 * C 8 4Bit Yes 2
1006 * D 5 4Bit Yes 3
1007 * E 5 4Bit Yes None
1008 * F 16 2Bit Yes 4 [1]
1009 * G 7 4Bit Yes 5
1010 * H 10 4Bit[2] Yes 6
1011 * I 16 2Bit Yes None
1012 * J 12 2Bit Yes None
1013 * K 16 4Bit[2] No None
1014 * L 15 4Bit[2] No None
1015 * M 6 4Bit No IRQ_EINT
1016 * N 16 2Bit No IRQ_EINT
1017 * O 16 2Bit Yes 7
1018 * P 15 2Bit Yes 8
1019 * Q 9 2Bit Yes 9
1020 *
1021 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1022 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1023 */
1024
1025 static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1026 #ifdef CONFIG_ARCH_S3C64XX
1027 {
1028 .chip = {
1029 .base = S3C64XX_GPA(0),
1030 .ngpio = S3C64XX_GPIO_A_NR,
1031 .label = "GPA",
1032 },
1033 }, {
1034 .chip = {
1035 .base = S3C64XX_GPB(0),
1036 .ngpio = S3C64XX_GPIO_B_NR,
1037 .label = "GPB",
1038 },
1039 }, {
1040 .chip = {
1041 .base = S3C64XX_GPC(0),
1042 .ngpio = S3C64XX_GPIO_C_NR,
1043 .label = "GPC",
1044 },
1045 }, {
1046 .chip = {
1047 .base = S3C64XX_GPD(0),
1048 .ngpio = S3C64XX_GPIO_D_NR,
1049 .label = "GPD",
1050 },
1051 }, {
1052 .config = &samsung_gpio_cfgs[0],
1053 .chip = {
1054 .base = S3C64XX_GPE(0),
1055 .ngpio = S3C64XX_GPIO_E_NR,
1056 .label = "GPE",
1057 },
1058 }, {
1059 .base = S3C64XX_GPG_BASE,
1060 .chip = {
1061 .base = S3C64XX_GPG(0),
1062 .ngpio = S3C64XX_GPIO_G_NR,
1063 .label = "GPG",
1064 },
1065 }, {
1066 .base = S3C64XX_GPM_BASE,
1067 .config = &samsung_gpio_cfgs[1],
1068 .chip = {
1069 .base = S3C64XX_GPM(0),
1070 .ngpio = S3C64XX_GPIO_M_NR,
1071 .label = "GPM",
1072 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1073 },
1074 },
1075 #endif
1076 };
1077
1078 static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1079 #ifdef CONFIG_ARCH_S3C64XX
1080 {
1081 .base = S3C64XX_GPH_BASE + 0x4,
1082 .chip = {
1083 .base = S3C64XX_GPH(0),
1084 .ngpio = S3C64XX_GPIO_H_NR,
1085 .label = "GPH",
1086 },
1087 }, {
1088 .base = S3C64XX_GPK_BASE + 0x4,
1089 .config = &samsung_gpio_cfgs[0],
1090 .chip = {
1091 .base = S3C64XX_GPK(0),
1092 .ngpio = S3C64XX_GPIO_K_NR,
1093 .label = "GPK",
1094 },
1095 }, {
1096 .base = S3C64XX_GPL_BASE + 0x4,
1097 .config = &samsung_gpio_cfgs[1],
1098 .chip = {
1099 .base = S3C64XX_GPL(0),
1100 .ngpio = S3C64XX_GPIO_L_NR,
1101 .label = "GPL",
1102 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1103 },
1104 },
1105 #endif
1106 };
1107
1108 static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1109 #ifdef CONFIG_ARCH_S3C64XX
1110 {
1111 .base = S3C64XX_GPF_BASE,
1112 .config = &samsung_gpio_cfgs[6],
1113 .chip = {
1114 .base = S3C64XX_GPF(0),
1115 .ngpio = S3C64XX_GPIO_F_NR,
1116 .label = "GPF",
1117 },
1118 }, {
1119 .config = &samsung_gpio_cfgs[7],
1120 .chip = {
1121 .base = S3C64XX_GPI(0),
1122 .ngpio = S3C64XX_GPIO_I_NR,
1123 .label = "GPI",
1124 },
1125 }, {
1126 .config = &samsung_gpio_cfgs[7],
1127 .chip = {
1128 .base = S3C64XX_GPJ(0),
1129 .ngpio = S3C64XX_GPIO_J_NR,
1130 .label = "GPJ",
1131 },
1132 }, {
1133 .config = &samsung_gpio_cfgs[6],
1134 .chip = {
1135 .base = S3C64XX_GPO(0),
1136 .ngpio = S3C64XX_GPIO_O_NR,
1137 .label = "GPO",
1138 },
1139 }, {
1140 .config = &samsung_gpio_cfgs[6],
1141 .chip = {
1142 .base = S3C64XX_GPP(0),
1143 .ngpio = S3C64XX_GPIO_P_NR,
1144 .label = "GPP",
1145 },
1146 }, {
1147 .config = &samsung_gpio_cfgs[6],
1148 .chip = {
1149 .base = S3C64XX_GPQ(0),
1150 .ngpio = S3C64XX_GPIO_Q_NR,
1151 .label = "GPQ",
1152 },
1153 }, {
1154 .base = S3C64XX_GPN_BASE,
1155 .irq_base = IRQ_EINT(0),
1156 .config = &samsung_gpio_cfgs[5],
1157 .chip = {
1158 .base = S3C64XX_GPN(0),
1159 .ngpio = S3C64XX_GPIO_N_NR,
1160 .label = "GPN",
1161 .to_irq = samsung_gpiolib_to_irq,
1162 },
1163 },
1164 #endif
1165 };
1166
1167 /* TODO: cleanup soc_is_* */
samsung_gpiolib_init(void)1168 static __init int samsung_gpiolib_init(void)
1169 {
1170 /*
1171 * Currently there are two drivers that can provide GPIO support for
1172 * Samsung SoCs. For device tree enabled platforms, the new
1173 * pinctrl-samsung driver is used, providing both GPIO and pin control
1174 * interfaces. For legacy (non-DT) platforms this driver is used.
1175 */
1176 if (of_have_populated_dt())
1177 return 0;
1178
1179 if (soc_is_s3c24xx()) {
1180 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1181 ARRAY_SIZE(samsung_gpio_cfgs));
1182 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1183 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1184 } else if (soc_is_s3c64xx()) {
1185 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1186 ARRAY_SIZE(samsung_gpio_cfgs));
1187 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1188 ARRAY_SIZE(s3c64xx_gpios_2bit),
1189 S3C64XX_VA_GPIO + 0xE0, 0x20);
1190 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1191 ARRAY_SIZE(s3c64xx_gpios_4bit),
1192 S3C64XX_VA_GPIO);
1193 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1194 ARRAY_SIZE(s3c64xx_gpios_4bit2));
1195 }
1196
1197 return 0;
1198 }
1199 core_initcall(samsung_gpiolib_init);
1200
s3c_gpio_cfgpin(unsigned int pin,unsigned int config)1201 int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1202 {
1203 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1204 unsigned long flags;
1205 int offset;
1206 int ret;
1207
1208 if (!chip)
1209 return -EINVAL;
1210
1211 offset = pin - chip->chip.base;
1212
1213 samsung_gpio_lock(chip, flags);
1214 ret = samsung_gpio_do_setcfg(chip, offset, config);
1215 samsung_gpio_unlock(chip, flags);
1216
1217 return ret;
1218 }
1219 EXPORT_SYMBOL(s3c_gpio_cfgpin);
1220
s3c_gpio_cfgpin_range(unsigned int start,unsigned int nr,unsigned int cfg)1221 int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1222 unsigned int cfg)
1223 {
1224 int ret;
1225
1226 for (; nr > 0; nr--, start++) {
1227 ret = s3c_gpio_cfgpin(start, cfg);
1228 if (ret != 0)
1229 return ret;
1230 }
1231
1232 return 0;
1233 }
1234 EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1235
s3c_gpio_cfgall_range(unsigned int start,unsigned int nr,unsigned int cfg,samsung_gpio_pull_t pull)1236 int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1237 unsigned int cfg, samsung_gpio_pull_t pull)
1238 {
1239 int ret;
1240
1241 for (; nr > 0; nr--, start++) {
1242 s3c_gpio_setpull(start, pull);
1243 ret = s3c_gpio_cfgpin(start, cfg);
1244 if (ret != 0)
1245 return ret;
1246 }
1247
1248 return 0;
1249 }
1250 EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1251
s3c_gpio_getcfg(unsigned int pin)1252 unsigned s3c_gpio_getcfg(unsigned int pin)
1253 {
1254 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1255 unsigned long flags;
1256 unsigned ret = 0;
1257 int offset;
1258
1259 if (chip) {
1260 offset = pin - chip->chip.base;
1261
1262 samsung_gpio_lock(chip, flags);
1263 ret = samsung_gpio_do_getcfg(chip, offset);
1264 samsung_gpio_unlock(chip, flags);
1265 }
1266
1267 return ret;
1268 }
1269 EXPORT_SYMBOL(s3c_gpio_getcfg);
1270
s3c_gpio_setpull(unsigned int pin,samsung_gpio_pull_t pull)1271 int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1272 {
1273 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1274 unsigned long flags;
1275 int offset, ret;
1276
1277 if (!chip)
1278 return -EINVAL;
1279
1280 offset = pin - chip->chip.base;
1281
1282 samsung_gpio_lock(chip, flags);
1283 ret = samsung_gpio_do_setpull(chip, offset, pull);
1284 samsung_gpio_unlock(chip, flags);
1285
1286 return ret;
1287 }
1288 EXPORT_SYMBOL(s3c_gpio_setpull);
1289
s3c_gpio_getpull(unsigned int pin)1290 samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1291 {
1292 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1293 unsigned long flags;
1294 int offset;
1295 u32 pup = 0;
1296
1297 if (chip) {
1298 offset = pin - chip->chip.base;
1299
1300 samsung_gpio_lock(chip, flags);
1301 pup = samsung_gpio_do_getpull(chip, offset);
1302 samsung_gpio_unlock(chip, flags);
1303 }
1304
1305 return (__force samsung_gpio_pull_t)pup;
1306 }
1307 EXPORT_SYMBOL(s3c_gpio_getpull);
1308
1309 #ifdef CONFIG_PLAT_S3C24XX
s3c2410_modify_misccr(unsigned int clear,unsigned int change)1310 unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1311 {
1312 unsigned long flags;
1313 unsigned long misccr;
1314
1315 local_irq_save(flags);
1316 misccr = __raw_readl(S3C24XX_MISCCR);
1317 misccr &= ~clear;
1318 misccr ^= change;
1319 __raw_writel(misccr, S3C24XX_MISCCR);
1320 local_irq_restore(flags);
1321
1322 return misccr;
1323 }
1324 EXPORT_SYMBOL(s3c2410_modify_misccr);
1325 #endif
1326