diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx/gpiolib.c')
-rw-r--r-- | arch/arm/plat-s3c24xx/gpiolib.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c new file mode 100644 index 000000000000..825d8d0c5ca2 --- /dev/null +++ b/arch/arm/plat-s3c24xx/gpiolib.c | |||
@@ -0,0 +1,259 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/gpiolib.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C24XX GPIOlib support | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/irq.h> | ||
24 | |||
25 | #include <asm/arch/regs-gpio.h> | ||
26 | |||
27 | struct s3c24xx_gpio_chip { | ||
28 | struct gpio_chip chip; | ||
29 | void __iomem *base; | ||
30 | }; | ||
31 | |||
32 | static inline struct s3c24xx_gpio_chip *to_s3c_chip(struct gpio_chip *gpc) | ||
33 | { | ||
34 | return container_of(gpc, struct s3c24xx_gpio_chip, chip); | ||
35 | } | ||
36 | |||
37 | /* these routines are exported for use by other parts of the platform | ||
38 | * and system support, but are not intended to be used directly by the | ||
39 | * drivers themsevles. | ||
40 | */ | ||
41 | |||
42 | int s3c24xx_gpiolib_input(struct gpio_chip *chip, unsigned offset) | ||
43 | { | ||
44 | struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); | ||
45 | void __iomem *base = ourchip->base; | ||
46 | unsigned long flags; | ||
47 | unsigned long con; | ||
48 | |||
49 | local_irq_save(flags); | ||
50 | |||
51 | con = __raw_readl(base + 0x00); | ||
52 | con &= ~(3 << (offset * 2)); | ||
53 | con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2); | ||
54 | |||
55 | __raw_writel(con, base + 0x00); | ||
56 | |||
57 | local_irq_restore(flags); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | int s3c24xx_gpiolib_output(struct gpio_chip *chip, | ||
62 | unsigned offset, int value) | ||
63 | { | ||
64 | struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); | ||
65 | void __iomem *base = ourchip->base; | ||
66 | unsigned long flags; | ||
67 | unsigned long dat; | ||
68 | unsigned long con; | ||
69 | |||
70 | local_irq_save(flags); | ||
71 | |||
72 | dat = __raw_readl(base + 0x04); | ||
73 | dat &= ~(1 << offset); | ||
74 | if (value) | ||
75 | dat |= 1 << offset; | ||
76 | __raw_writel(dat, base + 0x04); | ||
77 | |||
78 | con = __raw_readl(base + 0x00); | ||
79 | con &= ~(3 << (offset * 2)); | ||
80 | con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2); | ||
81 | |||
82 | __raw_writel(con, base + 0x00); | ||
83 | __raw_writel(dat, base + 0x04); | ||
84 | |||
85 | local_irq_restore(flags); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | void s3c24xx_gpiolib_set(struct gpio_chip *chip, unsigned offset, int value) | ||
90 | { | ||
91 | struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); | ||
92 | void __iomem *base = ourchip->base; | ||
93 | unsigned long flags; | ||
94 | unsigned long dat; | ||
95 | |||
96 | local_irq_save(flags); | ||
97 | |||
98 | dat = __raw_readl(base + 0x04); | ||
99 | dat &= ~(1 << offset); | ||
100 | if (value) | ||
101 | dat |= 1 << offset; | ||
102 | __raw_writel(dat, base + 0x04); | ||
103 | |||
104 | local_irq_restore(flags); | ||
105 | } | ||
106 | |||
107 | int s3c24xx_gpiolib_get(struct gpio_chip *chip, unsigned offset) | ||
108 | { | ||
109 | struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); | ||
110 | unsigned long val; | ||
111 | |||
112 | val = __raw_readl(ourchip->base + 0x04); | ||
113 | val >>= offset; | ||
114 | val &= 1; | ||
115 | |||
116 | return val; | ||
117 | } | ||
118 | |||
119 | static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset) | ||
120 | { | ||
121 | return -EINVAL; | ||
122 | } | ||
123 | |||
124 | static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip, | ||
125 | unsigned offset, int value) | ||
126 | { | ||
127 | struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip); | ||
128 | void __iomem *base = ourchip->base; | ||
129 | unsigned long flags; | ||
130 | unsigned long dat; | ||
131 | unsigned long con; | ||
132 | |||
133 | local_irq_save(flags); | ||
134 | |||
135 | con = __raw_readl(base + 0x00); | ||
136 | dat = __raw_readl(base + 0x04); | ||
137 | |||
138 | dat &= ~(1 << offset); | ||
139 | if (value) | ||
140 | dat |= 1 << offset; | ||
141 | |||
142 | __raw_writel(dat, base + 0x04); | ||
143 | |||
144 | con &= ~(1 << offset); | ||
145 | |||
146 | __raw_writel(con, base + 0x00); | ||
147 | __raw_writel(dat, base + 0x04); | ||
148 | |||
149 | local_irq_restore(flags); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | |||
154 | struct s3c24xx_gpio_chip gpios[] = { | ||
155 | [0] = { | ||
156 | .base = S3C24XX_GPIO_BASE(S3C2410_GPA0), | ||
157 | .chip = { | ||
158 | .base = S3C2410_GPA0, | ||
159 | .owner = THIS_MODULE, | ||
160 | .label = "GPIOA", | ||
161 | .ngpio = 24, | ||
162 | .direction_input = s3c24xx_gpiolib_banka_input, | ||
163 | .direction_output = s3c24xx_gpiolib_banka_output, | ||
164 | .set = s3c24xx_gpiolib_set, | ||
165 | .get = s3c24xx_gpiolib_get, | ||
166 | }, | ||
167 | }, | ||
168 | [1] = { | ||
169 | .base = S3C24XX_GPIO_BASE(S3C2410_GPB0), | ||
170 | .chip = { | ||
171 | .base = S3C2410_GPB0, | ||
172 | .owner = THIS_MODULE, | ||
173 | .label = "GPIOB", | ||
174 | .ngpio = 16, | ||
175 | .direction_input = s3c24xx_gpiolib_input, | ||
176 | .direction_output = s3c24xx_gpiolib_output, | ||
177 | .set = s3c24xx_gpiolib_set, | ||
178 | .get = s3c24xx_gpiolib_get, | ||
179 | }, | ||
180 | }, | ||
181 | [2] = { | ||
182 | .base = S3C24XX_GPIO_BASE(S3C2410_GPC0), | ||
183 | .chip = { | ||
184 | .base = S3C2410_GPC0, | ||
185 | .owner = THIS_MODULE, | ||
186 | .label = "GPIOC", | ||
187 | .ngpio = 16, | ||
188 | .direction_input = s3c24xx_gpiolib_input, | ||
189 | .direction_output = s3c24xx_gpiolib_output, | ||
190 | .set = s3c24xx_gpiolib_set, | ||
191 | .get = s3c24xx_gpiolib_get, | ||
192 | }, | ||
193 | }, | ||
194 | [3] = { | ||
195 | .base = S3C24XX_GPIO_BASE(S3C2410_GPD0), | ||
196 | .chip = { | ||
197 | .base = S3C2410_GPD0, | ||
198 | .owner = THIS_MODULE, | ||
199 | .label = "GPIOD", | ||
200 | .ngpio = 16, | ||
201 | .direction_input = s3c24xx_gpiolib_input, | ||
202 | .direction_output = s3c24xx_gpiolib_output, | ||
203 | .set = s3c24xx_gpiolib_set, | ||
204 | .get = s3c24xx_gpiolib_get, | ||
205 | }, | ||
206 | }, | ||
207 | [4] = { | ||
208 | .base = S3C24XX_GPIO_BASE(S3C2410_GPE0), | ||
209 | .chip = { | ||
210 | .base = S3C2410_GPE0, | ||
211 | .label = "GPIOE", | ||
212 | .owner = THIS_MODULE, | ||
213 | .ngpio = 16, | ||
214 | .direction_input = s3c24xx_gpiolib_input, | ||
215 | .direction_output = s3c24xx_gpiolib_output, | ||
216 | .set = s3c24xx_gpiolib_set, | ||
217 | .get = s3c24xx_gpiolib_get, | ||
218 | }, | ||
219 | }, | ||
220 | [5] = { | ||
221 | .base = S3C24XX_GPIO_BASE(S3C2410_GPF0), | ||
222 | .chip = { | ||
223 | .base = S3C2410_GPF0, | ||
224 | .owner = THIS_MODULE, | ||
225 | .label = "GPIOF", | ||
226 | .ngpio = 8, | ||
227 | .direction_input = s3c24xx_gpiolib_input, | ||
228 | .direction_output = s3c24xx_gpiolib_output, | ||
229 | .set = s3c24xx_gpiolib_set, | ||
230 | .get = s3c24xx_gpiolib_get, | ||
231 | }, | ||
232 | }, | ||
233 | [6] = { | ||
234 | .base = S3C24XX_GPIO_BASE(S3C2410_GPG0), | ||
235 | .chip = { | ||
236 | .base = S3C2410_GPG0, | ||
237 | .owner = THIS_MODULE, | ||
238 | .label = "GPIOG", | ||
239 | .ngpio = 10, | ||
240 | .direction_input = s3c24xx_gpiolib_input, | ||
241 | .direction_output = s3c24xx_gpiolib_output, | ||
242 | .set = s3c24xx_gpiolib_set, | ||
243 | .get = s3c24xx_gpiolib_get, | ||
244 | }, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | static __init int s3c24xx_gpiolib_init(void) | ||
249 | { | ||
250 | struct s3c24xx_gpio_chip *chip = gpios; | ||
251 | int gpn; | ||
252 | |||
253 | for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++) | ||
254 | gpiochip_add(&chip->chip); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | arch_initcall(s3c24xx_gpiolib_init); | ||