Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
0004 //      http://www.samsung.com/
0005 //
0006 // Copyright 2008 Openmoko, Inc.
0007 // Copyright 2008 Simtec Electronics
0008 //      Ben Dooks <ben@simtec.co.uk>
0009 //      http://armlinux.simtec.co.uk/
0010 //
0011 // Samsung - GPIOlib support
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/irq.h>
0015 #include <linux/io.h>
0016 #include <linux/gpio.h>
0017 #include <linux/init.h>
0018 #include <linux/spinlock.h>
0019 #include <linux/module.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/device.h>
0022 #include <linux/ioport.h>
0023 #include <linux/of.h>
0024 #include <linux/slab.h>
0025 #include <linux/of_address.h>
0026 
0027 #include <asm/irq.h>
0028 
0029 #include "irqs.h"
0030 #include "map.h"
0031 #include "regs-gpio.h"
0032 #include "gpio-samsung.h"
0033 
0034 #include "cpu.h"
0035 #include "gpio-core.h"
0036 #include "gpio-cfg.h"
0037 #include "gpio-cfg-helpers.h"
0038 #include "hardware-s3c24xx.h"
0039 #include "pm.h"
0040 
0041 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
0042                 unsigned int off, samsung_gpio_pull_t pull)
0043 {
0044     void __iomem *reg = chip->base + 0x08;
0045     int shift = off * 2;
0046     u32 pup;
0047 
0048     pup = __raw_readl(reg);
0049     pup &= ~(3 << shift);
0050     pup |= pull << shift;
0051     __raw_writel(pup, reg);
0052 
0053     return 0;
0054 }
0055 
0056 samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
0057                         unsigned int off)
0058 {
0059     void __iomem *reg = chip->base + 0x08;
0060     int shift = off * 2;
0061     u32 pup = __raw_readl(reg);
0062 
0063     pup >>= shift;
0064     pup &= 0x3;
0065 
0066     return (__force samsung_gpio_pull_t)pup;
0067 }
0068 
0069 int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
0070              unsigned int off, samsung_gpio_pull_t pull)
0071 {
0072     switch (pull) {
0073     case S3C_GPIO_PULL_NONE:
0074         pull = 0x01;
0075         break;
0076     case S3C_GPIO_PULL_UP:
0077         pull = 0x00;
0078         break;
0079     case S3C_GPIO_PULL_DOWN:
0080         pull = 0x02;
0081         break;
0082     }
0083     return samsung_gpio_setpull_updown(chip, off, pull);
0084 }
0085 
0086 samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
0087                      unsigned int off)
0088 {
0089     samsung_gpio_pull_t pull;
0090 
0091     pull = samsung_gpio_getpull_updown(chip, off);
0092 
0093     switch (pull) {
0094     case 0x00:
0095         pull = S3C_GPIO_PULL_UP;
0096         break;
0097     case 0x01:
0098     case 0x03:
0099         pull = S3C_GPIO_PULL_NONE;
0100         break;
0101     case 0x02:
0102         pull = S3C_GPIO_PULL_DOWN;
0103         break;
0104     }
0105 
0106     return pull;
0107 }
0108 
0109 static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
0110                   unsigned int off, samsung_gpio_pull_t pull,
0111                   samsung_gpio_pull_t updown)
0112 {
0113     void __iomem *reg = chip->base + 0x08;
0114     u32 pup = __raw_readl(reg);
0115 
0116     if (pull == updown)
0117         pup &= ~(1 << off);
0118     else if (pull == S3C_GPIO_PULL_NONE)
0119         pup |= (1 << off);
0120     else
0121         return -EINVAL;
0122 
0123     __raw_writel(pup, reg);
0124     return 0;
0125 }
0126 
0127 static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
0128                           unsigned int off,
0129                           samsung_gpio_pull_t updown)
0130 {
0131     void __iomem *reg = chip->base + 0x08;
0132     u32 pup = __raw_readl(reg);
0133 
0134     pup &= (1 << off);
0135     return pup ? S3C_GPIO_PULL_NONE : updown;
0136 }
0137 
0138 samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
0139                          unsigned int off)
0140 {
0141     return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
0142 }
0143 
0144 int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
0145                  unsigned int off, samsung_gpio_pull_t pull)
0146 {
0147     return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
0148 }
0149 
0150 samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
0151                            unsigned int off)
0152 {
0153     return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
0154 }
0155 
0156 int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
0157                    unsigned int off, samsung_gpio_pull_t pull)
0158 {
0159     return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
0160 }
0161 
0162 /*
0163  * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
0164  * @chip: The gpio chip that is being configured.
0165  * @off: The offset for the GPIO being configured.
0166  * @cfg: The configuration value to set.
0167  *
0168  * This helper deal with the GPIO cases where the control register
0169  * has two bits of configuration per gpio, which have the following
0170  * functions:
0171  *  00 = input
0172  *  01 = output
0173  *  1x = special function
0174  */
0175 
0176 static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
0177                     unsigned int off, unsigned int cfg)
0178 {
0179     void __iomem *reg = chip->base;
0180     unsigned int shift = off * 2;
0181     u32 con;
0182 
0183     if (samsung_gpio_is_cfg_special(cfg)) {
0184         cfg &= 0xf;
0185         if (cfg > 3)
0186             return -EINVAL;
0187 
0188         cfg <<= shift;
0189     }
0190 
0191     con = __raw_readl(reg);
0192     con &= ~(0x3 << shift);
0193     con |= cfg;
0194     __raw_writel(con, reg);
0195 
0196     return 0;
0197 }
0198 
0199 /*
0200  * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
0201  * @chip: The gpio chip that is being configured.
0202  * @off: The offset for the GPIO being configured.
0203  *
0204  * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
0205  * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
0206  * S3C_GPIO_SPECIAL() macro.
0207  */
0208 
0209 static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
0210                          unsigned int off)
0211 {
0212     u32 con;
0213 
0214     con = __raw_readl(chip->base);
0215     con >>= off * 2;
0216     con &= 3;
0217 
0218     /* this conversion works for IN and OUT as well as special mode */
0219     return S3C_GPIO_SPECIAL(con);
0220 }
0221 
0222 /*
0223  * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
0224  * @chip: The gpio chip that is being configured.
0225  * @off: The offset for the GPIO being configured.
0226  * @cfg: The configuration value to set.
0227  *
0228  * This helper deal with the GPIO cases where the control register has 4 bits
0229  * of control per GPIO, generally in the form of:
0230  *  0000 = Input
0231  *  0001 = Output
0232  *  others = Special functions (dependent on bank)
0233  *
0234  * Note, since the code to deal with the case where there are two control
0235  * registers instead of one, we do not have a separate set of functions for
0236  * each case.
0237  */
0238 
0239 static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
0240                     unsigned int off, unsigned int cfg)
0241 {
0242     void __iomem *reg = chip->base;
0243     unsigned int shift = (off & 7) * 4;
0244     u32 con;
0245 
0246     if (off < 8 && chip->chip.ngpio > 8)
0247         reg -= 4;
0248 
0249     if (samsung_gpio_is_cfg_special(cfg)) {
0250         cfg &= 0xf;
0251         cfg <<= shift;
0252     }
0253 
0254     con = __raw_readl(reg);
0255     con &= ~(0xf << shift);
0256     con |= cfg;
0257     __raw_writel(con, reg);
0258 
0259     return 0;
0260 }
0261 
0262 /*
0263  * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
0264  * @chip: The gpio chip that is being configured.
0265  * @off: The offset for the GPIO being configured.
0266  *
0267  * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
0268  * register setting into a value the software can use, such as could be passed
0269  * to samsung_gpio_setcfg_4bit().
0270  *
0271  * @sa samsung_gpio_getcfg_2bit
0272  */
0273 
0274 static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
0275                      unsigned int off)
0276 {
0277     void __iomem *reg = chip->base;
0278     unsigned int shift = (off & 7) * 4;
0279     u32 con;
0280 
0281     if (off < 8 && chip->chip.ngpio > 8)
0282         reg -= 4;
0283 
0284     con = __raw_readl(reg);
0285     con >>= shift;
0286     con &= 0xf;
0287 
0288     /* this conversion works for IN and OUT as well as special mode */
0289     return S3C_GPIO_SPECIAL(con);
0290 }
0291 
0292 #ifdef CONFIG_PLAT_S3C24XX
0293 /*
0294  * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
0295  * @chip: The gpio chip that is being configured.
0296  * @off: The offset for the GPIO being configured.
0297  * @cfg: The configuration value to set.
0298  *
0299  * This helper deal with the GPIO cases where the control register
0300  * has one bit of configuration for the gpio, where setting the bit
0301  * means the pin is in special function mode and unset means output.
0302  */
0303 
0304 static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
0305                      unsigned int off, unsigned int cfg)
0306 {
0307     void __iomem *reg = chip->base;
0308     unsigned int shift = off;
0309     u32 con;
0310 
0311     if (samsung_gpio_is_cfg_special(cfg)) {
0312         cfg &= 0xf;
0313 
0314         /* Map output to 0, and SFN2 to 1 */
0315         cfg -= 1;
0316         if (cfg > 1)
0317             return -EINVAL;
0318 
0319         cfg <<= shift;
0320     }
0321 
0322     con = __raw_readl(reg);
0323     con &= ~(0x1 << shift);
0324     con |= cfg;
0325     __raw_writel(con, reg);
0326 
0327     return 0;
0328 }
0329 
0330 /*
0331  * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
0332  * @chip: The gpio chip that is being configured.
0333  * @off: The offset for the GPIO being configured.
0334  *
0335  * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
0336  * GPIO configuration value.
0337  *
0338  * @sa samsung_gpio_getcfg_2bit
0339  * @sa samsung_gpio_getcfg_4bit
0340  */
0341 
0342 static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
0343                       unsigned int off)
0344 {
0345     u32 con;
0346 
0347     con = __raw_readl(chip->base);
0348     con >>= off;
0349     con &= 1;
0350     con++;
0351 
0352     return S3C_GPIO_SFN(con);
0353 }
0354 #endif
0355 
0356 static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
0357                        int nr_chips)
0358 {
0359     for (; nr_chips > 0; nr_chips--, chipcfg++) {
0360         if (!chipcfg->set_config)
0361             chipcfg->set_config = samsung_gpio_setcfg_4bit;
0362         if (!chipcfg->get_config)
0363             chipcfg->get_config = samsung_gpio_getcfg_4bit;
0364         if (!chipcfg->set_pull)
0365             chipcfg->set_pull = samsung_gpio_setpull_updown;
0366         if (!chipcfg->get_pull)
0367             chipcfg->get_pull = samsung_gpio_getpull_updown;
0368     }
0369 }
0370 
0371 struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
0372     .set_config = samsung_gpio_setcfg_2bit,
0373     .get_config = samsung_gpio_getcfg_2bit,
0374 };
0375 
0376 #ifdef CONFIG_PLAT_S3C24XX
0377 static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
0378     .set_config = s3c24xx_gpio_setcfg_abank,
0379     .get_config = s3c24xx_gpio_getcfg_abank,
0380 };
0381 #endif
0382 
0383 static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
0384     [0] = {
0385         .cfg_eint   = 0x0,
0386     },
0387     [1] = {
0388         .cfg_eint   = 0x3,
0389     },
0390     [2] = {
0391         .cfg_eint   = 0x7,
0392     },
0393     [3] = {
0394         .cfg_eint   = 0xF,
0395     },
0396     [4] = {
0397         .cfg_eint   = 0x0,
0398         .set_config = samsung_gpio_setcfg_2bit,
0399         .get_config = samsung_gpio_getcfg_2bit,
0400     },
0401     [5] = {
0402         .cfg_eint   = 0x2,
0403         .set_config = samsung_gpio_setcfg_2bit,
0404         .get_config = samsung_gpio_getcfg_2bit,
0405     },
0406     [6] = {
0407         .cfg_eint   = 0x3,
0408         .set_config = samsung_gpio_setcfg_2bit,
0409         .get_config = samsung_gpio_getcfg_2bit,
0410     },
0411     [7] = {
0412         .set_config = samsung_gpio_setcfg_2bit,
0413         .get_config = samsung_gpio_getcfg_2bit,
0414     },
0415 };
0416 
0417 /*
0418  * Default routines for controlling GPIO, based on the original S3C24XX
0419  * GPIO functions which deal with the case where each gpio bank of the
0420  * chip is as following:
0421  *
0422  * base + 0x00: Control register, 2 bits per gpio
0423  *          gpio n: 2 bits starting at (2*n)
0424  *      00 = input, 01 = output, others mean special-function
0425  * base + 0x04: Data register, 1 bit per gpio
0426  *      bit n: data bit n
0427 */
0428 
0429 static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
0430 {
0431     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0432     void __iomem *base = ourchip->base;
0433     unsigned long flags;
0434     unsigned long con;
0435 
0436     samsung_gpio_lock(ourchip, flags);
0437 
0438     con = __raw_readl(base + 0x00);
0439     con &= ~(3 << (offset * 2));
0440 
0441     __raw_writel(con, base + 0x00);
0442 
0443     samsung_gpio_unlock(ourchip, flags);
0444     return 0;
0445 }
0446 
0447 static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
0448                        unsigned offset, int value)
0449 {
0450     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0451     void __iomem *base = ourchip->base;
0452     unsigned long flags;
0453     unsigned long dat;
0454     unsigned long con;
0455 
0456     samsung_gpio_lock(ourchip, flags);
0457 
0458     dat = __raw_readl(base + 0x04);
0459     dat &= ~(1 << offset);
0460     if (value)
0461         dat |= 1 << offset;
0462     __raw_writel(dat, base + 0x04);
0463 
0464     con = __raw_readl(base + 0x00);
0465     con &= ~(3 << (offset * 2));
0466     con |= 1 << (offset * 2);
0467 
0468     __raw_writel(con, base + 0x00);
0469     __raw_writel(dat, base + 0x04);
0470 
0471     samsung_gpio_unlock(ourchip, flags);
0472     return 0;
0473 }
0474 
0475 /*
0476  * The samsung_gpiolib_4bit routines are to control the gpio banks where
0477  * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
0478  * following example:
0479  *
0480  * base + 0x00: Control register, 4 bits per gpio
0481  *      gpio n: 4 bits starting at (4*n)
0482  *      0000 = input, 0001 = output, others mean special-function
0483  * base + 0x04: Data register, 1 bit per gpio
0484  *      bit n: data bit n
0485  *
0486  * Note, since the data register is one bit per gpio and is at base + 0x4
0487  * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
0488  * state of the output.
0489  */
0490 
0491 static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
0492                       unsigned int offset)
0493 {
0494     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0495     void __iomem *base = ourchip->base;
0496     unsigned long con;
0497 
0498     con = __raw_readl(base + GPIOCON_OFF);
0499     if (ourchip->bitmap_gpio_int & BIT(offset))
0500         con |= 0xf << con_4bit_shift(offset);
0501     else
0502         con &= ~(0xf << con_4bit_shift(offset));
0503     __raw_writel(con, base + GPIOCON_OFF);
0504 
0505     pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
0506 
0507     return 0;
0508 }
0509 
0510 static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
0511                        unsigned int offset, int value)
0512 {
0513     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0514     void __iomem *base = ourchip->base;
0515     unsigned long con;
0516     unsigned long dat;
0517 
0518     con = __raw_readl(base + GPIOCON_OFF);
0519     con &= ~(0xf << con_4bit_shift(offset));
0520     con |= 0x1 << con_4bit_shift(offset);
0521 
0522     dat = __raw_readl(base + GPIODAT_OFF);
0523 
0524     if (value)
0525         dat |= 1 << offset;
0526     else
0527         dat &= ~(1 << offset);
0528 
0529     __raw_writel(dat, base + GPIODAT_OFF);
0530     __raw_writel(con, base + GPIOCON_OFF);
0531     __raw_writel(dat, base + GPIODAT_OFF);
0532 
0533     pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
0534 
0535     return 0;
0536 }
0537 
0538 /*
0539  * The next set of routines are for the case where the GPIO configuration
0540  * registers are 4 bits per GPIO but there is more than one register (the
0541  * bank has more than 8 GPIOs.
0542  *
0543  * This case is the similar to the 4 bit case, but the registers are as
0544  * follows:
0545  *
0546  * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
0547  *      gpio n: 4 bits starting at (4*n)
0548  *      0000 = input, 0001 = output, others mean special-function
0549  * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
0550  *      gpio n: 4 bits starting at (4*n)
0551  *      0000 = input, 0001 = output, others mean special-function
0552  * base + 0x08: Data register, 1 bit per gpio
0553  *      bit n: data bit n
0554  *
0555  * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
0556  * routines we store the 'base + 0x4' address so that these routines see
0557  * the data register at ourchip->base + 0x04.
0558  */
0559 
0560 static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
0561                        unsigned int offset)
0562 {
0563     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0564     void __iomem *base = ourchip->base;
0565     void __iomem *regcon = base;
0566     unsigned long con;
0567 
0568     if (offset > 7)
0569         offset -= 8;
0570     else
0571         regcon -= 4;
0572 
0573     con = __raw_readl(regcon);
0574     con &= ~(0xf << con_4bit_shift(offset));
0575     __raw_writel(con, regcon);
0576 
0577     pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
0578 
0579     return 0;
0580 }
0581 
0582 static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
0583                     unsigned int offset, int value)
0584 {
0585     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0586     void __iomem *base = ourchip->base;
0587     void __iomem *regcon = base;
0588     unsigned long con;
0589     unsigned long dat;
0590     unsigned con_offset = offset;
0591 
0592     if (con_offset > 7)
0593         con_offset -= 8;
0594     else
0595         regcon -= 4;
0596 
0597     con = __raw_readl(regcon);
0598     con &= ~(0xf << con_4bit_shift(con_offset));
0599     con |= 0x1 << con_4bit_shift(con_offset);
0600 
0601     dat = __raw_readl(base + GPIODAT_OFF);
0602 
0603     if (value)
0604         dat |= 1 << offset;
0605     else
0606         dat &= ~(1 << offset);
0607 
0608     __raw_writel(dat, base + GPIODAT_OFF);
0609     __raw_writel(con, regcon);
0610     __raw_writel(dat, base + GPIODAT_OFF);
0611 
0612     pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
0613 
0614     return 0;
0615 }
0616 
0617 #ifdef CONFIG_PLAT_S3C24XX
0618 /* The next set of routines are for the case of s3c24xx bank a */
0619 
0620 static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
0621 {
0622     return -EINVAL;
0623 }
0624 
0625 static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
0626                     unsigned offset, int value)
0627 {
0628     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0629     void __iomem *base = ourchip->base;
0630     unsigned long flags;
0631     unsigned long dat;
0632     unsigned long con;
0633 
0634     local_irq_save(flags);
0635 
0636     con = __raw_readl(base + 0x00);
0637     dat = __raw_readl(base + 0x04);
0638 
0639     dat &= ~(1 << offset);
0640     if (value)
0641         dat |= 1 << offset;
0642 
0643     __raw_writel(dat, base + 0x04);
0644 
0645     con &= ~(1 << offset);
0646 
0647     __raw_writel(con, base + 0x00);
0648     __raw_writel(dat, base + 0x04);
0649 
0650     local_irq_restore(flags);
0651     return 0;
0652 }
0653 #endif
0654 
0655 static void samsung_gpiolib_set(struct gpio_chip *chip,
0656                 unsigned offset, int value)
0657 {
0658     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0659     void __iomem *base = ourchip->base;
0660     unsigned long flags;
0661     unsigned long dat;
0662 
0663     samsung_gpio_lock(ourchip, flags);
0664 
0665     dat = __raw_readl(base + 0x04);
0666     dat &= ~(1 << offset);
0667     if (value)
0668         dat |= 1 << offset;
0669     __raw_writel(dat, base + 0x04);
0670 
0671     samsung_gpio_unlock(ourchip, flags);
0672 }
0673 
0674 static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
0675 {
0676     struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0677     unsigned long val;
0678 
0679     val = __raw_readl(ourchip->base + 0x04);
0680     val >>= offset;
0681     val &= 1;
0682 
0683     return val;
0684 }
0685 
0686 /*
0687  * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
0688  * for use with the configuration calls, and other parts of the s3c gpiolib
0689  * support code.
0690  *
0691  * Not all s3c support code will need this, as some configurations of cpu
0692  * may only support one or two different configuration options and have an
0693  * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
0694  * the machine support file should provide its own samsung_gpiolib_getchip()
0695  * and any other necessary functions.
0696  */
0697 
0698 #ifdef CONFIG_S3C_GPIO_TRACK
0699 struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
0700 
0701 static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
0702 {
0703     unsigned int gpn;
0704     int i;
0705 
0706     gpn = chip->chip.base;
0707     for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
0708         BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
0709         s3c_gpios[gpn] = chip;
0710     }
0711 }
0712 #endif /* CONFIG_S3C_GPIO_TRACK */
0713 
0714 /*
0715  * samsung_gpiolib_add() - add the Samsung gpio_chip.
0716  * @chip: The chip to register
0717  *
0718  * This is a wrapper to gpiochip_add() that takes our specific gpio chip
0719  * information and makes the necessary alterations for the platform and
0720  * notes the information for use with the configuration systems and any
0721  * other parts of the system.
0722  */
0723 
0724 static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
0725 {
0726     struct gpio_chip *gc = &chip->chip;
0727     int ret;
0728 
0729     BUG_ON(!chip->base);
0730     BUG_ON(!gc->label);
0731     BUG_ON(!gc->ngpio);
0732 
0733     spin_lock_init(&chip->lock);
0734 
0735     if (!gc->direction_input)
0736         gc->direction_input = samsung_gpiolib_2bit_input;
0737     if (!gc->direction_output)
0738         gc->direction_output = samsung_gpiolib_2bit_output;
0739     if (!gc->set)
0740         gc->set = samsung_gpiolib_set;
0741     if (!gc->get)
0742         gc->get = samsung_gpiolib_get;
0743 
0744 #ifdef CONFIG_PM
0745     if (chip->pm != NULL) {
0746         if (!chip->pm->save || !chip->pm->resume)
0747             pr_err("gpio: %s has missing PM functions\n",
0748                    gc->label);
0749     } else
0750         pr_err("gpio: %s has no PM function\n", gc->label);
0751 #endif
0752 
0753     /* gpiochip_add() prints own failure message on error. */
0754     ret = gpiochip_add_data(gc, chip);
0755     if (ret >= 0)
0756         s3c_gpiolib_track(chip);
0757 }
0758 
0759 static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
0760                          int nr_chips, void __iomem *base)
0761 {
0762     int i;
0763     struct gpio_chip *gc = &chip->chip;
0764 
0765     for (i = 0 ; i < nr_chips; i++, chip++) {
0766         /* skip banks not present on SoC */
0767         if (chip->chip.base >= S3C_GPIO_END)
0768             continue;
0769 
0770         if (!chip->config)
0771             chip->config = &s3c24xx_gpiocfg_default;
0772         if (!chip->pm)
0773             chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
0774         if ((base != NULL) && (chip->base == NULL))
0775             chip->base = base + ((i) * 0x10);
0776 
0777         if (!gc->direction_input)
0778             gc->direction_input = samsung_gpiolib_2bit_input;
0779         if (!gc->direction_output)
0780             gc->direction_output = samsung_gpiolib_2bit_output;
0781 
0782         samsung_gpiolib_add(chip);
0783     }
0784 }
0785 
0786 static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
0787                           int nr_chips, void __iomem *base,
0788                           unsigned int offset)
0789 {
0790     int i;
0791 
0792     for (i = 0 ; i < nr_chips; i++, chip++) {
0793         chip->chip.direction_input = samsung_gpiolib_2bit_input;
0794         chip->chip.direction_output = samsung_gpiolib_2bit_output;
0795 
0796         if (!chip->config)
0797             chip->config = &samsung_gpio_cfgs[7];
0798         if (!chip->pm)
0799             chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
0800         if ((base != NULL) && (chip->base == NULL))
0801             chip->base = base + ((i) * offset);
0802 
0803         samsung_gpiolib_add(chip);
0804     }
0805 }
0806 
0807 /*
0808  * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
0809  * @chip: The gpio chip that is being configured.
0810  * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
0811  *
0812  * This helper deal with the GPIO cases where the control register has 4 bits
0813  * of control per GPIO, generally in the form of:
0814  * 0000 = Input
0815  * 0001 = Output
0816  * others = Special functions (dependent on bank)
0817  *
0818  * Note, since the code to deal with the case where there are two control
0819  * registers instead of one, we do not have a separate set of function
0820  * (samsung_gpiolib_add_4bit2_chips)for each case.
0821  */
0822 
0823 static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
0824                           int nr_chips, void __iomem *base)
0825 {
0826     int i;
0827 
0828     for (i = 0 ; i < nr_chips; i++, chip++) {
0829         chip->chip.direction_input = samsung_gpiolib_4bit_input;
0830         chip->chip.direction_output = samsung_gpiolib_4bit_output;
0831 
0832         if (!chip->config)
0833             chip->config = &samsung_gpio_cfgs[2];
0834         if (!chip->pm)
0835             chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
0836         if ((base != NULL) && (chip->base == NULL))
0837             chip->base = base + ((i) * 0x20);
0838 
0839         chip->bitmap_gpio_int = 0;
0840 
0841         samsung_gpiolib_add(chip);
0842     }
0843 }
0844 
0845 static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
0846                            int nr_chips)
0847 {
0848     for (; nr_chips > 0; nr_chips--, chip++) {
0849         chip->chip.direction_input = samsung_gpiolib_4bit2_input;
0850         chip->chip.direction_output = samsung_gpiolib_4bit2_output;
0851 
0852         if (!chip->config)
0853             chip->config = &samsung_gpio_cfgs[2];
0854         if (!chip->pm)
0855             chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
0856 
0857         samsung_gpiolib_add(chip);
0858     }
0859 }
0860 
0861 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
0862 {
0863     struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
0864 
0865     return samsung_chip->irq_base + offset;
0866 }
0867 
0868 #ifdef CONFIG_PLAT_S3C24XX
0869 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
0870 {
0871     if (offset < 4) {
0872         if (soc_is_s3c2412())
0873             return IRQ_EINT0_2412 + offset;
0874         else
0875             return IRQ_EINT0 + offset;
0876     }
0877 
0878     if (offset < 8)
0879         return IRQ_EINT4 + offset - 4;
0880 
0881     return -EINVAL;
0882 }
0883 #endif
0884 
0885 #ifdef CONFIG_ARCH_S3C64XX
0886 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
0887 {
0888     return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
0889 }
0890 
0891 static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
0892 {
0893     return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
0894 }
0895 #endif
0896 
0897 struct samsung_gpio_chip s3c24xx_gpios[] = {
0898 #ifdef CONFIG_PLAT_S3C24XX
0899     {
0900         .config = &s3c24xx_gpiocfg_banka,
0901         .chip   = {
0902             .base           = S3C2410_GPA(0),
0903             .owner          = THIS_MODULE,
0904             .label          = "GPIOA",
0905             .ngpio          = 27,
0906             .direction_input    = s3c24xx_gpiolib_banka_input,
0907             .direction_output   = s3c24xx_gpiolib_banka_output,
0908         },
0909     }, {
0910         .chip   = {
0911             .base   = S3C2410_GPB(0),
0912             .owner  = THIS_MODULE,
0913             .label  = "GPIOB",
0914             .ngpio  = 11,
0915         },
0916     }, {
0917         .chip   = {
0918             .base   = S3C2410_GPC(0),
0919             .owner  = THIS_MODULE,
0920             .label  = "GPIOC",
0921             .ngpio  = 16,
0922         },
0923     }, {
0924         .chip   = {
0925             .base   = S3C2410_GPD(0),
0926             .owner  = THIS_MODULE,
0927             .label  = "GPIOD",
0928             .ngpio  = 16,
0929         },
0930     }, {
0931         .chip   = {
0932             .base   = S3C2410_GPE(0),
0933             .label  = "GPIOE",
0934             .owner  = THIS_MODULE,
0935             .ngpio  = 16,
0936         },
0937     }, {
0938         .chip   = {
0939             .base   = S3C2410_GPF(0),
0940             .owner  = THIS_MODULE,
0941             .label  = "GPIOF",
0942             .ngpio  = 8,
0943             .to_irq = s3c24xx_gpiolib_fbank_to_irq,
0944         },
0945     }, {
0946         .irq_base = IRQ_EINT8,
0947         .chip   = {
0948             .base   = S3C2410_GPG(0),
0949             .owner  = THIS_MODULE,
0950             .label  = "GPIOG",
0951             .ngpio  = 16,
0952             .to_irq = samsung_gpiolib_to_irq,
0953         },
0954     }, {
0955         .chip   = {
0956             .base   = S3C2410_GPH(0),
0957             .owner  = THIS_MODULE,
0958             .label  = "GPIOH",
0959             .ngpio  = 15,
0960         },
0961     },
0962         /* GPIOS for the S3C2443 and later devices. */
0963     {
0964         .base   = S3C2440_GPJCON,
0965         .chip   = {
0966             .base   = S3C2410_GPJ(0),
0967             .owner  = THIS_MODULE,
0968             .label  = "GPIOJ",
0969             .ngpio  = 16,
0970         },
0971     }, {
0972         .base   = S3C2443_GPKCON,
0973         .chip   = {
0974             .base   = S3C2410_GPK(0),
0975             .owner  = THIS_MODULE,
0976             .label  = "GPIOK",
0977             .ngpio  = 16,
0978         },
0979     }, {
0980         .base   = S3C2443_GPLCON,
0981         .chip   = {
0982             .base   = S3C2410_GPL(0),
0983             .owner  = THIS_MODULE,
0984             .label  = "GPIOL",
0985             .ngpio  = 15,
0986         },
0987     }, {
0988         .base   = S3C2443_GPMCON,
0989         .chip   = {
0990             .base   = S3C2410_GPM(0),
0991             .owner  = THIS_MODULE,
0992             .label  = "GPIOM",
0993             .ngpio  = 2,
0994         },
0995     },
0996 #endif
0997 };
0998 
0999 /*
1000  * GPIO bank summary:
1001  *
1002  * Bank GPIOs   Style   SlpCon  ExtInt Group
1003  * A    8   4Bit    Yes 1
1004  * B    7   4Bit    Yes 1
1005  * C    8   4Bit    Yes 2
1006  * D    5   4Bit    Yes 3
1007  * E    5   4Bit    Yes None
1008  * F    16  2Bit    Yes 4 [1]
1009  * G    7   4Bit    Yes 5
1010  * H    10  4Bit[2] Yes 6
1011  * I    16  2Bit    Yes None
1012  * J    12  2Bit    Yes None
1013  * K    16  4Bit[2] No  None
1014  * L    15  4Bit[2] No  None
1015  * M    6   4Bit    No  IRQ_EINT
1016  * N    16  2Bit    No  IRQ_EINT
1017  * O    16  2Bit    Yes 7
1018  * P    15  2Bit    Yes 8
1019  * Q    9   2Bit    Yes 9
1020  *
1021  * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1022  * [2] BANK has two control registers, GPxCON0 and GPxCON1
1023  */
1024 
1025 static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1026 #ifdef CONFIG_ARCH_S3C64XX
1027     {
1028         .chip   = {
1029             .base   = S3C64XX_GPA(0),
1030             .ngpio  = S3C64XX_GPIO_A_NR,
1031             .label  = "GPA",
1032         },
1033     }, {
1034         .chip   = {
1035             .base   = S3C64XX_GPB(0),
1036             .ngpio  = S3C64XX_GPIO_B_NR,
1037             .label  = "GPB",
1038         },
1039     }, {
1040         .chip   = {
1041             .base   = S3C64XX_GPC(0),
1042             .ngpio  = S3C64XX_GPIO_C_NR,
1043             .label  = "GPC",
1044         },
1045     }, {
1046         .chip   = {
1047             .base   = S3C64XX_GPD(0),
1048             .ngpio  = S3C64XX_GPIO_D_NR,
1049             .label  = "GPD",
1050         },
1051     }, {
1052         .config = &samsung_gpio_cfgs[0],
1053         .chip   = {
1054             .base   = S3C64XX_GPE(0),
1055             .ngpio  = S3C64XX_GPIO_E_NR,
1056             .label  = "GPE",
1057         },
1058     }, {
1059         .base   = S3C64XX_GPG_BASE,
1060         .chip   = {
1061             .base   = S3C64XX_GPG(0),
1062             .ngpio  = S3C64XX_GPIO_G_NR,
1063             .label  = "GPG",
1064         },
1065     }, {
1066         .base   = S3C64XX_GPM_BASE,
1067         .config = &samsung_gpio_cfgs[1],
1068         .chip   = {
1069             .base   = S3C64XX_GPM(0),
1070             .ngpio  = S3C64XX_GPIO_M_NR,
1071             .label  = "GPM",
1072             .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1073         },
1074     },
1075 #endif
1076 };
1077 
1078 static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1079 #ifdef CONFIG_ARCH_S3C64XX
1080     {
1081         .base   = S3C64XX_GPH_BASE + 0x4,
1082         .chip   = {
1083             .base   = S3C64XX_GPH(0),
1084             .ngpio  = S3C64XX_GPIO_H_NR,
1085             .label  = "GPH",
1086         },
1087     }, {
1088         .base   = S3C64XX_GPK_BASE + 0x4,
1089         .config = &samsung_gpio_cfgs[0],
1090         .chip   = {
1091             .base   = S3C64XX_GPK(0),
1092             .ngpio  = S3C64XX_GPIO_K_NR,
1093             .label  = "GPK",
1094         },
1095     }, {
1096         .base   = S3C64XX_GPL_BASE + 0x4,
1097         .config = &samsung_gpio_cfgs[1],
1098         .chip   = {
1099             .base   = S3C64XX_GPL(0),
1100             .ngpio  = S3C64XX_GPIO_L_NR,
1101             .label  = "GPL",
1102             .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1103         },
1104     },
1105 #endif
1106 };
1107 
1108 static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1109 #ifdef CONFIG_ARCH_S3C64XX
1110     {
1111         .base   = S3C64XX_GPF_BASE,
1112         .config = &samsung_gpio_cfgs[6],
1113         .chip   = {
1114             .base   = S3C64XX_GPF(0),
1115             .ngpio  = S3C64XX_GPIO_F_NR,
1116             .label  = "GPF",
1117         },
1118     }, {
1119         .config = &samsung_gpio_cfgs[7],
1120         .chip   = {
1121             .base   = S3C64XX_GPI(0),
1122             .ngpio  = S3C64XX_GPIO_I_NR,
1123             .label  = "GPI",
1124         },
1125     }, {
1126         .config = &samsung_gpio_cfgs[7],
1127         .chip   = {
1128             .base   = S3C64XX_GPJ(0),
1129             .ngpio  = S3C64XX_GPIO_J_NR,
1130             .label  = "GPJ",
1131         },
1132     }, {
1133         .config = &samsung_gpio_cfgs[6],
1134         .chip   = {
1135             .base   = S3C64XX_GPO(0),
1136             .ngpio  = S3C64XX_GPIO_O_NR,
1137             .label  = "GPO",
1138         },
1139     }, {
1140         .config = &samsung_gpio_cfgs[6],
1141         .chip   = {
1142             .base   = S3C64XX_GPP(0),
1143             .ngpio  = S3C64XX_GPIO_P_NR,
1144             .label  = "GPP",
1145         },
1146     }, {
1147         .config = &samsung_gpio_cfgs[6],
1148         .chip   = {
1149             .base   = S3C64XX_GPQ(0),
1150             .ngpio  = S3C64XX_GPIO_Q_NR,
1151             .label  = "GPQ",
1152         },
1153     }, {
1154         .base   = S3C64XX_GPN_BASE,
1155         .irq_base = IRQ_EINT(0),
1156         .config = &samsung_gpio_cfgs[5],
1157         .chip   = {
1158             .base   = S3C64XX_GPN(0),
1159             .ngpio  = S3C64XX_GPIO_N_NR,
1160             .label  = "GPN",
1161             .to_irq = samsung_gpiolib_to_irq,
1162         },
1163     },
1164 #endif
1165 };
1166 
1167 /* TODO: cleanup soc_is_* */
1168 static __init int samsung_gpiolib_init(void)
1169 {
1170     /*
1171      * Currently there are two drivers that can provide GPIO support for
1172      * Samsung SoCs. For device tree enabled platforms, the new
1173      * pinctrl-samsung driver is used, providing both GPIO and pin control
1174      * interfaces. For legacy (non-DT) platforms this driver is used.
1175      */
1176     if (of_have_populated_dt())
1177         return 0;
1178 
1179     if (soc_is_s3c24xx()) {
1180         samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1181                 ARRAY_SIZE(samsung_gpio_cfgs));
1182         s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1183                 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1184     } else if (soc_is_s3c64xx()) {
1185         samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1186                 ARRAY_SIZE(samsung_gpio_cfgs));
1187         samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1188                 ARRAY_SIZE(s3c64xx_gpios_2bit),
1189                 S3C64XX_VA_GPIO + 0xE0, 0x20);
1190         samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1191                 ARRAY_SIZE(s3c64xx_gpios_4bit),
1192                 S3C64XX_VA_GPIO);
1193         samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1194                 ARRAY_SIZE(s3c64xx_gpios_4bit2));
1195     }
1196 
1197     return 0;
1198 }
1199 core_initcall(samsung_gpiolib_init);
1200 
1201 int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1202 {
1203     struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1204     unsigned long flags;
1205     int offset;
1206     int ret;
1207 
1208     if (!chip)
1209         return -EINVAL;
1210 
1211     offset = pin - chip->chip.base;
1212 
1213     samsung_gpio_lock(chip, flags);
1214     ret = samsung_gpio_do_setcfg(chip, offset, config);
1215     samsung_gpio_unlock(chip, flags);
1216 
1217     return ret;
1218 }
1219 EXPORT_SYMBOL(s3c_gpio_cfgpin);
1220 
1221 int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1222               unsigned int cfg)
1223 {
1224     int ret;
1225 
1226     for (; nr > 0; nr--, start++) {
1227         ret = s3c_gpio_cfgpin(start, cfg);
1228         if (ret != 0)
1229             return ret;
1230     }
1231 
1232     return 0;
1233 }
1234 EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1235 
1236 int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1237               unsigned int cfg, samsung_gpio_pull_t pull)
1238 {
1239     int ret;
1240 
1241     for (; nr > 0; nr--, start++) {
1242         s3c_gpio_setpull(start, pull);
1243         ret = s3c_gpio_cfgpin(start, cfg);
1244         if (ret != 0)
1245             return ret;
1246     }
1247 
1248     return 0;
1249 }
1250 EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1251 
1252 unsigned s3c_gpio_getcfg(unsigned int pin)
1253 {
1254     struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1255     unsigned long flags;
1256     unsigned ret = 0;
1257     int offset;
1258 
1259     if (chip) {
1260         offset = pin - chip->chip.base;
1261 
1262         samsung_gpio_lock(chip, flags);
1263         ret = samsung_gpio_do_getcfg(chip, offset);
1264         samsung_gpio_unlock(chip, flags);
1265     }
1266 
1267     return ret;
1268 }
1269 EXPORT_SYMBOL(s3c_gpio_getcfg);
1270 
1271 int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1272 {
1273     struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1274     unsigned long flags;
1275     int offset, ret;
1276 
1277     if (!chip)
1278         return -EINVAL;
1279 
1280     offset = pin - chip->chip.base;
1281 
1282     samsung_gpio_lock(chip, flags);
1283     ret = samsung_gpio_do_setpull(chip, offset, pull);
1284     samsung_gpio_unlock(chip, flags);
1285 
1286     return ret;
1287 }
1288 EXPORT_SYMBOL(s3c_gpio_setpull);
1289 
1290 samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1291 {
1292     struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1293     unsigned long flags;
1294     int offset;
1295     u32 pup = 0;
1296 
1297     if (chip) {
1298         offset = pin - chip->chip.base;
1299 
1300         samsung_gpio_lock(chip, flags);
1301         pup = samsung_gpio_do_getpull(chip, offset);
1302         samsung_gpio_unlock(chip, flags);
1303     }
1304 
1305     return (__force samsung_gpio_pull_t)pup;
1306 }
1307 EXPORT_SYMBOL(s3c_gpio_getpull);
1308 
1309 #ifdef CONFIG_PLAT_S3C24XX
1310 unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1311 {
1312     unsigned long flags;
1313     unsigned long misccr;
1314 
1315     local_irq_save(flags);
1316     misccr = __raw_readl(S3C24XX_MISCCR);
1317     misccr &= ~clear;
1318     misccr ^= change;
1319     __raw_writel(misccr, S3C24XX_MISCCR);
1320     local_irq_restore(flags);
1321 
1322     return misccr;
1323 }
1324 EXPORT_SYMBOL(s3c2410_modify_misccr);
1325 #endif