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);