diff options
Diffstat (limited to 'drivers/gpio/gpio-s5pv210.c')
-rw-r--r-- | drivers/gpio/gpio-s5pv210.c | 345 |
1 files changed, 343 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c index 1ba20a7..955a0f5 100644 --- a/drivers/gpio/gpio-s5pv210.c +++ b/drivers/gpio/gpio-s5pv210.c @@ -14,6 +14,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/module.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> @@ -222,6 +223,174 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { .label = "MP05", }, }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP06(0), + .ngpio = S5PV210_GPIO_MP06_NR, + .label = "MP06", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP07(0), + .ngpio = S5PV210_GPIO_MP07_NR, + .label = "MP07", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP10(0), + .ngpio = S5PV210_GPIO_MP10_NR, + .label = "MP10", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP11(0), + .ngpio = S5PV210_GPIO_MP11_NR, + .label = "MP11", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP12(0), + .ngpio = S5PV210_GPIO_MP12_NR, + .label = "MP12", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP13(0), + .ngpio = S5PV210_GPIO_MP13_NR, + .label = "MP13", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP14(0), + .ngpio = S5PV210_GPIO_MP14_NR, + .label = "MP14", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP15(0), + .ngpio = S5PV210_GPIO_MP15_NR, + .label = "MP15", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP16(0), + .ngpio = S5PV210_GPIO_MP16_NR, + .label = "MP16", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP17(0), + .ngpio = S5PV210_GPIO_MP17_NR, + .label = "MP17", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP18(0), + .ngpio = S5PV210_GPIO_MP18_NR, + .label = "MP18", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP20(0), + .ngpio = S5PV210_GPIO_MP20_NR, + .label = "MP20", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP21(0), + .ngpio = S5PV210_GPIO_MP21_NR, + .label = "MP21", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP22(0), + .ngpio = S5PV210_GPIO_MP22_NR, + .label = "MP22", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP23(0), + .ngpio = S5PV210_GPIO_MP23_NR, + .label = "MP23", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP24(0), + .ngpio = S5PV210_GPIO_MP24_NR, + .label = "MP24", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP25(0), + .ngpio = S5PV210_GPIO_MP25_NR, + .label = "MP25", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP26(0), + .ngpio = S5PV210_GPIO_MP26_NR, + .label = "MP26", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP27(0), + .ngpio = S5PV210_GPIO_MP27_NR, + .label = "MP27", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP28(0), + .ngpio = S5PV210_GPIO_MP28_NR, + .label = "MP28", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_ETC0(0), + .ngpio = S5PV210_GPIO_ETC0_NR, + .label = "ETC0", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_ETC1(0), + .ngpio = S5PV210_GPIO_ETC1_NR, + .label = "ETC1", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_ETC2(0), + .ngpio = S5PV210_GPIO_ETC2_NR, + .label = "ETC2", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_ETC4(0), + .ngpio = S5PV210_GPIO_ETC4_NR, + .label = "ETC4", + }, + }, { .base = (S5P_VA_GPIO + 0xC00), .config = &gpio_cfg_noint, .irq_base = IRQ_EINT(0), @@ -264,7 +433,180 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { }, }; -static __init int s5pv210_gpiolib_init(void) +/* S5PV210 machine dependent GPIO help function */ +int s3c_gpio_slp_cfgpin(unsigned int pin, unsigned int config) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + void __iomem *reg; + unsigned long flags; + int offset; + u32 con; + int shift; + + if (!chip) + return -EINVAL; + + if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0))) + return -EINVAL; + + if (config > S3C_GPIO_SLP_PREV) + return -EINVAL; + + reg = chip->base + 0x10; + + offset = pin - chip->chip.base; + shift = offset * 2; + + local_irq_save(flags); + + con = __raw_readl(reg); + con &= ~(3 << shift); + con |= config << shift; + __raw_writel(con, reg); + + local_irq_restore(flags); + return 0; +} + +s3c_gpio_pull_t s3c_gpio_get_slp_cfgpin(unsigned int pin) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + void __iomem *reg; + unsigned long flags; + int offset; + u32 con; + int shift; + + if (!chip) + return -EINVAL; + + if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0))) + return -EINVAL; + + reg = chip->base + 0x10; + + offset = pin - chip->chip.base; + shift = offset * 2; + + local_irq_save(flags); + + con = __raw_readl(reg); + con >>= shift; + con &= 0x3; + + local_irq_restore(flags); + + return (__force s3c_gpio_pull_t)con; +} + +int s3c_gpio_slp_setpull_updown(unsigned int pin, unsigned int config) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + void __iomem *reg; + unsigned long flags; + int offset; + u32 con; + int shift; + + if (!chip) + return -EINVAL; + + if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0))) + return -EINVAL; + + if (config > S3C_GPIO_PULL_UP) + return -EINVAL; + reg = chip->base + 0x14; + + offset = pin - chip->chip.base; + shift = offset * 2; + + local_irq_save(flags); + + con = __raw_readl(reg); + con &= ~(3 << shift); + con |= config << shift; + __raw_writel(con, reg); + + local_irq_restore(flags); + + return 0; +} +EXPORT_SYMBOL(s3c_gpio_slp_setpull_updown); + +int s3c_gpio_set_drvstrength(unsigned int pin, unsigned int config) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + void __iomem *reg; + unsigned long flags; + int offset; + u32 con; + int shift; + + if (!chip) + return -EINVAL; + + if (config > S3C_GPIO_DRVSTR_4X) + return -EINVAL; + + reg = chip->base + 0x0c; + + offset = pin - chip->chip.base; + shift = offset * 2; + + local_irq_save(flags); + + con = __raw_readl(reg); + con &= ~(3 << shift); + con |= config << shift; + + __raw_writel(con, reg); +#ifdef S5PC11X_ALIVEGPIO_STORE + con = __raw_readl(reg); +#endif + + local_irq_restore(flags); + + return 0; +} + +int s3c_gpio_set_slewrate(unsigned int pin, unsigned int config) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + void __iomem *reg; + unsigned long flags; + int offset; + u32 con; + int shift; + + if (!chip) + return -EINVAL; + + if (config > S3C_GPIO_SLEWRATE_SLOW) + return -EINVAL; + + reg = chip->base + 0x0c; + + offset = pin - chip->chip.base; + shift = offset; + + local_irq_save(flags); + + con = __raw_readl(reg); + con &= ~(1 << shift); + con |= config << shift; + + __raw_writel(con, reg); +#ifdef S5PC11X_ALIVEGPIO_STORE + con = __raw_readl(reg); +#endif + + local_irq_restore(flags); + + return 0; +} + +__init int s5pv210_gpiolib_init(void) { struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); @@ -285,4 +627,3 @@ static __init int s5pv210_gpiolib_init(void) return 0; } -core_initcall(s5pv210_gpiolib_init); |