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 "pm.h"
39
40static int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
41 unsigned int off, samsung_gpio_pull_t pull)
42{
43 void __iomem *reg = chip->base + 0x08;
44 int shift = off * 2;
45 u32 pup;
46
47 pup = __raw_readl(addr: reg);
48 pup &= ~(3 << shift);
49 pup |= pull << shift;
50 __raw_writel(val: pup, addr: reg);
51
52 return 0;
53}
54
55static samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
56 unsigned int off)
57{
58 void __iomem *reg = chip->base + 0x08;
59 int shift = off * 2;
60 u32 pup = __raw_readl(addr: reg);
61
62 pup >>= shift;
63 pup &= 0x3;
64
65 return (__force samsung_gpio_pull_t)pup;
66}
67
68static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
69 unsigned int off, unsigned int cfg)
70{
71 void __iomem *reg = chip->base;
72 unsigned int shift = off * 2;
73 u32 con;
74
75 if (samsung_gpio_is_cfg_special(cfg)) {
76 cfg &= 0xf;
77 if (cfg > 3)
78 return -EINVAL;
79
80 cfg <<= shift;
81 }
82
83 con = __raw_readl(addr: reg);
84 con &= ~(0x3 << shift);
85 con |= cfg;
86 __raw_writel(val: con, addr: reg);
87
88 return 0;
89}
90
91/*
92 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
93 * @chip: The gpio chip that is being configured.
94 * @off: The offset for the GPIO being configured.
95 *
96 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
97 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
98 * S3C_GPIO_SPECIAL() macro.
99 */
100
101static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
102 unsigned int off)
103{
104 u32 con;
105
106 con = __raw_readl(addr: chip->base);
107 con >>= off * 2;
108 con &= 3;
109
110 /* this conversion works for IN and OUT as well as special mode */
111 return S3C_GPIO_SPECIAL(con);
112}
113
114/*
115 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
116 * @chip: The gpio chip that is being configured.
117 * @off: The offset for the GPIO being configured.
118 * @cfg: The configuration value to set.
119 *
120 * This helper deal with the GPIO cases where the control register has 4 bits
121 * of control per GPIO, generally in the form of:
122 * 0000 = Input
123 * 0001 = Output
124 * others = Special functions (dependent on bank)
125 *
126 * Note, since the code to deal with the case where there are two control
127 * registers instead of one, we do not have a separate set of functions for
128 * each case.
129 */
130
131static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
132 unsigned int off, unsigned int cfg)
133{
134 void __iomem *reg = chip->base;
135 unsigned int shift = (off & 7) * 4;
136 u32 con;
137
138 if (off < 8 && chip->chip.ngpio > 8)
139 reg -= 4;
140
141 if (samsung_gpio_is_cfg_special(cfg)) {
142 cfg &= 0xf;
143 cfg <<= shift;
144 }
145
146 con = __raw_readl(addr: reg);
147 con &= ~(0xf << shift);
148 con |= cfg;
149 __raw_writel(val: con, addr: reg);
150
151 return 0;
152}
153
154/*
155 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
156 * @chip: The gpio chip that is being configured.
157 * @off: The offset for the GPIO being configured.
158 *
159 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
160 * register setting into a value the software can use, such as could be passed
161 * to samsung_gpio_setcfg_4bit().
162 *
163 * @sa samsung_gpio_getcfg_2bit
164 */
165
166static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
167 unsigned int off)
168{
169 void __iomem *reg = chip->base;
170 unsigned int shift = (off & 7) * 4;
171 u32 con;
172
173 if (off < 8 && chip->chip.ngpio > 8)
174 reg -= 4;
175
176 con = __raw_readl(addr: reg);
177 con >>= shift;
178 con &= 0xf;
179
180 /* this conversion works for IN and OUT as well as special mode */
181 return S3C_GPIO_SPECIAL(con);
182}
183
184static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
185 int nr_chips)
186{
187 for (; nr_chips > 0; nr_chips--, chipcfg++) {
188 if (!chipcfg->set_config)
189 chipcfg->set_config = samsung_gpio_setcfg_4bit;
190 if (!chipcfg->get_config)
191 chipcfg->get_config = samsung_gpio_getcfg_4bit;
192 if (!chipcfg->set_pull)
193 chipcfg->set_pull = samsung_gpio_setpull_updown;
194 if (!chipcfg->get_pull)
195 chipcfg->get_pull = samsung_gpio_getpull_updown;
196 }
197}
198
199static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
200 [0] = {
201 .cfg_eint = 0x0,
202 },
203 [1] = {
204 .cfg_eint = 0x3,
205 },
206 [2] = {
207 .cfg_eint = 0x7,
208 },
209 [3] = {
210 .cfg_eint = 0xF,
211 },
212 [4] = {
213 .cfg_eint = 0x0,
214 .set_config = samsung_gpio_setcfg_2bit,
215 .get_config = samsung_gpio_getcfg_2bit,
216 },
217 [5] = {
218 .cfg_eint = 0x2,
219 .set_config = samsung_gpio_setcfg_2bit,
220 .get_config = samsung_gpio_getcfg_2bit,
221 },
222 [6] = {
223 .cfg_eint = 0x3,
224 .set_config = samsung_gpio_setcfg_2bit,
225 .get_config = samsung_gpio_getcfg_2bit,
226 },
227 [7] = {
228 .set_config = samsung_gpio_setcfg_2bit,
229 .get_config = samsung_gpio_getcfg_2bit,
230 },
231};
232
233/*
234 * Default routines for controlling GPIO, based on the original S3C24XX
235 * GPIO functions which deal with the case where each gpio bank of the
236 * chip is as following:
237 *
238 * base + 0x00: Control register, 2 bits per gpio
239 * gpio n: 2 bits starting at (2*n)
240 * 00 = input, 01 = output, others mean special-function
241 * base + 0x04: Data register, 1 bit per gpio
242 * bit n: data bit n
243*/
244
245static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
246{
247 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
248 void __iomem *base = ourchip->base;
249 unsigned long flags;
250 unsigned long con;
251
252 samsung_gpio_lock(ourchip, flags);
253
254 con = __raw_readl(addr: base + 0x00);
255 con &= ~(3 << (offset * 2));
256
257 __raw_writel(val: con, addr: base + 0x00);
258
259 samsung_gpio_unlock(ourchip, flags);
260 return 0;
261}
262
263static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
264 unsigned offset, int value)
265{
266 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
267 void __iomem *base = ourchip->base;
268 unsigned long flags;
269 unsigned long dat;
270 unsigned long con;
271
272 samsung_gpio_lock(ourchip, flags);
273
274 dat = __raw_readl(addr: base + 0x04);
275 dat &= ~(1 << offset);
276 if (value)
277 dat |= 1 << offset;
278 __raw_writel(val: dat, addr: base + 0x04);
279
280 con = __raw_readl(addr: base + 0x00);
281 con &= ~(3 << (offset * 2));
282 con |= 1 << (offset * 2);
283
284 __raw_writel(val: con, addr: base + 0x00);
285 __raw_writel(val: dat, addr: base + 0x04);
286
287 samsung_gpio_unlock(ourchip, flags);
288 return 0;
289}
290
291/*
292 * The samsung_gpiolib_4bit routines are to control the gpio banks where
293 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
294 * following example:
295 *
296 * base + 0x00: Control register, 4 bits per gpio
297 * gpio n: 4 bits starting at (4*n)
298 * 0000 = input, 0001 = output, others mean special-function
299 * base + 0x04: Data register, 1 bit per gpio
300 * bit n: data bit n
301 *
302 * Note, since the data register is one bit per gpio and is at base + 0x4
303 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
304 * state of the output.
305 */
306
307static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
308 unsigned int offset)
309{
310 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
311 void __iomem *base = ourchip->base;
312 unsigned long con;
313
314 con = __raw_readl(addr: base + GPIOCON_OFF);
315 if (ourchip->bitmap_gpio_int & BIT(offset))
316 con |= 0xf << con_4bit_shift(offset);
317 else
318 con &= ~(0xf << con_4bit_shift(offset));
319 __raw_writel(val: con, addr: base + GPIOCON_OFF);
320
321 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
322
323 return 0;
324}
325
326static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
327 unsigned int offset, int value)
328{
329 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
330 void __iomem *base = ourchip->base;
331 unsigned long con;
332 unsigned long dat;
333
334 con = __raw_readl(addr: base + GPIOCON_OFF);
335 con &= ~(0xf << con_4bit_shift(offset));
336 con |= 0x1 << con_4bit_shift(offset);
337
338 dat = __raw_readl(addr: base + GPIODAT_OFF);
339
340 if (value)
341 dat |= 1 << offset;
342 else
343 dat &= ~(1 << offset);
344
345 __raw_writel(val: dat, addr: base + GPIODAT_OFF);
346 __raw_writel(val: con, addr: base + GPIOCON_OFF);
347 __raw_writel(val: dat, addr: base + GPIODAT_OFF);
348
349 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
350
351 return 0;
352}
353
354/*
355 * The next set of routines are for the case where the GPIO configuration
356 * registers are 4 bits per GPIO but there is more than one register (the
357 * bank has more than 8 GPIOs.
358 *
359 * This case is the similar to the 4 bit case, but the registers are as
360 * follows:
361 *
362 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
363 * gpio n: 4 bits starting at (4*n)
364 * 0000 = input, 0001 = output, others mean special-function
365 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
366 * gpio n: 4 bits starting at (4*n)
367 * 0000 = input, 0001 = output, others mean special-function
368 * base + 0x08: Data register, 1 bit per gpio
369 * bit n: data bit n
370 *
371 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
372 * routines we store the 'base + 0x4' address so that these routines see
373 * the data register at ourchip->base + 0x04.
374 */
375
376static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
377 unsigned int offset)
378{
379 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
380 void __iomem *base = ourchip->base;
381 void __iomem *regcon = base;
382 unsigned long con;
383
384 if (offset > 7)
385 offset -= 8;
386 else
387 regcon -= 4;
388
389 con = __raw_readl(addr: regcon);
390 con &= ~(0xf << con_4bit_shift(offset));
391 __raw_writel(val: con, addr: regcon);
392
393 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
394
395 return 0;
396}
397
398static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
399 unsigned int offset, int value)
400{
401 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
402 void __iomem *base = ourchip->base;
403 void __iomem *regcon = base;
404 unsigned long con;
405 unsigned long dat;
406 unsigned con_offset = offset;
407
408 if (con_offset > 7)
409 con_offset -= 8;
410 else
411 regcon -= 4;
412
413 con = __raw_readl(addr: regcon);
414 con &= ~(0xf << con_4bit_shift(con_offset));
415 con |= 0x1 << con_4bit_shift(con_offset);
416
417 dat = __raw_readl(addr: base + GPIODAT_OFF);
418
419 if (value)
420 dat |= 1 << offset;
421 else
422 dat &= ~(1 << offset);
423
424 __raw_writel(val: dat, addr: base + GPIODAT_OFF);
425 __raw_writel(val: con, addr: regcon);
426 __raw_writel(val: dat, addr: base + GPIODAT_OFF);
427
428 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
429
430 return 0;
431}
432
433static void samsung_gpiolib_set(struct gpio_chip *chip,
434 unsigned offset, int value)
435{
436 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
437 void __iomem *base = ourchip->base;
438 unsigned long flags;
439 unsigned long dat;
440
441 samsung_gpio_lock(ourchip, flags);
442
443 dat = __raw_readl(addr: base + 0x04);
444 dat &= ~(1 << offset);
445 if (value)
446 dat |= 1 << offset;
447 __raw_writel(val: dat, addr: base + 0x04);
448
449 samsung_gpio_unlock(ourchip, flags);
450}
451
452static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
453{
454 struct samsung_gpio_chip *ourchip = to_samsung_gpio(gpc: chip);
455 unsigned long val;
456
457 val = __raw_readl(addr: ourchip->base + 0x04);
458 val >>= offset;
459 val &= 1;
460
461 return val;
462}
463
464/*
465 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
466 * for use with the configuration calls, and other parts of the s3c gpiolib
467 * support code.
468 *
469 * Not all s3c support code will need this, as some configurations of cpu
470 * may only support one or two different configuration options and have an
471 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
472 * the machine support file should provide its own samsung_gpiolib_getchip()
473 * and any other necessary functions.
474 */
475
476#ifdef CONFIG_S3C_GPIO_TRACK
477struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
478
479static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
480{
481 unsigned int gpn;
482 int i;
483
484 gpn = chip->chip.base;
485 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
486 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
487 s3c_gpios[gpn] = chip;
488 }
489}
490#endif /* CONFIG_S3C_GPIO_TRACK */
491
492/*
493 * samsung_gpiolib_add() - add the Samsung gpio_chip.
494 * @chip: The chip to register
495 *
496 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
497 * information and makes the necessary alterations for the platform and
498 * notes the information for use with the configuration systems and any
499 * other parts of the system.
500 */
501
502static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
503{
504 struct gpio_chip *gc = &chip->chip;
505 int ret;
506
507 BUG_ON(!chip->base);
508 BUG_ON(!gc->label);
509 BUG_ON(!gc->ngpio);
510
511 spin_lock_init(&chip->lock);
512
513 if (!gc->direction_input)
514 gc->direction_input = samsung_gpiolib_2bit_input;
515 if (!gc->direction_output)
516 gc->direction_output = samsung_gpiolib_2bit_output;
517 if (!gc->set)
518 gc->set = samsung_gpiolib_set;
519 if (!gc->get)
520 gc->get = samsung_gpiolib_get;
521
522#ifdef CONFIG_PM
523 if (chip->pm != NULL) {
524 if (!chip->pm->save || !chip->pm->resume)
525 pr_err("gpio: %s has missing PM functions\n",
526 gc->label);
527 } else
528 pr_err("gpio: %s has no PM function\n", gc->label);
529#endif
530
531 /* gpiochip_add() prints own failure message on error. */
532 ret = gpiochip_add_data(gc, chip);
533 if (ret >= 0)
534 s3c_gpiolib_track(chip);
535}
536
537static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
538 int nr_chips, void __iomem *base,
539 unsigned int offset)
540{
541 int i;
542
543 for (i = 0 ; i < nr_chips; i++, chip++) {
544 chip->chip.direction_input = samsung_gpiolib_2bit_input;
545 chip->chip.direction_output = samsung_gpiolib_2bit_output;
546
547 if (!chip->config)
548 chip->config = &samsung_gpio_cfgs[7];
549 if (!chip->pm)
550 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
551 if ((base != NULL) && (chip->base == NULL))
552 chip->base = base + ((i) * offset);
553
554 samsung_gpiolib_add(chip);
555 }
556}
557
558/*
559 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
560 * @chip: The gpio chip that is being configured.
561 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
562 *
563 * This helper deal with the GPIO cases where the control register has 4 bits
564 * of control per GPIO, generally in the form of:
565 * 0000 = Input
566 * 0001 = Output
567 * others = Special functions (dependent on bank)
568 *
569 * Note, since the code to deal with the case where there are two control
570 * registers instead of one, we do not have a separate set of function
571 * (samsung_gpiolib_add_4bit2_chips)for each case.
572 */
573
574static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
575 int nr_chips, void __iomem *base)
576{
577 int i;
578
579 for (i = 0 ; i < nr_chips; i++, chip++) {
580 chip->chip.direction_input = samsung_gpiolib_4bit_input;
581 chip->chip.direction_output = samsung_gpiolib_4bit_output;
582
583 if (!chip->config)
584 chip->config = &samsung_gpio_cfgs[2];
585 if (!chip->pm)
586 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
587 if ((base != NULL) && (chip->base == NULL))
588 chip->base = base + ((i) * 0x20);
589
590 chip->bitmap_gpio_int = 0;
591
592 samsung_gpiolib_add(chip);
593 }
594}
595
596static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
597 int nr_chips)
598{
599 for (; nr_chips > 0; nr_chips--, chip++) {
600 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
601 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
602
603 if (!chip->config)
604 chip->config = &samsung_gpio_cfgs[2];
605 if (!chip->pm)
606 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
607
608 samsung_gpiolib_add(chip);
609 }
610}
611
612int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
613{
614 struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(gc: chip);
615
616 return samsung_chip->irq_base + offset;
617}
618
619static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
620{
621 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
622}
623
624static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
625{
626 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
627}
628
629/*
630 * GPIO bank summary:
631 *
632 * Bank GPIOs Style SlpCon ExtInt Group
633 * A 8 4Bit Yes 1
634 * B 7 4Bit Yes 1
635 * C 8 4Bit Yes 2
636 * D 5 4Bit Yes 3
637 * E 5 4Bit Yes None
638 * F 16 2Bit Yes 4 [1]
639 * G 7 4Bit Yes 5
640 * H 10 4Bit[2] Yes 6
641 * I 16 2Bit Yes None
642 * J 12 2Bit Yes None
643 * K 16 4Bit[2] No None
644 * L 15 4Bit[2] No None
645 * M 6 4Bit No IRQ_EINT
646 * N 16 2Bit No IRQ_EINT
647 * O 16 2Bit Yes 7
648 * P 15 2Bit Yes 8
649 * Q 9 2Bit Yes 9
650 *
651 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
652 * [2] BANK has two control registers, GPxCON0 and GPxCON1
653 */
654
655static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
656 {
657 .chip = {
658 .base = S3C64XX_GPA(0),
659 .ngpio = S3C64XX_GPIO_A_NR,
660 .label = "GPA",
661 },
662 }, {
663 .chip = {
664 .base = S3C64XX_GPB(0),
665 .ngpio = S3C64XX_GPIO_B_NR,
666 .label = "GPB",
667 },
668 }, {
669 .chip = {
670 .base = S3C64XX_GPC(0),
671 .ngpio = S3C64XX_GPIO_C_NR,
672 .label = "GPC",
673 },
674 }, {
675 .chip = {
676 .base = S3C64XX_GPD(0),
677 .ngpio = S3C64XX_GPIO_D_NR,
678 .label = "GPD",
679 },
680 }, {
681 .config = &samsung_gpio_cfgs[0],
682 .chip = {
683 .base = S3C64XX_GPE(0),
684 .ngpio = S3C64XX_GPIO_E_NR,
685 .label = "GPE",
686 },
687 }, {
688 .base = S3C64XX_GPG_BASE,
689 .chip = {
690 .base = S3C64XX_GPG(0),
691 .ngpio = S3C64XX_GPIO_G_NR,
692 .label = "GPG",
693 },
694 }, {
695 .base = S3C64XX_GPM_BASE,
696 .config = &samsung_gpio_cfgs[1],
697 .chip = {
698 .base = S3C64XX_GPM(0),
699 .ngpio = S3C64XX_GPIO_M_NR,
700 .label = "GPM",
701 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
702 },
703 },
704};
705
706static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
707 {
708 .base = S3C64XX_GPH_BASE + 0x4,
709 .chip = {
710 .base = S3C64XX_GPH(0),
711 .ngpio = S3C64XX_GPIO_H_NR,
712 .label = "GPH",
713 },
714 }, {
715 .base = S3C64XX_GPK_BASE + 0x4,
716 .config = &samsung_gpio_cfgs[0],
717 .chip = {
718 .base = S3C64XX_GPK(0),
719 .ngpio = S3C64XX_GPIO_K_NR,
720 .label = "GPK",
721 },
722 }, {
723 .base = S3C64XX_GPL_BASE + 0x4,
724 .config = &samsung_gpio_cfgs[1],
725 .chip = {
726 .base = S3C64XX_GPL(0),
727 .ngpio = S3C64XX_GPIO_L_NR,
728 .label = "GPL",
729 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
730 },
731 },
732};
733
734static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
735 {
736 .base = S3C64XX_GPF_BASE,
737 .config = &samsung_gpio_cfgs[6],
738 .chip = {
739 .base = S3C64XX_GPF(0),
740 .ngpio = S3C64XX_GPIO_F_NR,
741 .label = "GPF",
742 },
743 }, {
744 .config = &samsung_gpio_cfgs[7],
745 .chip = {
746 .base = S3C64XX_GPI(0),
747 .ngpio = S3C64XX_GPIO_I_NR,
748 .label = "GPI",
749 },
750 }, {
751 .config = &samsung_gpio_cfgs[7],
752 .chip = {
753 .base = S3C64XX_GPJ(0),
754 .ngpio = S3C64XX_GPIO_J_NR,
755 .label = "GPJ",
756 },
757 }, {
758 .config = &samsung_gpio_cfgs[6],
759 .chip = {
760 .base = S3C64XX_GPO(0),
761 .ngpio = S3C64XX_GPIO_O_NR,
762 .label = "GPO",
763 },
764 }, {
765 .config = &samsung_gpio_cfgs[6],
766 .chip = {
767 .base = S3C64XX_GPP(0),
768 .ngpio = S3C64XX_GPIO_P_NR,
769 .label = "GPP",
770 },
771 }, {
772 .config = &samsung_gpio_cfgs[6],
773 .chip = {
774 .base = S3C64XX_GPQ(0),
775 .ngpio = S3C64XX_GPIO_Q_NR,
776 .label = "GPQ",
777 },
778 }, {
779 .base = S3C64XX_GPN_BASE,
780 .irq_base = IRQ_EINT(0),
781 .config = &samsung_gpio_cfgs[5],
782 .chip = {
783 .base = S3C64XX_GPN(0),
784 .ngpio = S3C64XX_GPIO_N_NR,
785 .label = "GPN",
786 .to_irq = samsung_gpiolib_to_irq,
787 },
788 },
789};
790
791/* TODO: cleanup soc_is_* */
792static __init int samsung_gpiolib_init(void)
793{
794 /*
795 * Currently there are two drivers that can provide GPIO support for
796 * Samsung SoCs. For device tree enabled platforms, the new
797 * pinctrl-samsung driver is used, providing both GPIO and pin control
798 * interfaces. For legacy (non-DT) platforms this driver is used.
799 */
800 if (of_have_populated_dt())
801 return 0;
802
803 if (soc_is_s3c64xx()) {
804 samsung_gpiolib_set_cfg(chipcfg: samsung_gpio_cfgs,
805 ARRAY_SIZE(samsung_gpio_cfgs));
806 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
807 ARRAY_SIZE(s3c64xx_gpios_2bit),
808 S3C64XX_VA_GPIO + 0xE0, 0x20);
809 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
810 ARRAY_SIZE(s3c64xx_gpios_4bit),
811 S3C64XX_VA_GPIO);
812 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
813 ARRAY_SIZE(s3c64xx_gpios_4bit2));
814 }
815
816 return 0;
817}
818core_initcall(samsung_gpiolib_init);
819
820int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
821{
822 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
823 unsigned long flags;
824 int offset;
825 int ret;
826
827 if (!chip)
828 return -EINVAL;
829
830 offset = pin - chip->chip.base;
831
832 samsung_gpio_lock(chip, flags);
833 ret = samsung_gpio_do_setcfg(chip, off: offset, config);
834 samsung_gpio_unlock(chip, flags);
835
836 return ret;
837}
838EXPORT_SYMBOL(s3c_gpio_cfgpin);
839
840int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
841 unsigned int cfg)
842{
843 int ret;
844
845 for (; nr > 0; nr--, start++) {
846 ret = s3c_gpio_cfgpin(pin: start, config: cfg);
847 if (ret != 0)
848 return ret;
849 }
850
851 return 0;
852}
853EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
854
855int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
856 unsigned int cfg, samsung_gpio_pull_t pull)
857{
858 int ret;
859
860 for (; nr > 0; nr--, start++) {
861 s3c_gpio_setpull(pin: start, pull);
862 ret = s3c_gpio_cfgpin(pin: start, config: cfg);
863 if (ret != 0)
864 return ret;
865 }
866
867 return 0;
868}
869EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
870
871int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
872{
873 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
874 unsigned long flags;
875 int offset, ret;
876
877 if (!chip)
878 return -EINVAL;
879
880 offset = pin - chip->chip.base;
881
882 samsung_gpio_lock(chip, flags);
883 ret = samsung_gpio_do_setpull(chip, off: offset, pull);
884 samsung_gpio_unlock(chip, flags);
885
886 return ret;
887}
888EXPORT_SYMBOL(s3c_gpio_setpull);
889

source code of linux/arch/arm/mach-s3c/gpio-samsung.c