1 /* arch/arm/plat-s3c64xx/gpiolib.c
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
8 * S3C64XX - GPIOlib support
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.
15 #include <linux/kernel.h>
16 #include <linux/irq.h>
20 #include <mach/gpio.h>
22 #include <plat/gpio-core.h>
23 #include <plat/regs-gpio.h>
27 * Bank GPIOs Style SlpCon ExtInt Group
38 * K 16 4Bit[2] No None
39 * L 15 4Bit[2] No None
40 * M 6 4Bit No IRQ_EINT
41 * N 16 2Bit No IRQ_EINT
46 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
47 * [2] BANK has two control registers, GPxCON0 and GPxCON1
50 #define OFF_GPCON (0x00)
51 #define OFF_GPDAT (0x04)
53 #define con_4bit_shift(__off) ((__off) * 4)
55 /* 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
59 * base + 0x00: Control register, 4 bits per gpio
60 * gpio n: 4 bits starting at (4*n)
61 * 0000 = input, 0001 = output, others mean special-function
62 * base + 0x04: Data register, 1 bit per gpio
65 * Note, since the data register is one bit per gpio and is at base + 0x4
66 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
70 static int s3c64xx_gpiolib_4bit_input(struct gpio_chip
*chip
, unsigned offset
)
72 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
73 void __iomem
*base
= ourchip
->base
;
76 con
= __raw_readl(base
+ OFF_GPCON
);
77 con
&= ~(0xf << con_4bit_shift(offset
));
78 __raw_writel(con
, base
+ OFF_GPCON
);
83 static int s3c64xx_gpiolib_4bit_output(struct gpio_chip
*chip
,
84 unsigned offset
, int value
)
86 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
87 void __iomem
*base
= ourchip
->base
;
91 con
= __raw_readl(base
+ OFF_GPCON
);
92 con
&= ~(0xf << con_4bit_shift(offset
));
93 con
|= 0x1 << con_4bit_shift(offset
);
95 dat
= __raw_readl(base
+ OFF_GPDAT
);
99 dat
&= ~(1 << offset
);
101 __raw_writel(dat
, base
+ OFF_GPDAT
);
102 __raw_writel(con
, base
+ OFF_GPCON
);
103 __raw_writel(dat
, base
+ OFF_GPDAT
);
108 /* The next set of routines are for the case where the GPIO configuration
109 * registers are 4 bits per GPIO but there is more than one register (the
110 * bank has more than 8 GPIOs.
112 * This case is the similar to the 4 bit case, but the registers are as
115 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
116 * gpio n: 4 bits starting at (4*n)
117 * 0000 = input, 0001 = output, others mean special-function
118 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
119 * gpio n: 4 bits starting at (4*n)
120 * 0000 = input, 0001 = output, others mean special-function
121 * base + 0x08: Data register, 1 bit per gpio
124 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
125 * store the 'base + 0x4' address so that these routines see the data
126 * register at ourchip->base + 0x04.
129 static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip
*chip
, unsigned offset
)
131 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
132 void __iomem
*base
= ourchip
->base
;
133 void __iomem
*regcon
= base
;
141 con
= __raw_readl(regcon
);
142 con
&= ~(0xf << con_4bit_shift(offset
));
143 __raw_writel(con
, regcon
);
149 static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip
*chip
,
150 unsigned offset
, int value
)
152 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
153 void __iomem
*base
= ourchip
->base
;
154 void __iomem
*regcon
= base
;
163 con
= __raw_readl(regcon
);
164 con
&= ~(0xf << con_4bit_shift(offset
));
165 con
|= 0x1 << con_4bit_shift(offset
);
167 dat
= __raw_readl(base
+ OFF_GPDAT
);
171 dat
&= ~(1 << offset
);
173 __raw_writel(dat
, base
+ OFF_GPDAT
);
174 __raw_writel(con
, regcon
);
175 __raw_writel(dat
, base
+ OFF_GPDAT
);
180 static struct s3c_gpio_chip gpio_4bit
[] = {
182 .base
= S3C64XX_GPA_BASE
,
184 .base
= S3C64XX_GPA(0),
185 .ngpio
= S3C64XX_GPIO_A_NR
,
189 .base
= S3C64XX_GPB_BASE
,
191 .base
= S3C64XX_GPB(0),
192 .ngpio
= S3C64XX_GPIO_B_NR
,
196 .base
= S3C64XX_GPC_BASE
,
198 .base
= S3C64XX_GPC(0),
199 .ngpio
= S3C64XX_GPIO_C_NR
,
203 .base
= S3C64XX_GPD_BASE
,
205 .base
= S3C64XX_GPD(0),
206 .ngpio
= S3C64XX_GPIO_D_NR
,
210 .base
= S3C64XX_GPE_BASE
,
212 .base
= S3C64XX_GPE(0),
213 .ngpio
= S3C64XX_GPIO_E_NR
,
217 .base
= S3C64XX_GPG_BASE
,
219 .base
= S3C64XX_GPG(0),
220 .ngpio
= S3C64XX_GPIO_G_NR
,
224 .base
= S3C64XX_GPM_BASE
,
226 .base
= S3C64XX_GPM(0),
227 .ngpio
= S3C64XX_GPIO_M_NR
,
233 static struct s3c_gpio_chip gpio_4bit2
[] = {
235 .base
= S3C64XX_GPH_BASE
+ 0x4,
237 .base
= S3C64XX_GPH(0),
238 .ngpio
= S3C64XX_GPIO_H_NR
,
242 .base
= S3C64XX_GPK_BASE
+ 0x4,
244 .base
= S3C64XX_GPK(0),
245 .ngpio
= S3C64XX_GPIO_K_NR
,
249 .base
= S3C64XX_GPL_BASE
+ 0x4,
251 .base
= S3C64XX_GPL(0),
252 .ngpio
= S3C64XX_GPIO_L_NR
,
258 static struct s3c_gpio_chip gpio_2bit
[] = {
260 .base
= S3C64XX_GPF_BASE
,
262 .base
= S3C64XX_GPF(0),
263 .ngpio
= S3C64XX_GPIO_F_NR
,
267 .base
= S3C64XX_GPI_BASE
,
269 .base
= S3C64XX_GPI(0),
270 .ngpio
= S3C64XX_GPIO_I_NR
,
274 .base
= S3C64XX_GPJ_BASE
,
276 .base
= S3C64XX_GPJ(0),
277 .ngpio
= S3C64XX_GPIO_J_NR
,
281 .base
= S3C64XX_GPN_BASE
,
283 .base
= S3C64XX_GPN(0),
284 .ngpio
= S3C64XX_GPIO_N_NR
,
288 .base
= S3C64XX_GPO_BASE
,
290 .base
= S3C64XX_GPO(0),
291 .ngpio
= S3C64XX_GPIO_O_NR
,
295 .base
= S3C64XX_GPP_BASE
,
297 .base
= S3C64XX_GPP(0),
298 .ngpio
= S3C64XX_GPIO_P_NR
,
302 .base
= S3C64XX_GPQ_BASE
,
304 .base
= S3C64XX_GPQ(0),
305 .ngpio
= S3C64XX_GPIO_Q_NR
,
311 static __init
void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip
*chip
)
313 chip
->chip
.direction_input
= s3c64xx_gpiolib_4bit_input
;
314 chip
->chip
.direction_output
= s3c64xx_gpiolib_4bit_output
;
317 static __init
void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip
*chip
)
319 chip
->chip
.direction_input
= s3c64xx_gpiolib_4bit2_input
;
320 chip
->chip
.direction_output
= s3c64xx_gpiolib_4bit2_output
;
323 static __init
void s3c64xx_gpiolib_add(struct s3c_gpio_chip
*chips
,
325 void (*fn
)(struct s3c_gpio_chip
*))
327 for (; nr_chips
> 0; nr_chips
--, chips
++) {
330 s3c_gpiolib_add(chips
);
334 static __init
int s3c64xx_gpiolib_init(void)
336 s3c64xx_gpiolib_add(gpio_4bit
, ARRAY_SIZE(gpio_4bit
),
337 s3c64xx_gpiolib_add_4bit
);
339 s3c64xx_gpiolib_add(gpio_4bit2
, ARRAY_SIZE(gpio_4bit2
),
340 s3c64xx_gpiolib_add_4bit2
);
342 s3c64xx_gpiolib_add(gpio_2bit
, ARRAY_SIZE(gpio_2bit
), NULL
);
347 arch_initcall(s3c64xx_gpiolib_init
);