aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2010-01-19 01:30:54 -0500
committerBen Dooks <ben-linux@fluff.org>2010-01-19 04:37:18 -0500
commit1f323cfda5feee4e9c1fc09ededaee849f906468 (patch)
tree89c288fd8a5fe2c0cad1c39c5b752f162ff69e46 /arch/arm
parent9717453c40ba9ffbd8c40968df45498059bfec0e (diff)
ARM: SAMSUNG: Move GPIO common functions to plat-samsung
This patch moves GPIO common functions (from plat-s3c64xx) into plat-samsung. and adds the config option to build the plat-samsung/gpiolib for Samsung SoCs. Signed-off-by: Adityapratap Sharma <aditya.ps@samsung.com> Signed-off-by: Atul Dahiya <atul.dahiya@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-core.h28
-rw-r--r--arch/arm/plat-s3c64xx/Kconfig1
-rw-r--r--arch/arm/plat-s3c64xx/gpiolib.c162
-rw-r--r--arch/arm/plat-samsung/Kconfig7
-rw-r--r--arch/arm/plat-samsung/Makefile1
-rw-r--r--arch/arm/plat-samsung/gpiolib.c197
6 files changed, 236 insertions, 160 deletions
diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h
index 32af612767aa..94fed584d5ae 100644
--- a/arch/arm/plat-s3c/include/plat/gpio-core.h
+++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
@@ -11,6 +11,11 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12*/ 12*/
13 13
14#define GPIOCON_OFF (0x00)
15#define GPIODAT_OFF (0x04)
16
17#define con_4bit_shift(__off) ((__off) * 4)
18
14/* Define the core gpiolib support functions that the s3c platforms may 19/* Define the core gpiolib support functions that the s3c platforms may
15 * need to extend or change depending on the hardware and the s3c chip 20 * need to extend or change depending on the hardware and the s3c chip
16 * selected at build or found at run time. 21 * selected at build or found at run time.
@@ -80,6 +85,29 @@ extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
80 * and any other necessary functions. 85 * and any other necessary functions.
81 */ 86 */
82 87
88/**
89 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
90 * @chip: The gpio chip that is being configured.
91 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
92 *
93 * This helper deal with the GPIO cases where the control register has 4 bits
94 * of control per GPIO, generally in the form of:
95 * 0000 = Input
96 * 0001 = Output
97 * others = Special functions (dependant on bank)
98 *
99 * Note, since the code to deal with the case where there are two control
100 * registers instead of one, we do not have a seperate set of function
101 * (samsung_gpiolib_add_4bit2_chips)for each case.
102 */
103extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
104 int nr_chips);
105extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
106 int nr_chips);
107
108extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
109extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
110
83#ifdef CONFIG_S3C_GPIO_TRACK 111#ifdef CONFIG_S3C_GPIO_TRACK
84extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; 112extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
85 113
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index 0fba1f956b8a..37b4519fb832 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -22,6 +22,7 @@ config PLAT_S3C64XX
22 select S3C_GPIO_CFG_S3C64XX 22 select S3C_GPIO_CFG_S3C64XX
23 select S3C_DEV_NAND 23 select S3C_DEV_NAND
24 select USB_ARCH_HAS_OHCI 24 select USB_ARCH_HAS_OHCI
25 select SAMSUNG_GPIOLIB_4BIT
25 help 26 help
26 Base platform code for any Samsung S3C64XX device 27 Base platform code for any Samsung S3C64XX device
27 28
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index 778560457277..265e23b6de8e 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -49,150 +49,6 @@
49 * [2] BANK has two control registers, GPxCON0 and GPxCON1 49 * [2] BANK has two control registers, GPxCON0 and GPxCON1
50 */ 50 */
51 51
52#define OFF_GPCON (0x00)
53#define OFF_GPDAT (0x04)
54
55#define con_4bit_shift(__off) ((__off) * 4)
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
63/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
64 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
65 * following example:
66 *
67 * base + 0x00: Control register, 4 bits per gpio
68 * gpio n: 4 bits starting at (4*n)
69 * 0000 = input, 0001 = output, others mean special-function
70 * base + 0x04: Data register, 1 bit per gpio
71 * bit n: data bit n
72 *
73 * Note, since the data register is one bit per gpio and is at base + 0x4
74 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
75 * the output.
76*/
77
78static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
79{
80 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
81 void __iomem *base = ourchip->base;
82 unsigned long con;
83
84 con = __raw_readl(base + OFF_GPCON);
85 con &= ~(0xf << con_4bit_shift(offset));
86 __raw_writel(con, base + OFF_GPCON);
87
88 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
89
90 return 0;
91}
92
93static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
94 unsigned offset, int value)
95{
96 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
97 void __iomem *base = ourchip->base;
98 unsigned long con;
99 unsigned long dat;
100
101 con = __raw_readl(base + OFF_GPCON);
102 con &= ~(0xf << con_4bit_shift(offset));
103 con |= 0x1 << con_4bit_shift(offset);
104
105 dat = __raw_readl(base + OFF_GPDAT);
106 if (value)
107 dat |= 1 << offset;
108 else
109 dat &= ~(1 << offset);
110
111 __raw_writel(dat, base + OFF_GPDAT);
112 __raw_writel(con, base + OFF_GPCON);
113 __raw_writel(dat, base + OFF_GPDAT);
114
115 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
116
117 return 0;
118}
119
120/* The next set of routines are for the case where the GPIO configuration
121 * registers are 4 bits per GPIO but there is more than one register (the
122 * bank has more than 8 GPIOs.
123 *
124 * This case is the similar to the 4 bit case, but the registers are as
125 * follows:
126 *
127 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
128 * gpio n: 4 bits starting at (4*n)
129 * 0000 = input, 0001 = output, others mean special-function
130 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
131 * gpio n: 4 bits starting at (4*n)
132 * 0000 = input, 0001 = output, others mean special-function
133 * base + 0x08: Data register, 1 bit per gpio
134 * bit n: data bit n
135 *
136 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
137 * store the 'base + 0x4' address so that these routines see the data
138 * register at ourchip->base + 0x04.
139*/
140
141static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
142{
143 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
144 void __iomem *base = ourchip->base;
145 void __iomem *regcon = base;
146 unsigned long con;
147
148 if (offset > 7)
149 offset -= 8;
150 else
151 regcon -= 4;
152
153 con = __raw_readl(regcon);
154 con &= ~(0xf << con_4bit_shift(offset));
155 __raw_writel(con, regcon);
156
157 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
158
159 return 0;
160
161}
162
163static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
164 unsigned offset, int value)
165{
166 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
167 void __iomem *base = ourchip->base;
168 void __iomem *regcon = base;
169 unsigned long con;
170 unsigned long dat;
171
172 if (offset > 7)
173 offset -= 8;
174 else
175 regcon -= 4;
176
177 con = __raw_readl(regcon);
178 con &= ~(0xf << con_4bit_shift(offset));
179 con |= 0x1 << con_4bit_shift(offset);
180
181 dat = __raw_readl(base + OFF_GPDAT);
182 if (value)
183 dat |= 1 << offset;
184 else
185 dat &= ~(1 << offset);
186
187 __raw_writel(dat, base + OFF_GPDAT);
188 __raw_writel(con, regcon);
189 __raw_writel(dat, base + OFF_GPDAT);
190
191 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
192
193 return 0;
194}
195
196static struct s3c_gpio_cfg gpio_4bit_cfg_noint = { 52static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
197 .set_config = s3c_gpio_setcfg_s3c64xx_4bit, 53 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
198 .set_pull = s3c_gpio_setpull_updown, 54 .set_pull = s3c_gpio_setpull_updown,
@@ -399,20 +255,6 @@ static struct s3c_gpio_chip gpio_2bit[] = {
399 }, 255 },
400}; 256};
401 257
402static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
403{
404 chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
405 chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
406 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
407}
408
409static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
410{
411 chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
412 chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
413 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
414}
415
416static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip) 258static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
417{ 259{
418 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit); 260 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
@@ -432,10 +274,10 @@ static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
432static __init int s3c64xx_gpiolib_init(void) 274static __init int s3c64xx_gpiolib_init(void)
433{ 275{
434 s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit), 276 s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
435 s3c64xx_gpiolib_add_4bit); 277 samsung_gpiolib_add_4bit);
436 278
437 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2), 279 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
438 s3c64xx_gpiolib_add_4bit2); 280 samsung_gpiolib_add_4bit2);
439 281
440 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), 282 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
441 s3c64xx_gpiolib_add_2bit); 283 s3c64xx_gpiolib_add_2bit);
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index e6c122967355..6484b5bf82c3 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -33,6 +33,13 @@ config SAMSUNG_IRQ_UART
33 33
34# options for gpio configuration support 34# options for gpio configuration support
35 35
36config SAMSUNG_GPIOLIB_4BIT
37 bool
38 help
39 GPIOlib file contains the 4 bit modification functions for gpio
40 configuration. GPIOlib shall be compiled only for S3C64XX and S5P
41 series of processors.
42
36config S3C_GPIO_CFG_S3C24XX 43config S3C_GPIO_CFG_S3C24XX
37 bool 44 bool
38 help 45 help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index ceac416d80b8..1fc8d471c6ee 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -15,6 +15,7 @@ obj-y += clock.o
15obj-y += pwm-clock.o 15obj-y += pwm-clock.o
16obj-y += gpio-config.o 16obj-y += gpio-config.o
17 17
18obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT) += gpiolib.o
18obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o 19obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
19 20
20obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o 21obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
diff --git a/arch/arm/plat-samsung/gpiolib.c b/arch/arm/plat-samsung/gpiolib.c
new file mode 100644
index 000000000000..3419b67f4221
--- /dev/null
+++ b/arch/arm/plat-samsung/gpiolib.c
@@ -0,0 +1,197 @@
1/* arch/arm/plat-samsung/gpiolib.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 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
9 * http://www.samsung.com/
10 *
11 * SAMSUNG - GPIOlib support
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/kernel.h>
19#include <linux/irq.h>
20#include <linux/io.h>
21#include <mach/gpio.h>
22#include <plat/gpio-core.h>
23#include <plat/gpio-cfg.h>
24#include <plat/gpio-cfg-helpers.h>
25
26#ifndef DEBUG_GPIO
27#define gpio_dbg(x...) do { } while (0)
28#else
29#define gpio_dbg(x...) printk(KERN_DEBUG x)
30#endif
31
32/* The samsung_gpiolib_4bit routines are to control the gpio banks where
33 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
34 * following example:
35 *
36 * base + 0x00: Control register, 4 bits per gpio
37 * gpio n: 4 bits starting at (4*n)
38 * 0000 = input, 0001 = output, others mean special-function
39 * base + 0x04: Data register, 1 bit per gpio
40 * bit n: data bit n
41 *
42 * Note, since the data register is one bit per gpio and is at base + 0x4
43 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
44 * the output.
45*/
46
47int samsung_gpiolib_4bit_input(struct gpio_chip *chip, unsigned int offset)
48{
49 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
50 void __iomem *base = ourchip->base;
51 unsigned long con;
52
53 con = __raw_readl(base + GPIOCON_OFF);
54 con &= ~(0xf << con_4bit_shift(offset));
55 __raw_writel(con, base + GPIOCON_OFF);
56
57 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
58
59 return 0;
60}
61
62int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
63 unsigned int offset, int value)
64{
65 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
66 void __iomem *base = ourchip->base;
67 unsigned long con;
68 unsigned long dat;
69
70 con = __raw_readl(base + GPIOCON_OFF);
71 con &= ~(0xf << con_4bit_shift(offset));
72 con |= 0x1 << con_4bit_shift(offset);
73
74 dat = __raw_readl(base + GPIODAT_OFF);
75
76 if (value)
77 dat |= 1 << offset;
78 else
79 dat &= ~(1 << offset);
80
81 __raw_writel(dat, base + GPIODAT_OFF);
82 __raw_writel(con, base + GPIOCON_OFF);
83 __raw_writel(dat, base + GPIODAT_OFF);
84
85 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
86
87 return 0;
88}
89
90/* The next set of routines are for the case where the GPIO configuration
91 * registers are 4 bits per GPIO but there is more than one register (the
92 * bank has more than 8 GPIOs.
93 *
94 * This case is the similar to the 4 bit case, but the registers are as
95 * follows:
96 *
97 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
98 * gpio n: 4 bits starting at (4*n)
99 * 0000 = input, 0001 = output, others mean special-function
100 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
101 * gpio n: 4 bits starting at (4*n)
102 * 0000 = input, 0001 = output, others mean special-function
103 * base + 0x08: Data register, 1 bit per gpio
104 * bit n: data bit n
105 *
106 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
107 * store the 'base + 0x4' address so that these routines see the data
108 * register at ourchip->base + 0x04.
109*/
110
111int samsung_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned int offset)
112{
113 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
114 void __iomem *base = ourchip->base;
115 void __iomem *regcon = base;
116 unsigned long con;
117
118 if (offset > 7)
119 offset -= 8;
120 else
121 regcon -= 4;
122
123 con = __raw_readl(regcon);
124 con &= ~(0xf << con_4bit_shift(offset));
125 __raw_writel(con, regcon);
126
127 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
128
129 return 0;
130}
131
132int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
133 unsigned int offset, int value)
134{
135 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
136 void __iomem *base = ourchip->base;
137 void __iomem *regcon = base;
138 unsigned long con;
139 unsigned long dat;
140 unsigned con_offset = offset;
141
142 if (con_offset > 7)
143 con_offset -= 8;
144 else
145 regcon -= 4;
146
147 con = __raw_readl(regcon);
148 con &= ~(0xf << con_4bit_shift(con_offset));
149 con |= 0x1 << con_4bit_shift(con_offset);
150
151 dat = __raw_readl(base + GPIODAT_OFF);
152
153 if (value)
154 dat |= 1 << offset;
155 else
156 dat &= ~(1 << offset);
157
158 __raw_writel(dat, base + GPIODAT_OFF);
159 __raw_writel(con, regcon);
160 __raw_writel(dat, base + GPIODAT_OFF);
161
162 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
163
164 return 0;
165}
166
167void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
168{
169 chip->chip.direction_input = samsung_gpiolib_4bit_input;
170 chip->chip.direction_output = samsung_gpiolib_4bit_output;
171 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
172}
173
174void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
175{
176 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
177 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
178 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
179}
180
181void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
182 int nr_chips)
183{
184 for (; nr_chips > 0; nr_chips--, chip++) {
185 samsung_gpiolib_add_4bit(chip);
186 s3c_gpiolib_add(chip);
187 }
188}
189
190void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
191 int nr_chips)
192{
193 for (; nr_chips > 0; nr_chips--, chip++) {
194 samsung_gpiolib_add_4bit2(chip);
195 s3c_gpiolib_add(chip);
196 }
197}