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

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

Version: ~ [ linux-5.5-rc1 ] ~ [ linux-5.4.2 ] ~ [ linux-5.3.15 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.88 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.158 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.206 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.206 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp