diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2010-12-14 06:54:03 -0500 |
---|---|---|
committer | Nicolas Pitre <nico@fluxnic.net> | 2011-03-03 16:27:02 -0500 |
commit | 9eac6d0a4e7e5149a7f86575b46d710ad2e05fe2 (patch) | |
tree | 3f3eb4504f3221954a5adaae66e417d9a0883e71 /arch/arm/plat-orion/gpio.c | |
parent | 4ee1f6b574765a6c97f945e6b0277e5ccac38cb5 (diff) |
ARM: Remove dependency of plat-orion GPIO code on mach directory includes.
This patch makes the various mach dirs that use the plat-orion GPIO
code pass in GPIO-related platform info (GPIO controller base address,
secondary base IRQ number, etc) explicitly, instead of having
plat-orion get those values by including a mach dir include file --
the latter mechanism is problematic if you want to support multiple
ARM platforms in the same kernel image.
Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
Diffstat (limited to 'arch/arm/plat-orion/gpio.c')
-rw-r--r-- | arch/arm/plat-orion/gpio.c | 456 |
1 files changed, 310 insertions, 146 deletions
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 5f3522314815..078894bc3b9a 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c | |||
@@ -17,55 +17,123 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | 19 | ||
20 | static DEFINE_SPINLOCK(gpio_lock); | 20 | /* |
21 | static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; | 21 | * GPIO unit register offsets. |
22 | static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; | 22 | */ |
23 | #define GPIO_OUT_OFF 0x0000 | ||
24 | #define GPIO_IO_CONF_OFF 0x0004 | ||
25 | #define GPIO_BLINK_EN_OFF 0x0008 | ||
26 | #define GPIO_IN_POL_OFF 0x000c | ||
27 | #define GPIO_DATA_IN_OFF 0x0010 | ||
28 | #define GPIO_EDGE_CAUSE_OFF 0x0014 | ||
29 | #define GPIO_EDGE_MASK_OFF 0x0018 | ||
30 | #define GPIO_LEVEL_MASK_OFF 0x001c | ||
31 | |||
32 | struct orion_gpio_chip { | ||
33 | struct gpio_chip chip; | ||
34 | spinlock_t lock; | ||
35 | void __iomem *base; | ||
36 | unsigned long valid_input; | ||
37 | unsigned long valid_output; | ||
38 | int mask_offset; | ||
39 | int secondary_irq_base; | ||
40 | }; | ||
41 | |||
42 | static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip) | ||
43 | { | ||
44 | return ochip->base + GPIO_OUT_OFF; | ||
45 | } | ||
46 | |||
47 | static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip) | ||
48 | { | ||
49 | return ochip->base + GPIO_IO_CONF_OFF; | ||
50 | } | ||
51 | |||
52 | static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip) | ||
53 | { | ||
54 | return ochip->base + GPIO_BLINK_EN_OFF; | ||
55 | } | ||
56 | |||
57 | static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip) | ||
58 | { | ||
59 | return ochip->base + GPIO_IN_POL_OFF; | ||
60 | } | ||
61 | |||
62 | static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip) | ||
63 | { | ||
64 | return ochip->base + GPIO_DATA_IN_OFF; | ||
65 | } | ||
66 | |||
67 | static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip) | ||
68 | { | ||
69 | return ochip->base + GPIO_EDGE_CAUSE_OFF; | ||
70 | } | ||
71 | |||
72 | static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip) | ||
73 | { | ||
74 | return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF; | ||
75 | } | ||
76 | |||
77 | static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip) | ||
78 | { | ||
79 | return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF; | ||
80 | } | ||
81 | |||
23 | 82 | ||
24 | static inline void __set_direction(unsigned pin, int input) | 83 | static struct orion_gpio_chip orion_gpio_chips[2]; |
84 | static int orion_gpio_chip_count; | ||
85 | |||
86 | static inline void | ||
87 | __set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input) | ||
25 | { | 88 | { |
26 | u32 u; | 89 | u32 u; |
27 | 90 | ||
28 | u = readl(GPIO_IO_CONF(pin)); | 91 | u = readl(GPIO_IO_CONF(ochip)); |
29 | if (input) | 92 | if (input) |
30 | u |= 1 << (pin & 31); | 93 | u |= 1 << pin; |
31 | else | 94 | else |
32 | u &= ~(1 << (pin & 31)); | 95 | u &= ~(1 << pin); |
33 | writel(u, GPIO_IO_CONF(pin)); | 96 | writel(u, GPIO_IO_CONF(ochip)); |
34 | } | 97 | } |
35 | 98 | ||
36 | static void __set_level(unsigned pin, int high) | 99 | static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high) |
37 | { | 100 | { |
38 | u32 u; | 101 | u32 u; |
39 | 102 | ||
40 | u = readl(GPIO_OUT(pin)); | 103 | u = readl(GPIO_OUT(ochip)); |
41 | if (high) | 104 | if (high) |
42 | u |= 1 << (pin & 31); | 105 | u |= 1 << pin; |
43 | else | 106 | else |
44 | u &= ~(1 << (pin & 31)); | 107 | u &= ~(1 << pin); |
45 | writel(u, GPIO_OUT(pin)); | 108 | writel(u, GPIO_OUT(ochip)); |
46 | } | 109 | } |
47 | 110 | ||
48 | static inline void __set_blinking(unsigned pin, int blink) | 111 | static inline void |
112 | __set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink) | ||
49 | { | 113 | { |
50 | u32 u; | 114 | u32 u; |
51 | 115 | ||
52 | u = readl(GPIO_BLINK_EN(pin)); | 116 | u = readl(GPIO_BLINK_EN(ochip)); |
53 | if (blink) | 117 | if (blink) |
54 | u |= 1 << (pin & 31); | 118 | u |= 1 << pin; |
55 | else | 119 | else |
56 | u &= ~(1 << (pin & 31)); | 120 | u &= ~(1 << pin); |
57 | writel(u, GPIO_BLINK_EN(pin)); | 121 | writel(u, GPIO_BLINK_EN(ochip)); |
58 | } | 122 | } |
59 | 123 | ||
60 | static inline int orion_gpio_is_valid(unsigned pin, int mode) | 124 | static inline int |
125 | orion_gpio_is_valid(struct orion_gpio_chip *ochip, unsigned pin, int mode) | ||
61 | { | 126 | { |
62 | if (pin < GPIO_MAX) { | 127 | if (pin >= ochip->chip.ngpio) |
63 | if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input)) | 128 | goto err_out; |
64 | goto err_out; | 129 | |
65 | if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output)) | 130 | if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input)) |
66 | goto err_out; | 131 | goto err_out; |
67 | return true; | 132 | |
68 | } | 133 | if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output)) |
134 | goto err_out; | ||
135 | |||
136 | return 1; | ||
69 | 137 | ||
70 | err_out: | 138 | err_out: |
71 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | 139 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); |
@@ -75,134 +143,155 @@ err_out: | |||
75 | /* | 143 | /* |
76 | * GENERIC_GPIO primitives. | 144 | * GENERIC_GPIO primitives. |
77 | */ | 145 | */ |
146 | static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) | ||
147 | { | ||
148 | struct orion_gpio_chip *ochip = | ||
149 | container_of(chip, struct orion_gpio_chip, chip); | ||
150 | |||
151 | if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) || | ||
152 | orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) | ||
153 | return 0; | ||
154 | |||
155 | return -EINVAL; | ||
156 | } | ||
157 | |||
78 | static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) | 158 | static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) |
79 | { | 159 | { |
160 | struct orion_gpio_chip *ochip = | ||
161 | container_of(chip, struct orion_gpio_chip, chip); | ||
80 | unsigned long flags; | 162 | unsigned long flags; |
81 | 163 | ||
82 | if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK)) | 164 | if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK)) |
83 | return -EINVAL; | 165 | return -EINVAL; |
84 | 166 | ||
85 | spin_lock_irqsave(&gpio_lock, flags); | 167 | spin_lock_irqsave(&ochip->lock, flags); |
86 | 168 | __set_direction(ochip, pin, 1); | |
87 | /* Configure GPIO direction. */ | 169 | spin_unlock_irqrestore(&ochip->lock, flags); |
88 | __set_direction(pin, 1); | ||
89 | |||
90 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
91 | 170 | ||
92 | return 0; | 171 | return 0; |
93 | } | 172 | } |
94 | 173 | ||
95 | static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin) | 174 | static int orion_gpio_get(struct gpio_chip *chip, unsigned pin) |
96 | { | 175 | { |
176 | struct orion_gpio_chip *ochip = | ||
177 | container_of(chip, struct orion_gpio_chip, chip); | ||
97 | int val; | 178 | int val; |
98 | 179 | ||
99 | if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) | 180 | if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) { |
100 | val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); | 181 | val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip)); |
101 | else | 182 | } else { |
102 | val = readl(GPIO_OUT(pin)); | 183 | val = readl(GPIO_OUT(ochip)); |
184 | } | ||
103 | 185 | ||
104 | return (val >> (pin & 31)) & 1; | 186 | return (val >> pin) & 1; |
105 | } | 187 | } |
106 | 188 | ||
107 | static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, | 189 | static int |
108 | int value) | 190 | orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value) |
109 | { | 191 | { |
192 | struct orion_gpio_chip *ochip = | ||
193 | container_of(chip, struct orion_gpio_chip, chip); | ||
110 | unsigned long flags; | 194 | unsigned long flags; |
111 | 195 | ||
112 | if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) | 196 | if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK)) |
113 | return -EINVAL; | 197 | return -EINVAL; |
114 | 198 | ||
115 | spin_lock_irqsave(&gpio_lock, flags); | 199 | spin_lock_irqsave(&ochip->lock, flags); |
116 | 200 | __set_blinking(ochip, pin, 0); | |
117 | /* Disable blinking. */ | 201 | __set_level(ochip, pin, value); |
118 | __set_blinking(pin, 0); | 202 | __set_direction(ochip, pin, 0); |
119 | 203 | spin_unlock_irqrestore(&ochip->lock, flags); | |
120 | /* Configure GPIO output value. */ | ||
121 | __set_level(pin, value); | ||
122 | |||
123 | /* Configure GPIO direction. */ | ||
124 | __set_direction(pin, 0); | ||
125 | |||
126 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
127 | 204 | ||
128 | return 0; | 205 | return 0; |
129 | } | 206 | } |
130 | 207 | ||
131 | static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin, | 208 | static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value) |
132 | int value) | ||
133 | { | 209 | { |
210 | struct orion_gpio_chip *ochip = | ||
211 | container_of(chip, struct orion_gpio_chip, chip); | ||
134 | unsigned long flags; | 212 | unsigned long flags; |
135 | 213 | ||
136 | spin_lock_irqsave(&gpio_lock, flags); | 214 | spin_lock_irqsave(&ochip->lock, flags); |
137 | 215 | __set_level(ochip, pin, value); | |
138 | /* Configure GPIO output value. */ | 216 | spin_unlock_irqrestore(&ochip->lock, flags); |
139 | __set_level(pin, value); | ||
140 | |||
141 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
142 | } | 217 | } |
143 | 218 | ||
144 | static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) | 219 | static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin) |
145 | { | 220 | { |
146 | if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) || | 221 | struct orion_gpio_chip *ochip = |
147 | orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) | 222 | container_of(chip, struct orion_gpio_chip, chip); |
148 | return 0; | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | 223 | ||
152 | static struct gpio_chip orion_gpiochip = { | 224 | return ochip->secondary_irq_base + pin; |
153 | .label = "orion_gpio", | ||
154 | .direction_input = orion_gpio_direction_input, | ||
155 | .get = orion_gpio_get_value, | ||
156 | .direction_output = orion_gpio_direction_output, | ||
157 | .set = orion_gpio_set_value, | ||
158 | .request = orion_gpio_request, | ||
159 | .base = 0, | ||
160 | .ngpio = GPIO_MAX, | ||
161 | .can_sleep = 0, | ||
162 | }; | ||
163 | |||
164 | void __init orion_gpio_init(void) | ||
165 | { | ||
166 | gpiochip_add(&orion_gpiochip); | ||
167 | } | 225 | } |
168 | 226 | ||
227 | |||
169 | /* | 228 | /* |
170 | * Orion-specific GPIO API extensions. | 229 | * Orion-specific GPIO API extensions. |
171 | */ | 230 | */ |
231 | static struct orion_gpio_chip *orion_gpio_chip_find(int pin) | ||
232 | { | ||
233 | int i; | ||
234 | |||
235 | for (i = 0; i < orion_gpio_chip_count; i++) { | ||
236 | struct orion_gpio_chip *ochip = orion_gpio_chips + i; | ||
237 | struct gpio_chip *chip = &ochip->chip; | ||
238 | |||
239 | if (pin >= chip->base && pin < chip->base + chip->ngpio) | ||
240 | return ochip; | ||
241 | } | ||
242 | |||
243 | return NULL; | ||
244 | } | ||
245 | |||
172 | void __init orion_gpio_set_unused(unsigned pin) | 246 | void __init orion_gpio_set_unused(unsigned pin) |
173 | { | 247 | { |
248 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); | ||
249 | |||
250 | if (ochip == NULL) | ||
251 | return; | ||
252 | |||
253 | pin -= ochip->chip.base; | ||
254 | |||
174 | /* Configure as output, drive low. */ | 255 | /* Configure as output, drive low. */ |
175 | __set_level(pin, 0); | 256 | __set_level(ochip, pin, 0); |
176 | __set_direction(pin, 0); | 257 | __set_direction(ochip, pin, 0); |
177 | } | 258 | } |
178 | 259 | ||
179 | void __init orion_gpio_set_valid(unsigned pin, int mode) | 260 | void __init orion_gpio_set_valid(unsigned pin, int mode) |
180 | { | 261 | { |
262 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); | ||
263 | |||
264 | if (ochip == NULL) | ||
265 | return; | ||
266 | |||
267 | pin -= ochip->chip.base; | ||
268 | |||
181 | if (mode == 1) | 269 | if (mode == 1) |
182 | mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; | 270 | mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; |
271 | |||
183 | if (mode & GPIO_INPUT_OK) | 272 | if (mode & GPIO_INPUT_OK) |
184 | __set_bit(pin, gpio_valid_input); | 273 | __set_bit(pin, &ochip->valid_input); |
185 | else | 274 | else |
186 | __clear_bit(pin, gpio_valid_input); | 275 | __clear_bit(pin, &ochip->valid_input); |
276 | |||
187 | if (mode & GPIO_OUTPUT_OK) | 277 | if (mode & GPIO_OUTPUT_OK) |
188 | __set_bit(pin, gpio_valid_output); | 278 | __set_bit(pin, &ochip->valid_output); |
189 | else | 279 | else |
190 | __clear_bit(pin, gpio_valid_output); | 280 | __clear_bit(pin, &ochip->valid_output); |
191 | } | 281 | } |
192 | 282 | ||
193 | void orion_gpio_set_blink(unsigned pin, int blink) | 283 | void orion_gpio_set_blink(unsigned pin, int blink) |
194 | { | 284 | { |
285 | struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin); | ||
195 | unsigned long flags; | 286 | unsigned long flags; |
196 | 287 | ||
197 | spin_lock_irqsave(&gpio_lock, flags); | 288 | if (ochip == NULL) |
289 | return; | ||
198 | 290 | ||
199 | /* Set output value to zero. */ | 291 | spin_lock_irqsave(&ochip->lock, flags); |
200 | __set_level(pin, 0); | 292 | __set_level(ochip, pin, 0); |
201 | 293 | __set_blinking(ochip, pin, blink); | |
202 | /* Set blinking. */ | 294 | spin_unlock_irqrestore(&ochip->lock, flags); |
203 | __set_blinking(pin, blink); | ||
204 | |||
205 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
206 | } | 295 | } |
207 | EXPORT_SYMBOL(orion_gpio_set_blink); | 296 | EXPORT_SYMBOL(orion_gpio_set_blink); |
208 | 297 | ||
@@ -234,59 +323,78 @@ EXPORT_SYMBOL(orion_gpio_set_blink); | |||
234 | ****************************************************************************/ | 323 | ****************************************************************************/ |
235 | static void gpio_irq_ack(struct irq_data *d) | 324 | static void gpio_irq_ack(struct irq_data *d) |
236 | { | 325 | { |
237 | int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; | 326 | struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); |
327 | int type; | ||
328 | |||
329 | type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; | ||
238 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | 330 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { |
239 | int pin = irq_to_gpio(d->irq); | 331 | int pin = d->irq - ochip->secondary_irq_base; |
240 | writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin)); | 332 | |
333 | writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip)); | ||
241 | } | 334 | } |
242 | } | 335 | } |
243 | 336 | ||
244 | static void gpio_irq_mask(struct irq_data *d) | 337 | static void gpio_irq_mask(struct irq_data *d) |
245 | { | 338 | { |
246 | int pin = irq_to_gpio(d->irq); | 339 | struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); |
247 | int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; | 340 | int type; |
248 | u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? | 341 | void __iomem *reg; |
249 | GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); | 342 | int pin; |
250 | u32 u = readl(reg); | 343 | |
251 | u &= ~(1 << (pin & 31)); | 344 | type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; |
252 | writel(u, reg); | 345 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
346 | reg = GPIO_EDGE_MASK(ochip); | ||
347 | else | ||
348 | reg = GPIO_LEVEL_MASK(ochip); | ||
349 | |||
350 | pin = d->irq - ochip->secondary_irq_base; | ||
351 | |||
352 | writel(readl(reg) & ~(1 << pin), reg); | ||
253 | } | 353 | } |
254 | 354 | ||
255 | static void gpio_irq_unmask(struct irq_data *d) | 355 | static void gpio_irq_unmask(struct irq_data *d) |
256 | { | 356 | { |
257 | int pin = irq_to_gpio(d->irq); | 357 | struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); |
258 | int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; | 358 | int type; |
259 | u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ? | 359 | void __iomem *reg; |
260 | GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin); | 360 | int pin; |
261 | u32 u = readl(reg); | 361 | |
262 | u |= 1 << (pin & 31); | 362 | type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK; |
263 | writel(u, reg); | 363 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
364 | reg = GPIO_EDGE_MASK(ochip); | ||
365 | else | ||
366 | reg = GPIO_LEVEL_MASK(ochip); | ||
367 | |||
368 | pin = d->irq - ochip->secondary_irq_base; | ||
369 | |||
370 | writel(readl(reg) | (1 << pin), reg); | ||
264 | } | 371 | } |
265 | 372 | ||
266 | static int gpio_irq_set_type(struct irq_data *d, u32 type) | 373 | static int gpio_irq_set_type(struct irq_data *d, u32 type) |
267 | { | 374 | { |
268 | int pin = irq_to_gpio(d->irq); | 375 | struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); |
269 | struct irq_desc *desc; | 376 | int pin; |
270 | u32 u; | 377 | u32 u; |
271 | 378 | ||
272 | u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)); | 379 | pin = d->irq - ochip->secondary_irq_base; |
380 | |||
381 | u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); | ||
273 | if (!u) { | 382 | if (!u) { |
274 | printk(KERN_ERR "orion gpio_irq_set_type failed " | 383 | printk(KERN_ERR "orion gpio_irq_set_type failed " |
275 | "(irq %d, pin %d).\n", d->irq, pin); | 384 | "(irq %d, pin %d).\n", d->irq, pin); |
276 | return -EINVAL; | 385 | return -EINVAL; |
277 | } | 386 | } |
278 | 387 | ||
279 | desc = irq_desc + d->irq; | ||
280 | |||
281 | /* | 388 | /* |
282 | * Set edge/level type. | 389 | * Set edge/level type. |
283 | */ | 390 | */ |
284 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | 391 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { |
285 | desc->handle_irq = handle_edge_irq; | 392 | set_irq_handler(d->irq, handle_edge_irq); |
286 | } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | 393 | } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
287 | desc->handle_irq = handle_level_irq; | 394 | set_irq_handler(d->irq, handle_level_irq); |
288 | } else { | 395 | } else { |
289 | printk(KERN_ERR "failed to set irq=%d (type=%d)\n", d->irq, type); | 396 | printk(KERN_ERR "failed to set irq=%d (type=%d)\n", |
397 | d->irq, type); | ||
290 | return -EINVAL; | 398 | return -EINVAL; |
291 | } | 399 | } |
292 | 400 | ||
@@ -294,31 +402,29 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type) | |||
294 | * Configure interrupt polarity. | 402 | * Configure interrupt polarity. |
295 | */ | 403 | */ |
296 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { | 404 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) { |
297 | u = readl(GPIO_IN_POL(pin)); | 405 | u = readl(GPIO_IN_POL(ochip)); |
298 | u &= ~(1 << (pin & 31)); | 406 | u &= ~(1 << pin); |
299 | writel(u, GPIO_IN_POL(pin)); | 407 | writel(u, GPIO_IN_POL(ochip)); |
300 | } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { | 408 | } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) { |
301 | u = readl(GPIO_IN_POL(pin)); | 409 | u = readl(GPIO_IN_POL(ochip)); |
302 | u |= 1 << (pin & 31); | 410 | u |= 1 << pin; |
303 | writel(u, GPIO_IN_POL(pin)); | 411 | writel(u, GPIO_IN_POL(ochip)); |
304 | } else if (type == IRQ_TYPE_EDGE_BOTH) { | 412 | } else if (type == IRQ_TYPE_EDGE_BOTH) { |
305 | u32 v; | 413 | u32 v; |
306 | 414 | ||
307 | v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin)); | 415 | v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip)); |
308 | 416 | ||
309 | /* | 417 | /* |
310 | * set initial polarity based on current input level | 418 | * set initial polarity based on current input level |
311 | */ | 419 | */ |
312 | u = readl(GPIO_IN_POL(pin)); | 420 | u = readl(GPIO_IN_POL(ochip)); |
313 | if (v & (1 << (pin & 31))) | 421 | if (v & (1 << pin)) |
314 | u |= 1 << (pin & 31); /* falling */ | 422 | u |= 1 << pin; /* falling */ |
315 | else | 423 | else |
316 | u &= ~(1 << (pin & 31)); /* rising */ | 424 | u &= ~(1 << pin); /* rising */ |
317 | writel(u, GPIO_IN_POL(pin)); | 425 | writel(u, GPIO_IN_POL(ochip)); |
318 | } | 426 | } |
319 | 427 | ||
320 | desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type; | ||
321 | |||
322 | return 0; | 428 | return 0; |
323 | } | 429 | } |
324 | 430 | ||
@@ -330,29 +436,87 @@ struct irq_chip orion_gpio_irq_chip = { | |||
330 | .irq_set_type = gpio_irq_set_type, | 436 | .irq_set_type = gpio_irq_set_type, |
331 | }; | 437 | }; |
332 | 438 | ||
439 | void __init orion_gpio_init(int gpio_base, int ngpio, | ||
440 | u32 base, int mask_offset, int secondary_irq_base) | ||
441 | { | ||
442 | struct orion_gpio_chip *ochip; | ||
443 | int i; | ||
444 | |||
445 | if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) | ||
446 | return; | ||
447 | |||
448 | ochip = orion_gpio_chips + orion_gpio_chip_count; | ||
449 | ochip->chip.label = "orion_gpio"; | ||
450 | ochip->chip.request = orion_gpio_request; | ||
451 | ochip->chip.direction_input = orion_gpio_direction_input; | ||
452 | ochip->chip.get = orion_gpio_get; | ||
453 | ochip->chip.direction_output = orion_gpio_direction_output; | ||
454 | ochip->chip.set = orion_gpio_set; | ||
455 | ochip->chip.to_irq = orion_gpio_to_irq; | ||
456 | ochip->chip.base = gpio_base; | ||
457 | ochip->chip.ngpio = ngpio; | ||
458 | ochip->chip.can_sleep = 0; | ||
459 | spin_lock_init(&ochip->lock); | ||
460 | ochip->base = (void __iomem *)base; | ||
461 | ochip->valid_input = 0; | ||
462 | ochip->valid_output = 0; | ||
463 | ochip->mask_offset = mask_offset; | ||
464 | ochip->secondary_irq_base = secondary_irq_base; | ||
465 | |||
466 | gpiochip_add(&ochip->chip); | ||
467 | |||
468 | orion_gpio_chip_count++; | ||
469 | |||
470 | /* | ||
471 | * Mask and clear GPIO interrupts. | ||
472 | */ | ||
473 | writel(0, GPIO_EDGE_CAUSE(ochip)); | ||
474 | writel(0, GPIO_EDGE_MASK(ochip)); | ||
475 | writel(0, GPIO_LEVEL_MASK(ochip)); | ||
476 | |||
477 | for (i = 0; i < ngpio; i++) { | ||
478 | unsigned int irq = secondary_irq_base + i; | ||
479 | |||
480 | set_irq_chip(irq, &orion_gpio_irq_chip); | ||
481 | set_irq_handler(irq, handle_level_irq); | ||
482 | set_irq_chip_data(irq, ochip); | ||
483 | irq_desc[irq].status |= IRQ_LEVEL; | ||
484 | set_irq_flags(irq, IRQF_VALID); | ||
485 | } | ||
486 | } | ||
487 | |||
333 | void orion_gpio_irq_handler(int pinoff) | 488 | void orion_gpio_irq_handler(int pinoff) |
334 | { | 489 | { |
490 | struct orion_gpio_chip *ochip; | ||
335 | u32 cause; | 491 | u32 cause; |
336 | int pin; | 492 | int i; |
337 | 493 | ||
338 | cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff)); | 494 | ochip = orion_gpio_chip_find(pinoff); |
339 | cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff)); | 495 | if (ochip == NULL) |
496 | return; | ||
340 | 497 | ||
341 | for (pin = pinoff; pin < pinoff + 8; pin++) { | 498 | cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip)); |
342 | int irq = gpio_to_irq(pin); | 499 | cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip)); |
343 | struct irq_desc *desc = irq_desc + irq; | ||
344 | 500 | ||
345 | if (!(cause & (1 << (pin & 31)))) | 501 | for (i = 0; i < ochip->chip.ngpio; i++) { |
502 | int irq; | ||
503 | struct irq_desc *desc; | ||
504 | |||
505 | irq = ochip->secondary_irq_base + i; | ||
506 | |||
507 | if (!(cause & (1 << i))) | ||
346 | continue; | 508 | continue; |
347 | 509 | ||
510 | desc = irq_desc + irq; | ||
348 | if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { | 511 | if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { |
349 | /* Swap polarity (race with GPIO line) */ | 512 | /* Swap polarity (race with GPIO line) */ |
350 | u32 polarity; | 513 | u32 polarity; |
351 | 514 | ||
352 | polarity = readl(GPIO_IN_POL(pin)); | 515 | polarity = readl(GPIO_IN_POL(ochip)); |
353 | polarity ^= 1 << (pin & 31); | 516 | polarity ^= 1 << i; |
354 | writel(polarity, GPIO_IN_POL(pin)); | 517 | writel(polarity, GPIO_IN_POL(ochip)); |
355 | } | 518 | } |
519 | |||
356 | desc_handle_irq(irq, desc); | 520 | desc_handle_irq(irq, desc); |
357 | } | 521 | } |
358 | } | 522 | } |