diff options
author | Herbert Valerio Riedel <hvr@gnu.org> | 2007-11-26 12:45:59 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-26 09:37:31 -0500 |
commit | 7ca722533979d47563e75a40c86c405153818b83 (patch) | |
tree | f715a2f370d300587736b47d32f3fe64bdecf2ce /arch/arm/mach-ep93xx | |
parent | 4e9f9fd5148004b983b29e15de66918e71da56c0 (diff) |
[ARM] 4669/1: ep93xx: simplify GPIO code and cleanups
This patch renumbers the (virtual) GPIO line numbering to have all
irq-capable gpio lines <= EP93XX_GPIO_LINE_MAX_IRQ by swapping the
port f range with the port c range; This simplifies code such as
#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
or
if (line >= 0 && line < 16) {
/* Port A/B */
} else if (line >= 40 && line < 48) {
/* Port F */
}
considerably; in addition to the renumbering this patch also
introduces macro constants EP93XX_GPIO_LINE_MAX_IRQ and
EP93XX_GPIO_LINE_MAX, and replaces most magic numbers by those and
invocations of gpio_to_irq()/irq_to_gpio().
Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org>
Acked-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 147 |
1 files changed, 70 insertions, 77 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8a7340661377..58957d7a5763 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3]; | |||
157 | static unsigned char gpio_int_type1[3]; | 157 | static unsigned char gpio_int_type1[3]; |
158 | static unsigned char gpio_int_type2[3]; | 158 | static unsigned char gpio_int_type2[3]; |
159 | 159 | ||
160 | static void update_gpio_int_params(int abf) | 160 | /* Port ordering is: A B F */ |
161 | static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; | ||
162 | static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; | ||
163 | static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; | ||
164 | static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c }; | ||
165 | |||
166 | static void update_gpio_int_params(unsigned port) | ||
161 | { | 167 | { |
162 | if (abf == 0) { | 168 | BUG_ON(port > 2); |
163 | __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); | ||
164 | __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); | ||
165 | __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); | ||
166 | __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE); | ||
167 | } else if (abf == 1) { | ||
168 | __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); | ||
169 | __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); | ||
170 | __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); | ||
171 | __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE); | ||
172 | } else if (abf == 2) { | ||
173 | __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE); | ||
174 | __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2); | ||
175 | __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1); | ||
176 | __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE); | ||
177 | } else { | ||
178 | BUG(); | ||
179 | } | ||
180 | } | ||
181 | 169 | ||
170 | __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); | ||
171 | |||
172 | __raw_writeb(gpio_int_type2[port], | ||
173 | EP93XX_GPIO_REG(int_type2_register_offset[port])); | ||
174 | |||
175 | __raw_writeb(gpio_int_type1[port], | ||
176 | EP93XX_GPIO_REG(int_type1_register_offset[port])); | ||
177 | |||
178 | __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], | ||
179 | EP93XX_GPIO_REG(int_en_register_offset[port])); | ||
180 | } | ||
182 | 181 | ||
183 | static unsigned char data_register_offset[8] = { | 182 | /* Port ordering is: A B F D E C G H */ |
184 | 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, | 183 | static const u8 data_register_offset[8] = { |
184 | 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40, | ||
185 | }; | 185 | }; |
186 | 186 | ||
187 | static unsigned char data_direction_register_offset[8] = { | 187 | static const u8 data_direction_register_offset[8] = { |
188 | 0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44, | 188 | 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static void ep93xx_gpio_set_direction(unsigned line, int direction) | 191 | static void ep93xx_gpio_set_direction(unsigned line, int direction) |
@@ -199,14 +199,10 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction) | |||
199 | 199 | ||
200 | local_irq_save(flags); | 200 | local_irq_save(flags); |
201 | if (direction == GPIO_OUT) { | 201 | if (direction == GPIO_OUT) { |
202 | if (line >= 0 && line < 16) { | 202 | if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) { |
203 | /* Port A/B. */ | 203 | /* Port A/B/F */ |
204 | gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); | 204 | gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); |
205 | update_gpio_int_params(line >> 3); | 205 | update_gpio_int_params(line >> 3); |
206 | } else if (line >= 40 && line < 48) { | ||
207 | /* Port F. */ | ||
208 | gpio_int_unmasked[2] &= ~(1 << (line & 7)); | ||
209 | update_gpio_int_params(2); | ||
210 | } | 206 | } |
211 | 207 | ||
212 | v = __raw_readb(data_direction_register); | 208 | v = __raw_readb(data_direction_register); |
@@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config); | |||
228 | 224 | ||
229 | int gpio_direction_input(unsigned gpio) | 225 | int gpio_direction_input(unsigned gpio) |
230 | { | 226 | { |
231 | if (gpio > EP93XX_GPIO_LINE_H(7)) | 227 | if (gpio > EP93XX_GPIO_LINE_MAX) |
232 | return -EINVAL; | 228 | return -EINVAL; |
233 | 229 | ||
234 | ep93xx_gpio_set_direction(gpio, GPIO_IN); | 230 | ep93xx_gpio_set_direction(gpio, GPIO_IN); |
@@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input); | |||
239 | 235 | ||
240 | int gpio_direction_output(unsigned gpio, int value) | 236 | int gpio_direction_output(unsigned gpio, int value) |
241 | { | 237 | { |
242 | if (gpio > EP93XX_GPIO_LINE_H(7)) | 238 | if (gpio > EP93XX_GPIO_LINE_MAX) |
243 | return -EINVAL; | 239 | return -EINVAL; |
244 | 240 | ||
245 | gpio_set_value(gpio, value); | 241 | gpio_set_value(gpio, value); |
@@ -290,47 +286,50 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
290 | status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); | 286 | status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); |
291 | for (i = 0; i < 8; i++) { | 287 | for (i = 0; i < 8; i++) { |
292 | if (status & (1 << i)) { | 288 | if (status & (1 << i)) { |
293 | desc = irq_desc + IRQ_EP93XX_GPIO(0) + i; | 289 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; |
294 | desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc); | 290 | desc = irq_desc + gpio_irq; |
291 | desc_handle_irq(gpio_irq, desc); | ||
295 | } | 292 | } |
296 | } | 293 | } |
297 | 294 | ||
298 | status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); | 295 | status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); |
299 | for (i = 0; i < 8; i++) { | 296 | for (i = 0; i < 8; i++) { |
300 | if (status & (1 << i)) { | 297 | if (status & (1 << i)) { |
301 | desc = irq_desc + IRQ_EP93XX_GPIO(8) + i; | 298 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; |
302 | desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc); | 299 | desc = irq_desc + gpio_irq; |
300 | desc_handle_irq(gpio_irq, desc); | ||
303 | } | 301 | } |
304 | } | 302 | } |
305 | } | 303 | } |
306 | 304 | ||
307 | static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) | 305 | static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) |
308 | { | 306 | { |
309 | int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4); | 307 | /* |
308 | * map discontiguous hw irq range to continous sw irq range: | ||
309 | * | ||
310 | * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) | ||
311 | */ | ||
312 | int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ | ||
313 | int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; | ||
310 | 314 | ||
311 | desc_handle_irq(gpio_irq, irq_desc + gpio_irq); | 315 | desc_handle_irq(gpio_irq, irq_desc + gpio_irq); |
312 | } | 316 | } |
313 | 317 | ||
314 | static void ep93xx_gpio_irq_mask_ack(unsigned int irq) | 318 | static void ep93xx_gpio_irq_mask_ack(unsigned int irq) |
315 | { | 319 | { |
316 | int line = irq - IRQ_EP93XX_GPIO(0); | 320 | int line = irq_to_gpio(irq); |
317 | int port = line >> 3; | 321 | int port = line >> 3; |
322 | int port_mask = 1 << (line & 7); | ||
318 | 323 | ||
319 | gpio_int_unmasked[port] &= ~(1 << (line & 7)); | 324 | gpio_int_unmasked[port] &= ~port_mask; |
320 | update_gpio_int_params(port); | 325 | update_gpio_int_params(port); |
321 | 326 | ||
322 | if (port == 0) { | 327 | __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); |
323 | __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); | ||
324 | } else if (port == 1) { | ||
325 | __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK); | ||
326 | } else if (port == 2) { | ||
327 | __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK); | ||
328 | } | ||
329 | } | 328 | } |
330 | 329 | ||
331 | static void ep93xx_gpio_irq_mask(unsigned int irq) | 330 | static void ep93xx_gpio_irq_mask(unsigned int irq) |
332 | { | 331 | { |
333 | int line = irq - IRQ_EP93XX_GPIO(0); | 332 | int line = irq_to_gpio(irq); |
334 | int port = line >> 3; | 333 | int port = line >> 3; |
335 | 334 | ||
336 | gpio_int_unmasked[port] &= ~(1 << (line & 7)); | 335 | gpio_int_unmasked[port] &= ~(1 << (line & 7)); |
@@ -339,7 +338,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq) | |||
339 | 338 | ||
340 | static void ep93xx_gpio_irq_unmask(unsigned int irq) | 339 | static void ep93xx_gpio_irq_unmask(unsigned int irq) |
341 | { | 340 | { |
342 | int line = irq - IRQ_EP93XX_GPIO(0); | 341 | int line = irq_to_gpio(irq); |
343 | int port = line >> 3; | 342 | int port = line >> 3; |
344 | 343 | ||
345 | gpio_int_unmasked[port] |= 1 << (line & 7); | 344 | gpio_int_unmasked[port] |= 1 << (line & 7); |
@@ -354,37 +353,30 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq) | |||
354 | */ | 353 | */ |
355 | static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) | 354 | static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) |
356 | { | 355 | { |
357 | int port; | 356 | const int gpio = irq_to_gpio(irq); |
358 | int line; | 357 | const int port = gpio >> 3; |
358 | const int port_mask = 1 << (gpio & 7); | ||
359 | 359 | ||
360 | line = irq - IRQ_EP93XX_GPIO(0); | 360 | ep93xx_gpio_set_direction(gpio, GPIO_IN); |
361 | if (line >= 0 && line < 16) { | ||
362 | ep93xx_gpio_set_direction(line, GPIO_IN); | ||
363 | } else { | ||
364 | ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN); | ||
365 | } | ||
366 | |||
367 | port = line >> 3; | ||
368 | line &= 7; | ||
369 | 361 | ||
370 | if (type & IRQT_RISING) { | 362 | if (type & IRQT_RISING) { |
371 | gpio_int_enabled[port] |= 1 << line; | 363 | gpio_int_enabled[port] |= port_mask; |
372 | gpio_int_type1[port] |= 1 << line; | 364 | gpio_int_type1[port] |= port_mask; |
373 | gpio_int_type2[port] |= 1 << line; | 365 | gpio_int_type2[port] |= port_mask; |
374 | } else if (type & IRQT_FALLING) { | 366 | } else if (type & IRQT_FALLING) { |
375 | gpio_int_enabled[port] |= 1 << line; | 367 | gpio_int_enabled[port] |= port_mask; |
376 | gpio_int_type1[port] |= 1 << line; | 368 | gpio_int_type1[port] |= port_mask; |
377 | gpio_int_type2[port] &= ~(1 << line); | 369 | gpio_int_type2[port] &= ~port_mask; |
378 | } else if (type & IRQT_HIGH) { | 370 | } else if (type & IRQT_HIGH) { |
379 | gpio_int_enabled[port] |= 1 << line; | 371 | gpio_int_enabled[port] |= port_mask; |
380 | gpio_int_type1[port] &= ~(1 << line); | 372 | gpio_int_type1[port] &= ~port_mask; |
381 | gpio_int_type2[port] |= 1 << line; | 373 | gpio_int_type2[port] |= port_mask; |
382 | } else if (type & IRQT_LOW) { | 374 | } else if (type & IRQT_LOW) { |
383 | gpio_int_enabled[port] |= 1 << line; | 375 | gpio_int_enabled[port] |= port_mask; |
384 | gpio_int_type1[port] &= ~(1 << line); | 376 | gpio_int_type1[port] &= ~port_mask; |
385 | gpio_int_type2[port] &= ~(1 << line); | 377 | gpio_int_type2[port] &= ~port_mask; |
386 | } else { | 378 | } else { |
387 | gpio_int_enabled[port] &= ~(1 << line); | 379 | gpio_int_enabled[port] &= ~port_mask; |
388 | } | 380 | } |
389 | update_gpio_int_params(port); | 381 | update_gpio_int_params(port); |
390 | 382 | ||
@@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = { | |||
402 | 394 | ||
403 | void __init ep93xx_init_irq(void) | 395 | void __init ep93xx_init_irq(void) |
404 | { | 396 | { |
405 | int irq; | 397 | int gpio_irq; |
406 | 398 | ||
407 | vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); | 399 | vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); |
408 | vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); | 400 | vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); |
409 | 401 | ||
410 | for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) { | 402 | for (gpio_irq = gpio_to_irq(0); |
411 | set_irq_chip(irq, &ep93xx_gpio_irq_chip); | 403 | gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { |
412 | set_irq_handler(irq, handle_level_irq); | 404 | set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip); |
413 | set_irq_flags(irq, IRQF_VALID); | 405 | set_irq_handler(gpio_irq, handle_level_irq); |
406 | set_irq_flags(gpio_irq, IRQF_VALID); | ||
414 | } | 407 | } |
415 | 408 | ||
416 | set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); | 409 | set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); |