~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-s3c/gpio-samsung.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 40 static 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(reg);
 48         pup &= ~(3 << shift);
 49         pup |= pull << shift;
 50         __raw_writel(pup, reg);
 51 
 52         return 0;
 53 }
 54 
 55 static 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(reg);
 61 
 62         pup >>= shift;
 63         pup &= 0x3;
 64 
 65         return (__force samsung_gpio_pull_t)pup;
 66 }
 67 
 68 static 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(reg);
 84         con &= ~(0x3 << shift);
 85         con |= cfg;
 86         __raw_writel(con, 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 
101 static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
102                                              unsigned int off)
103 {
104         u32 con;
105 
106         con = __raw_readl(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 
131 static 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(reg);
147         con &= ~(0xf << shift);
148         con |= cfg;
149         __raw_writel(con, 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 
166 static 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(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 
184 static 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 
199 static 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 
245 static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
246 {
247         struct samsung_gpio_chip *ourchip = to_samsung_gpio(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(base + 0x00);
255         con &= ~(3 << (offset * 2));
256 
257         __raw_writel(con, base + 0x00);
258 
259         samsung_gpio_unlock(ourchip, flags);
260         return 0;
261 }
262 
263 static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
264                                        unsigned offset, int value)
265 {
266         struct samsung_gpio_chip *ourchip = to_samsung_gpio(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(base + 0x04);
275         dat &= ~(1 << offset);
276         if (value)
277                 dat |= 1 << offset;
278         __raw_writel(dat, base + 0x04);
279 
280         con = __raw_readl(base + 0x00);
281         con &= ~(3 << (offset * 2));
282         con |= 1 << (offset * 2);
283 
284         __raw_writel(con, base + 0x00);
285         __raw_writel(dat, 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 
307 static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
308                                       unsigned int offset)
309 {
310         struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
311         void __iomem *base = ourchip->base;
312         unsigned long con;
313 
314         con = __raw_readl(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(con, base + GPIOCON_OFF);
320 
321         pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
322 
323         return 0;
324 }
325 
326 static 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(chip);
330         void __iomem *base = ourchip->base;
331         unsigned long con;
332         unsigned long dat;
333 
334         con = __raw_readl(base + GPIOCON_OFF);
335         con &= ~(0xf << con_4bit_shift(offset));
336         con |= 0x1 << con_4bit_shift(offset);
337 
338         dat = __raw_readl(base + GPIODAT_OFF);
339 
340         if (value)
341                 dat |= 1 << offset;
342         else
343                 dat &= ~(1 << offset);
344 
345         __raw_writel(dat, base + GPIODAT_OFF);
346         __raw_writel(con, base + GPIOCON_OFF);
347         __raw_writel(dat, 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 
376 static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
377                                        unsigned int offset)
378 {
379         struct samsung_gpio_chip *ourchip = to_samsung_gpio(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(regcon);
390         con &= ~(0xf << con_4bit_shift(offset));
391         __raw_writel(con, regcon);
392 
393         pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
394 
395         return 0;
396 }
397 
398 static 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(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(regcon);
414         con &= ~(0xf << con_4bit_shift(con_offset));
415         con |= 0x1 << con_4bit_shift(con_offset);
416 
417         dat = __raw_readl(base + GPIODAT_OFF);
418 
419         if (value)
420                 dat |= 1 << offset;
421         else
422                 dat &= ~(1 << offset);
423 
424         __raw_writel(dat, base + GPIODAT_OFF);
425         __raw_writel(con, regcon);
426         __raw_writel(dat, base + GPIODAT_OFF);
427 
428         pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
429 
430         return 0;
431 }
432 
433 static void samsung_gpiolib_set(struct gpio_chip *chip,
434                                 unsigned offset, int value)
435 {
436         struct samsung_gpio_chip *ourchip = to_samsung_gpio(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(base + 0x04);
444         dat &= ~(1 << offset);
445         if (value)
446                 dat |= 1 << offset;
447         __raw_writel(dat, base + 0x04);
448 
449         samsung_gpio_unlock(ourchip, flags);
450 }
451 
452 static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
453 {
454         struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
455         unsigned long val;
456 
457         val = __raw_readl(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
477 struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
478 
479 static __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 
502 static 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 
537 static 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 
574 static 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 
596 static 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 
612 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
613 {
614         struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
615 
616         return samsung_chip->irq_base + offset;
617 }
618 
619 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
620 {
621         return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
622 }
623 
624 static 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 
655 static 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 
706 static 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 
734 static 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_* */
792 static __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(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 }
818 core_initcall(samsung_gpiolib_init);
819 
820 int 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, offset, config);
834         samsung_gpio_unlock(chip, flags);
835 
836         return ret;
837 }
838 EXPORT_SYMBOL(s3c_gpio_cfgpin);
839 
840 int 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(start, cfg);
847                 if (ret != 0)
848                         return ret;
849         }
850 
851         return 0;
852 }
853 EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
854 
855 int 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(start, pull);
862                 ret = s3c_gpio_cfgpin(start, cfg);
863                 if (ret != 0)
864                         return ret;
865         }
866 
867         return 0;
868 }
869 EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
870 
871 int 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, offset, pull);
884         samsung_gpio_unlock(chip, flags);
885 
886         return ret;
887 }
888 EXPORT_SYMBOL(s3c_gpio_setpull);
889 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php