| /* linux/arch/arm/plat-s3c24xx/gpiolib.c |
| * |
| * Copyright (c) 2008-2010 Simtec Electronics |
| * http://armlinux.simtec.co.uk/ |
| * Ben Dooks <ben@simtec.co.uk> |
| * |
| * S3C24XX GPIOlib support |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/module.h> |
| #include <linux/interrupt.h> |
| #include <linux/sysdev.h> |
| #include <linux/ioport.h> |
| #include <linux/io.h> |
| #include <linux/gpio.h> |
| |
| #include <plat/gpio-core.h> |
| #include <plat/gpio-cfg.h> |
| #include <plat/gpio-cfg-helpers.h> |
| #include <mach/hardware.h> |
| #include <asm/irq.h> |
| #include <plat/pm.h> |
| |
| #include <mach/regs-gpio.h> |
| |
| static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset) |
| { |
| return -EINVAL; |
| } |
| |
| static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip, |
| unsigned offset, int value) |
| { |
| struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); |
| void __iomem *base = ourchip->base; |
| unsigned long flags; |
| unsigned long dat; |
| unsigned long con; |
| |
| local_irq_save(flags); |
| |
| con = __raw_readl(base + 0x00); |
| dat = __raw_readl(base + 0x04); |
| |
| dat &= ~(1 << offset); |
| if (value) |
| dat |= 1 << offset; |
| |
| __raw_writel(dat, base + 0x04); |
| |
| con &= ~(1 << offset); |
| |
| __raw_writel(con, base + 0x00); |
| __raw_writel(dat, base + 0x04); |
| |
| local_irq_restore(flags); |
| return 0; |
| } |
| |
| static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset) |
| { |
| if (offset < 4) |
| return IRQ_EINT0 + offset; |
| |
| if (offset < 8) |
| return IRQ_EINT4 + offset - 4; |
| |
| return -EINVAL; |
| } |
| |
| static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset) |
| { |
| return IRQ_EINT8 + offset; |
| } |
| |
| static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { |
| .set_config = s3c_gpio_setcfg_s3c24xx_a, |
| .get_config = s3c_gpio_getcfg_s3c24xx_a, |
| }; |
| |
| struct s3c_gpio_cfg s3c24xx_gpiocfg_default = { |
| .set_config = s3c_gpio_setcfg_s3c24xx, |
| .get_config = s3c_gpio_getcfg_s3c24xx, |
| }; |
| |
| struct s3c_gpio_chip s3c24xx_gpios[] = { |
| [0] = { |
| .base = S3C2410_GPACON, |
| .pm = __gpio_pm(&s3c_gpio_pm_1bit), |
| .config = &s3c24xx_gpiocfg_banka, |
| .chip = { |
| .base = S3C2410_GPA(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOA", |
| .ngpio = 24, |
| .direction_input = s3c24xx_gpiolib_banka_input, |
| .direction_output = s3c24xx_gpiolib_banka_output, |
| }, |
| }, |
| [1] = { |
| .base = S3C2410_GPBCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPB(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOB", |
| .ngpio = 16, |
| }, |
| }, |
| [2] = { |
| .base = S3C2410_GPCCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPC(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOC", |
| .ngpio = 16, |
| }, |
| }, |
| [3] = { |
| .base = S3C2410_GPDCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPD(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOD", |
| .ngpio = 16, |
| }, |
| }, |
| [4] = { |
| .base = S3C2410_GPECON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPE(0), |
| .label = "GPIOE", |
| .owner = THIS_MODULE, |
| .ngpio = 16, |
| }, |
| }, |
| [5] = { |
| .base = S3C2410_GPFCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPF(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOF", |
| .ngpio = 8, |
| .to_irq = s3c24xx_gpiolib_bankf_toirq, |
| }, |
| }, |
| [6] = { |
| .base = S3C2410_GPGCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPG(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOG", |
| .ngpio = 16, |
| .to_irq = s3c24xx_gpiolib_bankg_toirq, |
| }, |
| }, { |
| .base = S3C2410_GPHCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPH(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOH", |
| .ngpio = 11, |
| }, |
| }, |
| /* GPIOS for the S3C2443 and later devices. */ |
| { |
| .base = S3C2440_GPJCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPJ(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOJ", |
| .ngpio = 16, |
| }, |
| }, { |
| .base = S3C2443_GPKCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPK(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOK", |
| .ngpio = 16, |
| }, |
| }, { |
| .base = S3C2443_GPLCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPL(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOL", |
| .ngpio = 15, |
| }, |
| }, { |
| .base = S3C2443_GPMCON, |
| .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
| .chip = { |
| .base = S3C2410_GPM(0), |
| .owner = THIS_MODULE, |
| .label = "GPIOM", |
| .ngpio = 2, |
| }, |
| }, |
| }; |
| |
| |
| static __init int s3c24xx_gpiolib_init(void) |
| { |
| struct s3c_gpio_chip *chip = s3c24xx_gpios; |
| int gpn; |
| |
| for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) { |
| if (!chip->config) |
| chip->config = &s3c24xx_gpiocfg_default; |
| |
| s3c_gpiolib_add(chip); |
| } |
| |
| return 0; |
| } |
| |
| core_initcall(s3c24xx_gpiolib_init); |