aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-10-31 12:14:34 -0400
committerBen Dooks <ben-linux@fluff.org>2008-12-15 18:34:15 -0500
commit21b23664b9354c5449841e401efb9ad523fb898b (patch)
treeb26017929643be8be4e0a562943ef75fa96499d7
parent89d043c3db22c37523165905708d2fa8062fda86 (diff)
[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>
-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 000000000000..6c9fbb99ef14
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-core.h
@@ -0,0 +1,34 @@
1/* arch/arm/mach-s3c24100/include/mach/gpio-core.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C2410 - GPIO core support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef __ASM_ARCH_GPIO_CORE_H
16#define __ASM_ARCH_GPIO_CORE_H __FILE__
17
18#include <plat/gpio-core.h>
19#include <mach/regs-gpio.h>
20
21extern struct s3c_gpio_chip s3c24xx_gpios[];
22
23static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
24{
25 struct s3c_gpio_chip *chip;
26
27 if (pin > S3C2410_GPG10)
28 return NULL;
29
30 chip = &s3c24xx_gpios[pin/32];
31 return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
32}
33
34#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 000000000000..d89aae68b0a5
--- /dev/null
+++ b/arch/arm/mach-s3c6400/include/mach/gpio-core.h
@@ -0,0 +1,21 @@
1/* arch/arm/mach-s3c6400/include/mach/gpio-core.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX - GPIO core support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef __ASM_ARCH_GPIO_CORE_H
16#define __ASM_ARCH_GPIO_CORE_H __FILE__
17
18/* currently we just include the platform support */
19#include <plat/gpio-core.h>
20
21#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig
index 77fc38f51874..45e62cba595c 100644
--- a/arch/arm/plat-s3c/Kconfig
+++ b/arch/arm/plat-s3c/Kconfig
@@ -120,6 +120,33 @@ config S3C_GPIO_TRACK
120 Internal configuration option to enable the s3c specific gpio 120 Internal configuration option to enable the s3c specific gpio
121 chip tracking if the platform requires it. 121 chip tracking if the platform requires it.
122 122
123config S3C_GPIO_PULL_UPDOWN
124 bool
125 help
126 Internal configuration to enable the correct GPIO pull helper
127
128config S3C_GPIO_PULL_DOWN
129 bool
130 help
131 Internal configuration to enable the correct GPIO pull helper
132
133config S3C_GPIO_PULL_UP
134 bool
135 help
136 Internal configuration to enable the correct GPIO pull helper
137
138config S3C_GPIO_CFG_S3C24XX
139 bool
140 help
141 Internal configuration to enable S3C24XX style GPIO configuration
142 functions.
143
144config S3C_GPIO_CFG_S3C64XX
145 bool
146 help
147 Internal configuration to enable S3C64XX style GPIO configuration
148 functions.
149
123# device definitions to compile in 150# device definitions to compile in
124 151
125config S3C_DEV_HSMMC 152config S3C_DEV_HSMMC
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
index 4d0299aef7ca..68a3451a2d9d 100644
--- a/arch/arm/plat-s3c/Makefile
+++ b/arch/arm/plat-s3c/Makefile
@@ -16,6 +16,7 @@ obj-y += time.o
16obj-y += clock.o 16obj-y += clock.o
17obj-y += pwm-clock.o 17obj-y += pwm-clock.o
18obj-y += gpio.o 18obj-y += gpio.o
19obj-y += gpio-config.o
19 20
20# devices 21# devices
21 22
diff --git a/arch/arm/plat-s3c/gpio-config.c b/arch/arm/plat-s3c/gpio-config.c
new file mode 100644
index 000000000000..7642b975a998
--- /dev/null
+++ b/arch/arm/plat-s3c/gpio-config.c
@@ -0,0 +1,163 @@
1/* linux/arch/arm/plat-s3c/gpio-config.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C series GPIO configuration core
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/gpio.h>
17#include <linux/io.h>
18
19#include <mach/gpio-core.h>
20#include <plat/gpio-cfg.h>
21#include <plat/gpio-cfg-helpers.h>
22
23int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
24{
25 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
26 unsigned long flags;
27 int offset;
28 int ret;
29
30 if (!chip)
31 return -EINVAL;
32
33 offset = pin - chip->chip.base;
34
35 local_irq_save(flags);
36 ret = s3c_gpio_do_setcfg(chip, offset, config);
37 local_irq_restore(flags);
38
39 return ret;
40}
41
42int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
43{
44 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
45 unsigned long flags;
46 int offset, ret;
47
48 if (!chip)
49 return -EINVAL;
50
51 offset = pin - chip->chip.base;
52
53 local_irq_save(flags);
54 ret = s3c_gpio_do_setpull(chip, offset, pull);
55 local_irq_restore(flags);
56
57 return ret;
58}
59
60#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
61int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
62 unsigned int off, unsigned int cfg)
63{
64 void __iomem *reg = chip->base;
65 unsigned int shift = off;
66 u32 con;
67
68 if (s3c_gpio_is_cfg_special(cfg)) {
69 cfg &= 0xf;
70
71 /* Map output to 0, and SFN2 to 1 */
72 cfg -= 1;
73 if (cfg > 1)
74 return -EINVAL;
75
76 cfg <<= shift;
77 }
78
79 con = __raw_readl(reg);
80 con &= ~(0x1 << shift);
81 con |= cfg;
82 __raw_writel(con, reg);
83
84 return 0;
85}
86
87int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
88 unsigned int off, unsigned int cfg)
89{
90 void __iomem *reg = chip->base;
91 unsigned int shift = off * 2;
92 u32 con;
93
94 if (s3c_gpio_is_cfg_special(cfg)) {
95 cfg &= 0xf;
96 if (cfg > 3)
97 return -EINVAL;
98
99 cfg <<= shift;
100 }
101
102 con = __raw_readl(reg);
103 con &= ~(0x3 << shift);
104 con |= cfg;
105 __raw_writel(con, reg);
106
107 return 0;
108}
109#endif
110
111#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
112int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
113 unsigned int off, unsigned int cfg)
114{
115 void __iomem *reg = chip->base;
116 unsigned int shift = (off & 7) * 4;
117 u32 con;
118
119 if (off < 8 && chip->chip.ngpio >= 8)
120 reg -= 4;
121
122 if (s3c_gpio_is_cfg_special(cfg)) {
123 cfg &= 0xf;
124 cfg <<= shift;
125 }
126
127 con = __raw_readl(reg);
128 con &= ~(0xf << shift);
129 con |= cfg;
130 __raw_writel(con, reg);
131
132 return 0;
133}
134#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
135
136#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
137int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
138 unsigned int off, s3c_gpio_pull_t pull)
139{
140 void __iomem *reg = chip->base + 0x08;
141 int shift = off * 2;
142 u32 pup;
143
144 pup = __raw_readl(reg);
145 pup &= ~(3 << shift);
146 pup |= pull << shift;
147 __raw_writel(pup, reg);
148
149 return 0;
150}
151
152s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
153 unsigned int off)
154{
155 void __iomem *reg = chip->base + 0x08;
156 int shift = off * 2;
157 u32 pup = __raw_readl(reg);
158
159 pup >>= shift;
160 pup &= 0x3;
161 return (__force s3c_gpio_pull_t)pup;
162}
163#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 000000000000..652e2bbdaa20
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h
@@ -0,0 +1,176 @@
1/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk/
6 * Ben Dooks <ben@simtec.co.uk>
7 *
8 * S3C Platform - GPIO pin configuration helper definitions
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15/* This is meant for core cpu support, machine or other driver files
16 * should not be including this header.
17 */
18
19#ifndef __PLAT_GPIO_CFG_HELPERS_H
20#define __PLAT_GPIO_CFG_HELPERS_H __FILE__
21
22/* As a note, all gpio configuration functions are entered exclusively, either
23 * with the relevant lock held or the system prevented from doing anything else
24 * by disabling interrupts.
25*/
26
27static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
28 unsigned int off, unsigned int config)
29{
30 return (chip->config->set_config)(chip, off, config);
31}
32
33static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
34 unsigned int off, s3c_gpio_pull_t pull)
35{
36 return (chip->config->set_pull)(chip, off, pull);
37}
38
39/**
40 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
41 * @chip: The gpio chip that is being configured.
42 * @off: The offset for the GPIO being configured.
43 * @cfg: The configuration value to set.
44 *
45 * This helper deal with the GPIO cases where the control register
46 * has two bits of configuration per gpio, which have the following
47 * functions:
48 * 00 = input
49 * 01 = output
50 * 1x = special function
51*/
52extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
53 unsigned int off, unsigned int cfg);
54
55/**
56 * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
57 * @chip: The gpio chip that is being configured.
58 * @off: The offset for the GPIO being configured.
59 * @cfg: The configuration value to set.
60 *
61 * This helper deal with the GPIO cases where the control register
62 * has one bit of configuration for the gpio, where setting the bit
63 * means the pin is in special function mode and unset means output.
64*/
65extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
66 unsigned int off, unsigned int cfg);
67
68/**
69 * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
70 * @chip: The gpio chip that is being configured.
71 * @off: The offset for the GPIO being configured.
72 * @cfg: The configuration value to set.
73 *
74 * This helper deal with the GPIO cases where the control register has 4 bits
75 * of control per GPIO, generally in the form of:
76 * 0000 = Input
77 * 0001 = Output
78 * others = Special functions (dependant on bank)
79 *
80 * Note, since the code to deal with the case where there are two control
81 * registers instead of one, we do not have a seperate set of functions for
82 * each case.
83*/
84extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
85 unsigned int off, unsigned int cfg);
86
87
88/* Pull-{up,down} resistor controls.
89 *
90 * S3C2410,S3C2440,S3C24A0 = Pull-UP,
91 * S3C2412,S3C2413 = Pull-Down
92 * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
93 * S3C2443 = Pull-Both [not same as S3C6400]
94 */
95
96/**
97 * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
98 * @chip: The gpio chip that is being configured.
99 * @off: The offset for the GPIO being configured.
100 * @param: pull: The pull mode being requested.
101 *
102 * This is a helper function for the case where we have GPIOs with one
103 * bit configuring the presence of a pull-up resistor.
104 */
105extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
106 unsigned int off, s3c_gpio_pull_t pull);
107
108/**
109 * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
110 * @chip: The gpio chip that is being configured
111 * @off: The offset for the GPIO being configured
112 * @param: pull: The pull mode being requested
113 *
114 * This is a helper function for the case where we have GPIOs with one
115 * bit configuring the presence of a pull-down resistor.
116 */
117extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
118 unsigned int off, s3c_gpio_pull_t pull);
119
120/**
121 * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
122 * @chip: The gpio chip that is being configured.
123 * @off: The offset for the GPIO being configured.
124 * @param: pull: The pull mode being requested.
125 *
126 * This is a helper function for the case where we have GPIOs with two
127 * bits configuring the presence of a pull resistor, in the following
128 * order:
129 * 00 = No pull resistor connected
130 * 01 = Pull-up resistor connected
131 * 10 = Pull-down resistor connected
132 */
133extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
134 unsigned int off, s3c_gpio_pull_t pull);
135
136
137/**
138 * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
139 * @chip: The gpio chip that the GPIO pin belongs to
140 * @off: The offset to the pin to get the configuration of.
141 *
142 * This helper function reads the state of the pull-{up,down} resistor for the
143 * given GPIO in the same case as s3c_gpio_setpull_upown.
144*/
145extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
146 unsigned int off);
147
148/**
149 * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
150 * @chip: The gpio chip that is being configured.
151 * @off: The offset for the GPIO being configured.
152 * @param: pull: The pull mode being requested.
153 *
154 * This is a helper function for the case where we have GPIOs with two
155 * bits configuring the presence of a pull resistor, in the following
156 * order:
157 * 00 = Pull-up resistor connected
158 * 10 = Pull-down resistor connected
159 * x1 = No pull up resistor
160 */
161extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
162 unsigned int off, s3c_gpio_pull_t pull);
163
164/**
165 * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
166 * @chip: The gpio chip that the GPIO pin belongs to.
167 * @off: The offset to the pin to get the configuration of.
168 *
169 * This helper function reads the state of the pull-{up,down} resistor for the
170 * given GPIO in the same case as s3c_gpio_setpull_upown.
171*/
172extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip,
173 unsigned int off);
174
175#endif /* __PLAT_GPIO_CFG_HELPERS_H */
176
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 000000000000..29cd6a86cade
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/gpio-cfg.h
@@ -0,0 +1,110 @@
1/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk/
6 * Ben Dooks <ben@simtec.co.uk>
7 *
8 * S3C Platform - GPIO pin configuration
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15/* This file contains the necessary definitions to get the basic gpio
16 * pin configuration done such as setting a pin to input or output or
17 * changing the pull-{up,down} configurations.
18 */
19
20/* Note, this interface is being added to the s3c64xx arch first and will
21 * be added to the s3c24xx systems later.
22 */
23
24#ifndef __PLAT_GPIO_CFG_H
25#define __PLAT_GPIO_CFG_H __FILE__
26
27typedef unsigned int __bitwise__ s3c_gpio_pull_t;
28
29/* forward declaration if gpio-core.h hasn't been included */
30struct s3c_gpio_chip;
31
32/**
33 * struct s3c_gpio_cfg GPIO configuration
34 * @cfg_eint: Configuration setting when used for external interrupt source
35 * @get_pull: Read the current pull configuration for the GPIO
36 * @set_pull: Set the current pull configuraiton for the GPIO
37 * @set_config: Set the current configuration for the GPIO
38 * @get_config: Read the current configuration for the GPIO
39 *
40 * Each chip can have more than one type of GPIO bank available and some
41 * have different capabilites even when they have the same control register
42 * layouts. Provide an point to vector control routine and provide any
43 * per-bank configuration information that other systems such as the
44 * external interrupt code will need.
45 */
46struct s3c_gpio_cfg {
47 unsigned int cfg_eint;
48
49 s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
50 int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
51 s3c_gpio_pull_t pull);
52
53 unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
54 int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
55 unsigned config);
56};
57
58#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
59#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))
60
61/* Defines for generic pin configurations */
62#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))
63#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
64#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
65
66#define s3c_gpio_is_cfg_special(_cfg) \
67 (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
68
69/**
70 * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
71 * @pin pin The pin number to configure.
72 * @pin to The configuration for the pin's function.
73 *
74 * Configure which function is actually connected to the external
75 * pin, such as an gpio input, output or some form of special function
76 * connected to an internal peripheral block.
77 */
78extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
79
80/* Define values for the pull-{up,down} available for each gpio pin.
81 *
82 * These values control the state of the weak pull-{up,down} resistors
83 * available on most pins on the S3C series. Not all chips support both
84 * up or down settings, and it may be dependant on the chip that is being
85 * used to whether the particular mode is available.
86 */
87#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00)
88#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01)
89#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02)
90
91/**
92 * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
93 * @pin: The pin number to configure the pull resistor.
94 * @pull: The configuration for the pull resistor.
95 *
96 * This function sets the state of the pull-{up,down} resistor for the
97 * specified pin. It will return 0 if successfull, or a negative error
98 * code if the pin cannot support the requested pull setting.
99*/
100extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
101
102/**
103 * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
104 * @pin: The pin number to get the settings for
105 *
106 * Read the pull resistor value for the specified pin.
107*/
108extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
109
110#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 ad68b32a7f9d..2fc60a580ac8 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 @@
20 * specific code. 20 * specific code.
21*/ 21*/
22 22
23struct s3c_gpio_cfg;
24
23/** 25/**
24 * struct s3c_gpio_chip - wrapper for specific implementation of gpio 26 * struct s3c_gpio_chip - wrapper for specific implementation of gpio
25 * @chip: The chip structure to be exported via gpiolib. 27 * @chip: The chip structure to be exported via gpiolib.
26 * @base: The base pointer to the gpio configuration registers. 28 * @base: The base pointer to the gpio configuration registers.
29 * @config: special function and pull-resistor control information.
27 * 30 *
28 * This wrapper provides the necessary information for the Samsung 31 * This wrapper provides the necessary information for the Samsung
29 * specific gpios being registered with gpiolib. 32 * specific gpios being registered with gpiolib.
30 */ 33 */
31struct s3c_gpio_chip { 34struct s3c_gpio_chip {
32 struct gpio_chip chip; 35 struct gpio_chip chip;
36 struct s3c_gpio_cfg *config;
33 void __iomem *base; 37 void __iomem *base;
34}; 38};
35 39
@@ -48,7 +52,6 @@ static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
48 */ 52 */
49extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip); 53extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
50 54
51
52/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios 55/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
53 * for use with the configuration calls, and other parts of the s3c gpiolib 56 * for use with the configuration calls, and other parts of the s3c gpiolib
54 * support code. 57 * support code.
@@ -65,8 +68,10 @@ extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
65 68
66static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) 69static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
67{ 70{
68 return s3c_gpios[chip]; 71 return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
69} 72}
70#else 73#else
74/* machine specific code should provide s3c_gpiolib_getchip */
75
71static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } 76static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
72#endif 77#endif
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 9785a8fb4809..f95c6c9d9f1a 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,
59 return 0; 59 return 0;
60} 60}
61 61
62static struct s3c_gpio_chip gpios[] = { 62struct s3c_gpio_chip s3c24xx_gpios[] = {
63 [0] = { 63 [0] = {
64 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0), 64 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
65 .chip = { 65 .chip = {
@@ -129,10 +129,10 @@ static struct s3c_gpio_chip gpios[] = {
129 129
130static __init int s3c24xx_gpiolib_init(void) 130static __init int s3c24xx_gpiolib_init(void)
131{ 131{
132 struct s3c_gpio_chip *chip = gpios; 132 struct s3c_gpio_chip *chip = s3c24xx_gpios;
133 int gpn; 133 int gpn;
134 134
135 for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++) 135 for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++)
136 s3c_gpiolib_add(chip); 136 s3c_gpiolib_add(chip);
137 137
138 return 0; 138 return 0;
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index 3df2ec19d08a..842200abeb36 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -15,6 +15,9 @@ config PLAT_S3C64XX
15 select NO_IOPORT 15 select NO_IOPORT
16 select ARCH_REQUIRE_GPIOLIB 16 select ARCH_REQUIRE_GPIOLIB
17 select S3C_GPIO_TRACK 17 select S3C_GPIO_TRACK
18 select S3C_GPIO_PULL_UPDOWN
19 select S3C_GPIO_CFG_S3C24XX
20 select S3C_GPIO_CFG_S3C64XX
18 help 21 help
19 Base platform code for any Samsung S3C64XX device 22 Base platform code for any Samsung S3C64XX device
20 23
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index 28ba23502bce..cc62941d7b5c 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -18,8 +18,10 @@
18 18
19#include <mach/map.h> 19#include <mach/map.h>
20#include <mach/gpio.h> 20#include <mach/gpio.h>
21#include <mach/gpio-core.h>
21 22
22#include <plat/gpio-core.h> 23#include <plat/gpio-cfg.h>
24#include <plat/gpio-cfg-helpers.h>
23#include <plat/regs-gpio.h> 25#include <plat/regs-gpio.h>
24 26
25/* GPIO bank summary: 27/* GPIO bank summary:
@@ -52,6 +54,12 @@
52 54
53#define con_4bit_shift(__off) ((__off) * 4) 55#define con_4bit_shift(__off) ((__off) * 4)
54 56
57#if 1
58#define gpio_dbg(x...) do { } while(0)
59#else
60#define gpio_dbg(x...) printk(KERN_DEBUG ## x)
61#endif
62
55/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where 63/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
56 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the 64 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
57 * following example: 65 * following example:
@@ -77,6 +85,8 @@ static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
77 con &= ~(0xf << con_4bit_shift(offset)); 85 con &= ~(0xf << con_4bit_shift(offset));
78 __raw_writel(con, base + OFF_GPCON); 86 __raw_writel(con, base + OFF_GPCON);
79 87
88 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
89
80 return 0; 90 return 0;
81} 91}
82 92
@@ -102,6 +112,8 @@ static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
102 __raw_writel(con, base + OFF_GPCON); 112 __raw_writel(con, base + OFF_GPCON);
103 __raw_writel(dat, base + OFF_GPDAT); 113 __raw_writel(dat, base + OFF_GPDAT);
104 114
115 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
116
105 return 0; 117 return 0;
106} 118}
107 119
@@ -142,6 +154,8 @@ static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
142 con &= ~(0xf << con_4bit_shift(offset)); 154 con &= ~(0xf << con_4bit_shift(offset));
143 __raw_writel(con, regcon); 155 __raw_writel(con, regcon);
144 156
157 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
158
145 return 0; 159 return 0;
146 160
147} 161}
@@ -174,12 +188,35 @@ static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
174 __raw_writel(con, regcon); 188 __raw_writel(con, regcon);
175 __raw_writel(dat, base + OFF_GPDAT); 189 __raw_writel(dat, base + OFF_GPDAT);
176 190
191 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
192
177 return 0; 193 return 0;
178} 194}
179 195
196static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
197 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
198 .set_pull = s3c_gpio_setpull_updown,
199 .get_pull = s3c_gpio_getpull_updown,
200};
201
202static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
203 .cfg_eint = 7,
204 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
205 .set_pull = s3c_gpio_setpull_updown,
206 .get_pull = s3c_gpio_getpull_updown,
207};
208
209static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
210 .cfg_eint = 3,
211 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
212 .set_pull = s3c_gpio_setpull_updown,
213 .get_pull = s3c_gpio_getpull_updown,
214};
215
180static struct s3c_gpio_chip gpio_4bit[] = { 216static struct s3c_gpio_chip gpio_4bit[] = {
181 { 217 {
182 .base = S3C64XX_GPA_BASE, 218 .base = S3C64XX_GPA_BASE,
219 .config = &gpio_4bit_cfg_eint0111,
183 .chip = { 220 .chip = {
184 .base = S3C64XX_GPA(0), 221 .base = S3C64XX_GPA(0),
185 .ngpio = S3C64XX_GPIO_A_NR, 222 .ngpio = S3C64XX_GPIO_A_NR,
@@ -187,6 +224,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
187 }, 224 },
188 }, { 225 }, {
189 .base = S3C64XX_GPB_BASE, 226 .base = S3C64XX_GPB_BASE,
227 .config = &gpio_4bit_cfg_eint0111,
190 .chip = { 228 .chip = {
191 .base = S3C64XX_GPB(0), 229 .base = S3C64XX_GPB(0),
192 .ngpio = S3C64XX_GPIO_B_NR, 230 .ngpio = S3C64XX_GPIO_B_NR,
@@ -194,6 +232,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
194 }, 232 },
195 }, { 233 }, {
196 .base = S3C64XX_GPC_BASE, 234 .base = S3C64XX_GPC_BASE,
235 .config = &gpio_4bit_cfg_eint0111,
197 .chip = { 236 .chip = {
198 .base = S3C64XX_GPC(0), 237 .base = S3C64XX_GPC(0),
199 .ngpio = S3C64XX_GPIO_C_NR, 238 .ngpio = S3C64XX_GPIO_C_NR,
@@ -201,6 +240,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
201 }, 240 },
202 }, { 241 }, {
203 .base = S3C64XX_GPD_BASE, 242 .base = S3C64XX_GPD_BASE,
243 .config = &gpio_4bit_cfg_eint0111,
204 .chip = { 244 .chip = {
205 .base = S3C64XX_GPD(0), 245 .base = S3C64XX_GPD(0),
206 .ngpio = S3C64XX_GPIO_D_NR, 246 .ngpio = S3C64XX_GPIO_D_NR,
@@ -208,6 +248,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
208 }, 248 },
209 }, { 249 }, {
210 .base = S3C64XX_GPE_BASE, 250 .base = S3C64XX_GPE_BASE,
251 .config = &gpio_4bit_cfg_noint,
211 .chip = { 252 .chip = {
212 .base = S3C64XX_GPE(0), 253 .base = S3C64XX_GPE(0),
213 .ngpio = S3C64XX_GPIO_E_NR, 254 .ngpio = S3C64XX_GPIO_E_NR,
@@ -215,6 +256,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
215 }, 256 },
216 }, { 257 }, {
217 .base = S3C64XX_GPG_BASE, 258 .base = S3C64XX_GPG_BASE,
259 .config = &gpio_4bit_cfg_eint0111,
218 .chip = { 260 .chip = {
219 .base = S3C64XX_GPG(0), 261 .base = S3C64XX_GPG(0),
220 .ngpio = S3C64XX_GPIO_G_NR, 262 .ngpio = S3C64XX_GPIO_G_NR,
@@ -222,6 +264,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
222 }, 264 },
223 }, { 265 }, {
224 .base = S3C64XX_GPM_BASE, 266 .base = S3C64XX_GPM_BASE,
267 .config = &gpio_4bit_cfg_eint0011,
225 .chip = { 268 .chip = {
226 .base = S3C64XX_GPM(0), 269 .base = S3C64XX_GPM(0),
227 .ngpio = S3C64XX_GPIO_M_NR, 270 .ngpio = S3C64XX_GPIO_M_NR,
@@ -233,6 +276,7 @@ static struct s3c_gpio_chip gpio_4bit[] = {
233static struct s3c_gpio_chip gpio_4bit2[] = { 276static struct s3c_gpio_chip gpio_4bit2[] = {
234 { 277 {
235 .base = S3C64XX_GPH_BASE + 0x4, 278 .base = S3C64XX_GPH_BASE + 0x4,
279 .config = &gpio_4bit_cfg_eint0111,
236 .chip = { 280 .chip = {
237 .base = S3C64XX_GPH(0), 281 .base = S3C64XX_GPH(0),
238 .ngpio = S3C64XX_GPIO_H_NR, 282 .ngpio = S3C64XX_GPIO_H_NR,
@@ -240,6 +284,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
240 }, 284 },
241 }, { 285 }, {
242 .base = S3C64XX_GPK_BASE + 0x4, 286 .base = S3C64XX_GPK_BASE + 0x4,
287 .config = &gpio_4bit_cfg_noint,
243 .chip = { 288 .chip = {
244 .base = S3C64XX_GPK(0), 289 .base = S3C64XX_GPK(0),
245 .ngpio = S3C64XX_GPIO_K_NR, 290 .ngpio = S3C64XX_GPIO_K_NR,
@@ -247,6 +292,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
247 }, 292 },
248 }, { 293 }, {
249 .base = S3C64XX_GPL_BASE + 0x4, 294 .base = S3C64XX_GPL_BASE + 0x4,
295 .config = &gpio_4bit_cfg_eint0011,
250 .chip = { 296 .chip = {
251 .base = S3C64XX_GPL(0), 297 .base = S3C64XX_GPL(0),
252 .ngpio = S3C64XX_GPIO_L_NR, 298 .ngpio = S3C64XX_GPIO_L_NR,
@@ -255,9 +301,30 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
255 }, 301 },
256}; 302};
257 303
304static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
305 .set_config = s3c_gpio_setcfg_s3c24xx,
306 .set_pull = s3c_gpio_setpull_updown,
307 .get_pull = s3c_gpio_getpull_updown,
308};
309
310static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
311 .cfg_eint = 2,
312 .set_config = s3c_gpio_setcfg_s3c24xx,
313 .set_pull = s3c_gpio_setpull_updown,
314 .get_pull = s3c_gpio_getpull_updown,
315};
316
317static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
318 .cfg_eint = 3,
319 .set_config = s3c_gpio_setcfg_s3c24xx,
320 .set_pull = s3c_gpio_setpull_updown,
321 .get_pull = s3c_gpio_getpull_updown,
322};
323
258static struct s3c_gpio_chip gpio_2bit[] = { 324static struct s3c_gpio_chip gpio_2bit[] = {
259 { 325 {
260 .base = S3C64XX_GPF_BASE, 326 .base = S3C64XX_GPF_BASE,
327 .config = &gpio_2bit_cfg_eint11,
261 .chip = { 328 .chip = {
262 .base = S3C64XX_GPF(0), 329 .base = S3C64XX_GPF(0),
263 .ngpio = S3C64XX_GPIO_F_NR, 330 .ngpio = S3C64XX_GPIO_F_NR,
@@ -265,6 +332,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
265 }, 332 },
266 }, { 333 }, {
267 .base = S3C64XX_GPI_BASE, 334 .base = S3C64XX_GPI_BASE,
335 .config = &gpio_2bit_cfg_noint,
268 .chip = { 336 .chip = {
269 .base = S3C64XX_GPI(0), 337 .base = S3C64XX_GPI(0),
270 .ngpio = S3C64XX_GPIO_I_NR, 338 .ngpio = S3C64XX_GPIO_I_NR,
@@ -272,6 +340,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
272 }, 340 },
273 }, { 341 }, {
274 .base = S3C64XX_GPJ_BASE, 342 .base = S3C64XX_GPJ_BASE,
343 .config = &gpio_2bit_cfg_noint,
275 .chip = { 344 .chip = {
276 .base = S3C64XX_GPJ(0), 345 .base = S3C64XX_GPJ(0),
277 .ngpio = S3C64XX_GPIO_J_NR, 346 .ngpio = S3C64XX_GPIO_J_NR,
@@ -279,6 +348,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
279 }, 348 },
280 }, { 349 }, {
281 .base = S3C64XX_GPN_BASE, 350 .base = S3C64XX_GPN_BASE,
351 .config = &gpio_2bit_cfg_eint10,
282 .chip = { 352 .chip = {
283 .base = S3C64XX_GPN(0), 353 .base = S3C64XX_GPN(0),
284 .ngpio = S3C64XX_GPIO_N_NR, 354 .ngpio = S3C64XX_GPIO_N_NR,
@@ -286,6 +356,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
286 }, 356 },
287 }, { 357 }, {
288 .base = S3C64XX_GPO_BASE, 358 .base = S3C64XX_GPO_BASE,
359 .config = &gpio_2bit_cfg_eint11,
289 .chip = { 360 .chip = {
290 .base = S3C64XX_GPO(0), 361 .base = S3C64XX_GPO(0),
291 .ngpio = S3C64XX_GPIO_O_NR, 362 .ngpio = S3C64XX_GPIO_O_NR,
@@ -293,6 +364,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
293 }, 364 },
294 }, { 365 }, {
295 .base = S3C64XX_GPP_BASE, 366 .base = S3C64XX_GPP_BASE,
367 .config = &gpio_2bit_cfg_eint11,
296 .chip = { 368 .chip = {
297 .base = S3C64XX_GPP(0), 369 .base = S3C64XX_GPP(0),
298 .ngpio = S3C64XX_GPIO_P_NR, 370 .ngpio = S3C64XX_GPIO_P_NR,
@@ -300,6 +372,7 @@ static struct s3c_gpio_chip gpio_2bit[] = {
300 }, 372 },
301 }, { 373 }, {
302 .base = S3C64XX_GPQ_BASE, 374 .base = S3C64XX_GPQ_BASE,
375 .config = &gpio_2bit_cfg_eint11,
303 .chip = { 376 .chip = {
304 .base = S3C64XX_GPQ(0), 377 .base = S3C64XX_GPQ(0),
305 .ngpio = S3C64XX_GPIO_Q_NR, 378 .ngpio = S3C64XX_GPIO_Q_NR,