summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-10-31 16:14:34 +0000
committerBen Dooks <ben-linux@fluff.org>2008-12-15 23:34:15 +0000
commit21b23664b9354c5449841e401efb9ad523fb898b (patch)
treeb26017929643be8be4e0a562943ef75fa96499d7 /arch
parent89d043c3db22c37523165905708d2fa8062fda86 (diff)
downloadlinux-3.10-21b23664b9354c5449841e401efb9ad523fb898b.tar.gz
linux-3.10-21b23664b9354c5449841e401efb9ad523fb898b.tar.bz2
linux-3.10-21b23664b9354c5449841e401efb9ad523fb898b.zip
[ARM] S3C: Add new GPIO configuration calls
Add new GPIO configuration calls that mesh with the new gpiolib support. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio-core.h34
-rw-r--r--arch/arm/mach-s3c6400/include/mach/gpio-core.h21
-rw-r--r--arch/arm/plat-s3c/Kconfig27
-rw-r--r--arch/arm/plat-s3c/Makefile1
-rw-r--r--arch/arm/plat-s3c/gpio-config.c163
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h176
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-cfg.h110
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-core.h9
-rw-r--r--arch/arm/plat-s3c24xx/gpiolib.c6
-rw-r--r--arch/arm/plat-s3c64xx/Kconfig3
-rw-r--r--arch/arm/plat-s3c64xx/gpiolib.c75
11 files changed, 619 insertions, 6 deletions
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-core.h b/arch/arm/mach-s3c2410/include/mach/gpio-core.h
new file mode 100644
index 00000000000..6c9fbb99ef1
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-core.h
@@ -0,0 +1,34 @@
+/* arch/arm/mach-s3c24100/include/mach/gpio-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C2410 - GPIO core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_CORE_H
+#define __ASM_ARCH_GPIO_CORE_H __FILE__
+
+#include <plat/gpio-core.h>
+#include <mach/regs-gpio.h>
+
+extern struct s3c_gpio_chip s3c24xx_gpios[];
+
+static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+{
+ struct s3c_gpio_chip *chip;
+
+ if (pin > S3C2410_GPG10)
+ return NULL;
+
+ chip = &s3c24xx_gpios[pin/32];
+ return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
+}
+
+#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/gpio-core.h b/arch/arm/mach-s3c6400/include/mach/gpio-core.h
new file mode 100644
index 00000000000..d89aae68b0a
--- /dev/null
+++ b/arch/arm/mach-s3c6400/include/mach/gpio-core.h
@@ -0,0 +1,21 @@
+/* arch/arm/mach-s3c6400/include/mach/gpio-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - GPIO core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_CORE_H
+#define __ASM_ARCH_GPIO_CORE_H __FILE__
+
+/* currently we just include the platform support */
+#include <plat/gpio-core.h>
+
+#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig
index 77fc38f5187..45e62cba595 100644
--- a/arch/arm/plat-s3c/Kconfig
+++ b/arch/arm/plat-s3c/Kconfig
@@ -120,6 +120,33 @@ config S3C_GPIO_TRACK
Internal configuration option to enable the s3c specific gpio
chip tracking if the platform requires it.
+config S3C_GPIO_PULL_UPDOWN
+ bool
+ help
+ Internal configuration to enable the correct GPIO pull helper
+
+config S3C_GPIO_PULL_DOWN
+ bool
+ help
+ Internal configuration to enable the correct GPIO pull helper
+
+config S3C_GPIO_PULL_UP
+ bool
+ help
+ Internal configuration to enable the correct GPIO pull helper
+
+config S3C_GPIO_CFG_S3C24XX
+ bool
+ help
+ Internal configuration to enable S3C24XX style GPIO configuration
+ functions.
+
+config S3C_GPIO_CFG_S3C64XX
+ bool
+ help
+ Internal configuration to enable S3C64XX style GPIO configuration
+ functions.
+
# device definitions to compile in
config S3C_DEV_HSMMC
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
index 4d0299aef7c..68a3451a2d9 100644
--- a/arch/arm/plat-s3c/Makefile
+++ b/arch/arm/plat-s3c/Makefile
@@ -16,6 +16,7 @@ obj-y += time.o
obj-y += clock.o
obj-y += pwm-clock.o
obj-y += gpio.o
+obj-y += gpio-config.o
# devices
diff --git a/arch/arm/plat-s3c/gpio-config.c b/arch/arm/plat-s3c/gpio-config.c
new file mode 100644
index 00000000000..7642b975a99
--- /dev/null
+++ b/arch/arm/plat-s3c/gpio-config.c
@@ -0,0 +1,163 @@
+/* linux/arch/arm/plat-s3c/gpio-config.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO configuration core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <mach/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ unsigned long flags;
+ int offset;
+ int ret;
+
+ if (!chip)
+ return -EINVAL;
+
+ offset = pin - chip->chip.base;
+
+ local_irq_save(flags);
+ ret = s3c_gpio_do_setcfg(chip, offset, config);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ unsigned long flags;
+ int offset, ret;
+
+ if (!chip)
+ return -EINVAL;
+
+ offset = pin - chip->chip.base;
+
+ local_irq_save(flags);
+ ret = s3c_gpio_do_setpull(chip, offset, pull);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
+int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg)
+{
+ void __iomem *reg = chip->base;
+ unsigned int shift = off;
+ u32 con;
+
+ if (s3c_gpio_is_cfg_special(cfg)) {
+ cfg &= 0xf;
+
+ /* Map output to 0, and SFN2 to 1 */
+ cfg -= 1;
+ if (cfg > 1)
+ return -EINVAL;
+
+ cfg <<= shift;
+ }
+
+ con = __raw_readl(reg);
+ con &= ~(0x1 << shift);
+ con |= cfg;
+ __raw_writel(con, reg);
+
+ return 0;
+}
+
+int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg)
+{
+ void __iomem *reg = chip->base;
+ unsigned int shift = off * 2;
+ u32 con;
+
+ if (s3c_gpio_is_cfg_special(cfg)) {
+ cfg &= 0xf;
+ if (cfg > 3)
+ return -EINVAL;
+
+ cfg <<= shift;
+ }
+
+ con = __raw_readl(reg);
+ con &= ~(0x3 << shift);
+ con |= cfg;
+ __raw_writel(con, reg);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
+int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg)
+{
+ void __iomem *reg = chip->base;
+ unsigned int shift = (off & 7) * 4;
+ u32 con;
+
+ if (off < 8 && chip->chip.ngpio >= 8)
+ reg -= 4;
+
+ if (s3c_gpio_is_cfg_special(cfg)) {
+ cfg &= 0xf;
+ cfg <<= shift;
+ }
+
+ con = __raw_readl(reg);
+ con &= ~(0xf << shift);
+ con |= cfg;
+ __raw_writel(con, reg);
+
+ return 0;
+}
+#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
+
+#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
+int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull)
+{
+ void __iomem *reg = chip->base + 0x08;
+ int shift = off * 2;
+ u32 pup;
+
+ pup = __raw_readl(reg);
+ pup &= ~(3 << shift);
+ pup |= pull << shift;
+ __raw_writel(pup, reg);
+
+ return 0;
+}
+
+s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
+ unsigned int off)
+{
+ void __iomem *reg = chip->base + 0x08;
+ int shift = off * 2;
+ u32 pup = __raw_readl(reg);
+
+ pup >>= shift;
+ pup &= 0x3;
+ return (__force s3c_gpio_pull_t)pup;
+}
+#endif
diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h
new file mode 100644
index 00000000000..652e2bbdaa2
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h
@@ -0,0 +1,176 @@
+/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - GPIO pin configuration helper definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* This is meant for core cpu support, machine or other driver files
+ * should not be including this header.
+ */
+
+#ifndef __PLAT_GPIO_CFG_HELPERS_H
+#define __PLAT_GPIO_CFG_HELPERS_H __FILE__
+
+/* As a note, all gpio configuration functions are entered exclusively, either
+ * with the relevant lock held or the system prevented from doing anything else
+ * by disabling interrupts.
+*/
+
+static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int config)
+{
+ return (chip->config->set_config)(chip, off, config);
+}
+
+static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull)
+{
+ return (chip->config->set_pull)(chip, off, pull);
+}
+
+/**
+ * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ * 00 = input
+ * 01 = output
+ * 1x = special function
+*/
+extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg);
+
+/**
+ * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+*/
+extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg);
+
+/**
+ * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * others = Special functions (dependant on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a seperate set of functions for
+ * each case.
+*/
+extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+ unsigned int off, unsigned int cfg);
+
+
+/* Pull-{up,down} resistor controls.
+ *
+ * S3C2410,S3C2440,S3C24A0 = Pull-UP,
+ * S3C2412,S3C2413 = Pull-Down
+ * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
+ * S3C2443 = Pull-Both [not same as S3C6400]
+ */
+
+/**
+ * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with one
+ * bit configuring the presence of a pull-up resistor.
+ */
+extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * @chip: The gpio chip that is being configured
+ * @off: The offset for the GPIO being configured
+ * @param: pull: The pull mode being requested
+ *
+ * This is a helper function for the case where we have GPIOs with one
+ * bit configuring the presence of a pull-down resistor.
+ */
+extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with two
+ * bits configuring the presence of a pull resistor, in the following
+ * order:
+ * 00 = No pull resistor connected
+ * 01 = Pull-up resistor connected
+ * 10 = Pull-down resistor connected
+ */
+extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull);
+
+
+/**
+ * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * @chip: The gpio chip that the GPIO pin belongs to
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-{up,down} resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_upown.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
+ unsigned int off);
+
+/**
+ * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with two
+ * bits configuring the presence of a pull resistor, in the following
+ * order:
+ * 00 = Pull-up resistor connected
+ * 10 = Pull-down resistor connected
+ * x1 = No pull up resistor
+ */
+extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * @chip: The gpio chip that the GPIO pin belongs to.
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-{up,down} resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_upown.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip,
+ unsigned int off);
+
+#endif /* __PLAT_GPIO_CFG_HELPERS_H */
+
diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg.h b/arch/arm/plat-s3c/include/plat/gpio-cfg.h
new file mode 100644
index 00000000000..29cd6a86cad
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/gpio-cfg.h
@@ -0,0 +1,110 @@
+/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - GPIO pin configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* This file contains the necessary definitions to get the basic gpio
+ * pin configuration done such as setting a pin to input or output or
+ * changing the pull-{up,down} configurations.
+ */
+
+/* Note, this interface is being added to the s3c64xx arch first and will
+ * be added to the s3c24xx systems later.
+ */
+
+#ifndef __PLAT_GPIO_CFG_H
+#define __PLAT_GPIO_CFG_H __FILE__
+
+typedef unsigned int __bitwise__ s3c_gpio_pull_t;
+
+/* forward declaration if gpio-core.h hasn't been included */
+struct s3c_gpio_chip;
+
+/**
+ * struct s3c_gpio_cfg GPIO configuration
+ * @cfg_eint: Configuration setting when used for external interrupt source
+ * @get_pull: Read the current pull configuration for the GPIO
+ * @set_pull: Set the current pull configuraiton for the GPIO
+ * @set_config: Set the current configuration for the GPIO
+ * @get_config: Read the current configuration for the GPIO
+ *
+ * Each chip can have more than one type of GPIO bank available and some
+ * have different capabilites even when they have the same control register
+ * layouts. Provide an point to vector control routine and provide any
+ * per-bank configuration information that other systems such as the
+ * external interrupt code will need.
+ */
+struct s3c_gpio_cfg {
+ unsigned int cfg_eint;
+
+ s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
+ int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
+ s3c_gpio_pull_t pull);
+
+ unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
+ int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
+ unsigned config);
+};
+
+#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
+#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))
+
+/* Defines for generic pin configurations */
+#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))
+#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
+#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
+
+#define s3c_gpio_is_cfg_special(_cfg) \
+ (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
+
+/**
+ * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
+ * @pin pin The pin number to configure.
+ * @pin to The configuration for the pin's function.
+ *
+ * Configure which function is actually connected to the external
+ * pin, such as an gpio input, output or some form of special function
+ * connected to an internal peripheral block.
+ */
+extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
+
+/* Define values for the pull-{up,down} available for each gpio pin.
+ *
+ * These values control the state of the weak pull-{up,down} resistors
+ * available on most pins on the S3C series. Not all chips support both
+ * up or down settings, and it may be dependant on the chip that is being
+ * used to whether the particular mode is available.
+ */
+#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00)
+#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01)
+#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02)
+
+/**
+ * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
+ * @pin: The pin number to configure the pull resistor.
+ * @pull: The configuration for the pull resistor.
+ *
+ * This function sets the state of the pull-{up,down} resistor for the
+ * specified pin. It will return 0 if successfull, or a negative error
+ * code if the pin cannot support the requested pull setting.
+*/
+extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
+ * @pin: The pin number to get the settings for
+ *
+ * Read the pull resistor value for the specified pin.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
+
+#endif /* __PLAT_GPIO_CFG_H */
diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h
index ad68b32a7f9..2fc60a580ac 100644
--- a/arch/arm/plat-s3c/include/plat/gpio-core.h
+++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
@@ -20,16 +20,20 @@
* specific code.
*/
+struct s3c_gpio_cfg;
+
/**
* struct s3c_gpio_chip - wrapper for specific implementation of gpio
* @chip: The chip structure to be exported via gpiolib.
* @base: The base pointer to the gpio configuration registers.
+ * @config: special function and pull-resistor control information.
*
* This wrapper provides the necessary information for the Samsung
* specific gpios being registered with gpiolib.
*/
struct s3c_gpio_chip {
struct gpio_chip chip;
+ struct s3c_gpio_cfg *config;
void __iomem *base;
};
@@ -48,7 +52,6 @@ static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
*/
extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
* for use with the configuration calls, and other parts of the s3c gpiolib
* support code.
@@ -65,8 +68,10 @@ extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
{
- return s3c_gpios[chip];
+ return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
}
#else
+/* machine specific code should provide s3c_gpiolib_getchip */
+
static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
#endif
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 9785a8fb480..f95c6c9d9f1 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -59,7 +59,7 @@ static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
return 0;
}
-static struct s3c_gpio_chip gpios[] = {
+struct s3c_gpio_chip s3c24xx_gpios[] = {
[0] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
.chip = {
@@ -129,10 +129,10 @@ static struct s3c_gpio_chip gpios[] = {
static __init int s3c24xx_gpiolib_init(void)
{
- struct s3c_gpio_chip *chip = gpios;
+ struct s3c_gpio_chip *chip = s3c24xx_gpios;
int gpn;
- for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++)
+ for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++)
s3c_gpiolib_add(chip);
return 0;
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index 3df2ec19d08..842200abeb3 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -15,6 +15,9 @@ config PLAT_S3C64XX
select NO_IOPORT
select ARCH_REQUIRE_GPIOLIB
select S3C_GPIO_TRACK
+ select S3C_GPIO_PULL_UPDOWN
+ select S3C_GPIO_CFG_S3C24XX
+ select S3C_GPIO_CFG_S3C64XX
help
Base platform code for any Samsung S3C64XX device
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index 28ba23502bc..cc62941d7b5 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -18,8 +18,10 @@
#include <mach/map.h>
#include <mach/gpio.h>
+#include <mach/gpio-core.h>
-#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
#include <plat/regs-gpio.h>
/* GPIO bank summary:
@@ -52,6 +54,12 @@
#define con_4bit_shift(__off) ((__off) * 4)
+#if 1
+#define gpio_dbg(x...) do { } while(0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG ## x)
+#endif
+
/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
* the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
* following example:
@@ -77,6 +85,8 @@ static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, base + OFF_GPCON);
+ gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
return 0;
}
@@ -102,6 +112,8 @@ static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
__raw_writel(con, base + OFF_GPCON);
__raw_writel(dat, base + OFF_GPDAT);
+ gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
return 0;
}
@@ -142,6 +154,8 @@ static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
con &= ~(0xf << con_4bit_shift(offset));
__raw_writel(con, regcon);
+ gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
return 0;
}
@@ -174,12 +188,35 @@ static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
__raw_writel(con, regcon);
__raw_writel(dat, base + OFF_GPDAT);
+ gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
return 0;
}
+static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
+ .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
+ .cfg_eint = 7,
+ .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
+ .cfg_eint = 3,
+ .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
static struct s3c_gpio_chip gpio_4bit[] = {
{
.base = S3C64XX_GPA_BASE,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPA(0),
.ngpio = S3C64XX_GPIO_A_NR,
@@ -187,6 +224,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPB_BASE,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPB(0),
.ngpio = S3C64XX_GPIO_B_NR,
@@ -194,6 +232,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPC_BASE,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPC(0),
.ngpio = S3C64XX_GPIO_C_NR,
@@ -201,6 +240,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPD_BASE,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPD(0),
.ngpio = S3C64XX_GPIO_D_NR,
@@ -208,6 +248,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPE_BASE,
+ .config = &gpio_4bit_cfg_noint,
.chip = {
.base = S3C64XX_GPE(0),
.ngpio = S3C64XX_GPIO_E_NR,
@@ -215,6 +256,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPG_BASE,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPG(0),
.ngpio = S3C64XX_GPIO_G_NR,
@@ -222,6 +264,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
},
}, {
.base = S3C64XX_GPM_BASE,
+ .config = &gpio_4bit_cfg_eint0011,
.chip = {
.base = S3C64XX_GPM(0),
.ngpio = S3C64XX_GPIO_M_NR,
@@ -233,6 +276,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
static struct s3c_gpio_chip gpio_4bit2[] = {
{
.base = S3C64XX_GPH_BASE + 0x4,
+ .config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPH(0),
.ngpio = S3C64XX_GPIO_H_NR,
@@ -240,6 +284,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
},
}, {
.base = S3C64XX_GPK_BASE + 0x4,
+ .config = &gpio_4bit_cfg_noint,
.chip = {
.base = S3C64XX_GPK(0),
.ngpio = S3C64XX_GPIO_K_NR,
@@ -247,6 +292,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
},
}, {
.base = S3C64XX_GPL_BASE + 0x4,
+ .config = &gpio_4bit_cfg_eint0011,
.chip = {
.base = S3C64XX_GPL(0),
.ngpio = S3C64XX_GPIO_L_NR,
@@ -255,9 +301,30 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
},
};
+static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
+ .set_config = s3c_gpio_setcfg_s3c24xx,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
+ .cfg_eint = 2,
+ .set_config = s3c_gpio_setcfg_s3c24xx,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
+ .cfg_eint = 3,
+ .set_config = s3c_gpio_setcfg_s3c24xx,
+ .set_pull = s3c_gpio_setpull_updown,
+ .get_pull = s3c_gpio_getpull_updown,
+};
+
static struct s3c_gpio_chip gpio_2bit[] = {
{
.base = S3C64XX_GPF_BASE,
+ .config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPF(0),
.ngpio = S3C64XX_GPIO_F_NR,
@@ -265,6 +332,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPI_BASE,
+ .config = &gpio_2bit_cfg_noint,
.chip = {
.base = S3C64XX_GPI(0),
.ngpio = S3C64XX_GPIO_I_NR,
@@ -272,6 +340,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPJ_BASE,
+ .config = &gpio_2bit_cfg_noint,
.chip = {
.base = S3C64XX_GPJ(0),
.ngpio = S3C64XX_GPIO_J_NR,
@@ -279,6 +348,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPN_BASE,
+ .config = &gpio_2bit_cfg_eint10,
.chip = {
.base = S3C64XX_GPN(0),
.ngpio = S3C64XX_GPIO_N_NR,
@@ -286,6 +356,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPO_BASE,
+ .config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPO(0),
.ngpio = S3C64XX_GPIO_O_NR,
@@ -293,6 +364,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPP_BASE,
+ .config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPP(0),
.ngpio = S3C64XX_GPIO_P_NR,
@@ -300,6 +372,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
},
}, {
.base = S3C64XX_GPQ_BASE,
+ .config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPQ(0),
.ngpio = S3C64XX_GPIO_Q_NR,