Date: | 2011-03-04 13:14:01 (13 years 24 days ago) |
---|---|
Author: | Lars C. |
Commit: | 1a111cf8ee655cf85a71cb4723ec0b8a6a1d1de8 |
Message: | Generalize gpio support Make GPIO-chip IRQ and GPIO IRQ base configurable and move GPIO-chip initialization to the sub-archs. |
Files: |
arch/mips/include/asm/mach-jz47xx/gpio.h (2 diffs) arch/mips/jz47xx/gpiov2.c (12 diffs) arch/mips/jz47xx/jz4740/Makefile (1 diff) arch/mips/jz47xx/jz4740/gpio.c (1 diff) |
Change Details
arch/mips/include/asm/mach-jz47xx/gpio.h | ||
---|---|---|
17 | 17 | #define __ASM_MACH_JZ47XX_GPIO_H__ |
18 | 18 | |
19 | 19 | #include <linux/types.h> |
20 | #include <linux/spinlock.h> | |
21 | #include <linux/sysdev.h> | |
20 | 22 | |
21 | 23 | enum jz_gpio_function { |
22 | 24 | JZ_GPIO_FUNC_NONE, |
... | ... | |
80 | 82 | #define JZ_GPIO_PORTC(x) ((x) + 32 * 2) |
81 | 83 | #define JZ_GPIO_PORTD(x) ((x) + 32 * 3) |
82 | 84 | |
85 | struct jz_gpio_chip { | |
86 | unsigned int id; | |
87 | ||
88 | unsigned int irq; | |
89 | ||
90 | uint32_t wakeup; | |
91 | uint32_t suspend_mask; | |
92 | uint32_t edge_trigger_both; | |
93 | ||
94 | void __iomem *base; | |
95 | ||
96 | spinlock_t lock; | |
97 | ||
98 | struct gpio_chip gpio_chip; | |
99 | struct sys_device sysdev; | |
100 | }; | |
101 | ||
102 | #define JZ47XX_GPIO_CHIP(_bank, _ngpio, _irq) { \ | |
103 | .irq = _irq, \ | |
104 | .gpio_chip = { \ | |
105 | .label = "Bank " _bank, \ | |
106 | .owner = THIS_MODULE, \ | |
107 | .ngpio = _ngpio, \ | |
108 | }, \ | |
109 | } | |
110 | ||
111 | int __init jz47xx_gpio_init(struct jz_gpio_chip *chips, size_t num, | |
112 | unsigned int irq_base); | |
113 | ||
83 | 114 | #endif |
arch/mips/jz47xx/gpiov2.c | ||
---|---|---|
1 | 1 | /* |
2 | 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
3 | * JZ4740 platform GPIO support | |
3 | * JZ47XX platform GPIO support | |
4 | 4 | * |
5 | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | 6 | * under the terms of the GNU General Public License as published by the |
... | ... | |
28 | 28 | #include <linux/debugfs.h> |
29 | 29 | #include <linux/seq_file.h> |
30 | 30 | |
31 | #include <jz4740/base.h> | |
32 | #include <jz4740/irq.h> | |
33 | #include <jz4740/gpio.h> | |
34 | ||
35 | #define JZ4740_GPIO_BASE_A (32*0) | |
36 | #define JZ4740_GPIO_BASE_B (32*1) | |
37 | #define JZ4740_GPIO_BASE_C (32*2) | |
38 | #define JZ4740_GPIO_BASE_D (32*3) | |
39 | ||
40 | #define JZ4740_GPIO_NUM_A 32 | |
41 | #define JZ4740_GPIO_NUM_B 32 | |
42 | #define JZ4740_GPIO_NUM_C 31 | |
43 | #define JZ4740_GPIO_NUM_D 32 | |
44 | ||
45 | #define JZ4740_IRQ_GPIO_BASE_A (JZ47XX_IRQ_GPIO(0) + JZ4740_GPIO_BASE_A) | |
46 | #define JZ4740_IRQ_GPIO_BASE_B (JZ47XX_IRQ_GPIO(0) + JZ4740_GPIO_BASE_B) | |
47 | #define JZ4740_IRQ_GPIO_BASE_C (JZ47XX_IRQ_GPIO(0) + JZ4740_GPIO_BASE_C) | |
48 | #define JZ4740_IRQ_GPIO_BASE_D (JZ47XX_IRQ_GPIO(0) + JZ4740_GPIO_BASE_D) | |
31 | #include <asm/mach-jz47xx/jz4740/base.h> | |
32 | #include <asm/mach-jz47xx/gpio.h> | |
49 | 33 | |
50 | 34 | #define JZ_REG_GPIO_PIN 0x00 |
51 | 35 | #define JZ_REG_GPIO_DATA 0x10 |
... | ... | |
76 | 60 | #define GPIO_TO_REG(gpio, reg) (gpio_to_jz_gpio_chip(gpio)->base + (reg)) |
77 | 61 | #define CHIP_TO_REG(chip, reg) (gpio_chip_to_jz_gpio_chip(chip)->base + (reg)) |
78 | 62 | |
79 | struct jz_gpio_chip { | |
80 | unsigned int irq; | |
81 | unsigned int irq_base; | |
82 | uint32_t wakeup; | |
83 | uint32_t suspend_mask; | |
84 | uint32_t edge_trigger_both; | |
85 | ||
86 | void __iomem *base; | |
87 | ||
88 | spinlock_t lock; | |
89 | ||
90 | struct gpio_chip gpio_chip; | |
91 | struct sys_device sysdev; | |
92 | }; | |
93 | ||
94 | static struct jz_gpio_chip jz4740_gpio_chips[]; | |
63 | static struct jz_gpio_chip *jz_gpio_chips; | |
64 | static size_t jz_gpio_num_chips; | |
65 | static unsigned int jz_gpio_irq_base; | |
95 | 66 | |
96 | 67 | static inline struct jz_gpio_chip *gpio_to_jz_gpio_chip(unsigned int gpio) |
97 | 68 | { |
98 | return &jz4740_gpio_chips[gpio >> 5]; | |
69 | return &jz_gpio_chips[gpio >> 5]; | |
99 | 70 | } |
100 | 71 | |
101 | 72 | static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *gpio_chip) |
... | ... | |
271 | 242 | |
272 | 243 | int gpio_to_irq(unsigned gpio) |
273 | 244 | { |
274 | return JZ47XX_IRQ_GPIO(0) + gpio; | |
245 | return jz_gpio_irq_base + gpio; | |
275 | 246 | } |
276 | 247 | EXPORT_SYMBOL_GPL(gpio_to_irq); |
277 | 248 | |
278 | 249 | int irq_to_gpio(unsigned irq) |
279 | 250 | { |
280 | return irq - JZ47XX_IRQ_GPIO(0); | |
251 | return irq - jz_gpio_irq_base; | |
281 | 252 | } |
282 | 253 | EXPORT_SYMBOL_GPL(irq_to_gpio); |
283 | 254 | |
... | ... | |
307 | 278 | { |
308 | 279 | uint32_t flag; |
309 | 280 | unsigned int gpio_irq; |
310 | unsigned int gpio_bank; | |
311 | 281 | struct jz_gpio_chip *chip = get_irq_desc_data(desc); |
312 | 282 | |
313 | gpio_bank = JZ47XX_IRQ_GPIO(0) - irq; | |
314 | ||
315 | 283 | flag = readl(chip->base + JZ_REG_GPIO_FLAG); |
316 | 284 | |
317 | 285 | if (!flag) |
... | ... | |
321 | 289 | |
322 | 290 | jz_gpio_check_trigger_both(chip, irq); |
323 | 291 | |
324 | gpio_irq += (gpio_bank << 5) + JZ47XX_IRQ_GPIO(0); | |
292 | gpio_irq += (chip->id << 5) + JZ47XX_IRQ_GPIO(0); | |
325 | 293 | |
326 | 294 | generic_handle_irq(gpio_irq); |
327 | 295 | }; |
... | ... | |
453 | 421 | */ |
454 | 422 | static struct lock_class_key gpio_lock_class; |
455 | 423 | |
456 | #define JZ4740_GPIO_CHIP(_bank) { \ | |
457 | .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ | |
458 | .gpio_chip = { \ | |
459 | .label = "Bank " # _bank, \ | |
460 | .owner = THIS_MODULE, \ | |
461 | .set = jz_gpio_set_value, \ | |
462 | .get = jz_gpio_get_value, \ | |
463 | .direction_output = jz_gpio_direction_output, \ | |
464 | .direction_input = jz_gpio_direction_input, \ | |
465 | .base = JZ4740_GPIO_BASE_ ## _bank, \ | |
466 | .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ | |
467 | }, \ | |
468 | } | |
469 | ||
470 | static struct jz_gpio_chip jz4740_gpio_chips[] = { | |
471 | JZ4740_GPIO_CHIP(A), | |
472 | JZ4740_GPIO_CHIP(B), | |
473 | JZ4740_GPIO_CHIP(C), | |
474 | JZ4740_GPIO_CHIP(D), | |
475 | }; | |
476 | ||
477 | 424 | static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev) |
478 | 425 | { |
479 | 426 | return container_of(dev, struct jz_gpio_chip, sysdev); |
480 | 427 | } |
481 | 428 | |
482 | static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state) | |
429 | static int jz_gpio_suspend(struct sys_device *dev, pm_message_t state) | |
483 | 430 | { |
484 | 431 | struct jz_gpio_chip *chip = sysdev_to_chip(dev); |
485 | 432 | |
... | ... | |
490 | 437 | return 0; |
491 | 438 | } |
492 | 439 | |
493 | static int jz4740_gpio_resume(struct sys_device *dev) | |
440 | static int jz_gpio_resume(struct sys_device *dev) | |
494 | 441 | { |
495 | 442 | struct jz_gpio_chip *chip = sysdev_to_chip(dev); |
496 | 443 | uint32_t mask = chip->suspend_mask; |
... | ... | |
501 | 448 | return 0; |
502 | 449 | } |
503 | 450 | |
504 | static struct sysdev_class jz4740_gpio_sysdev_class = { | |
451 | static struct sysdev_class jz_gpio_sysdev_class = { | |
505 | 452 | .name = "gpio", |
506 | .suspend = jz4740_gpio_suspend, | |
507 | .resume = jz4740_gpio_resume, | |
453 | .suspend = jz_gpio_suspend, | |
454 | .resume = jz_gpio_resume, | |
508 | 455 | }; |
509 | 456 | |
510 | static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) | |
457 | static int __init jz47xx_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) | |
511 | 458 | { |
512 | 459 | int ret, irq; |
460 | unsigned int chip_irq_base, chip_irq_end; | |
513 | 461 | |
514 | 462 | chip->sysdev.id = id; |
515 | chip->sysdev.cls = &jz4740_gpio_sysdev_class; | |
463 | chip->sysdev.cls = &jz_gpio_sysdev_class; | |
516 | 464 | ret = sysdev_register(&chip->sysdev); |
517 | 465 | |
518 | 466 | if (ret) |
... | ... | |
521 | 469 | spin_lock_init(&chip->lock); |
522 | 470 | |
523 | 471 | chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); |
472 | chip->gpio_chip.base = 32 * id; | |
473 | ||
474 | chip->gpio_chip.set = jz_gpio_set_value; | |
475 | chip->gpio_chip.get = jz_gpio_get_value; | |
476 | chip->gpio_chip.direction_output = jz_gpio_direction_output; | |
477 | chip->gpio_chip.direction_input = jz_gpio_direction_input; | |
524 | 478 | |
525 | 479 | gpiochip_add(&chip->gpio_chip); |
526 | 480 | |
527 | chip->irq = JZ47XX_IRQ_INTC_GPIO(id); | |
528 | 481 | set_irq_data(chip->irq, chip); |
529 | 482 | set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler); |
530 | 483 | |
531 | for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { | |
484 | chip_irq_base = jz_gpio_irq_base + id * 32; | |
485 | chip_irq_end = chip_irq_base + chip->gpio_chip.ngpio; | |
486 | ||
487 | for (irq = chip_irq_base; irq < chip_irq_end; ++irq) { | |
532 | 488 | lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class); |
533 | 489 | set_irq_chip_data(irq, chip); |
534 | 490 | set_irq_chip_and_handler(irq, &jz_gpio_irq_chip, handle_level_irq); |
... | ... | |
537 | 493 | return 0; |
538 | 494 | } |
539 | 495 | |
540 | static int __init jz4740_gpio_init(void) | |
496 | int __init jz47xx_gpio_init(struct jz_gpio_chip *chips, size_t num, | |
497 | unsigned int irq_base) | |
541 | 498 | { |
542 | 499 | unsigned int i; |
543 | 500 | int ret; |
544 | 501 | |
545 | ret = sysdev_class_register(&jz4740_gpio_sysdev_class); | |
502 | ret = sysdev_class_register(&jz_gpio_sysdev_class); | |
546 | 503 | if (ret) |
547 | 504 | return ret; |
548 | 505 | |
549 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) | |
550 | jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); | |
506 | jz_gpio_num_chips = num; | |
507 | jz_gpio_irq_base = irq_base; | |
508 | ||
509 | for (i = 0; i < num; ++i) | |
510 | jz47xx_gpio_chip_init(&chips[i], i); | |
551 | 511 | |
552 | printk(KERN_INFO "JZ4740 GPIO initalized\n"); | |
512 | printk(KERN_INFO "JZ47XX GPIO initalized\n"); | |
553 | 513 | |
554 | 514 | return 0; |
555 | 515 | } |
556 | arch_initcall(jz4740_gpio_init); | |
557 | 516 | |
558 | 517 | #ifdef CONFIG_DEBUG_FS |
559 | 518 | |
... | ... | |
565 | 524 | |
566 | 525 | static int gpio_regs_show(struct seq_file *s, void *unused) |
567 | 526 | { |
568 | struct jz_gpio_chip *chip = jz4740_gpio_chips; | |
527 | struct jz_gpio_chip *chip = jz_gpio_chips; | |
569 | 528 | int i; |
570 | 529 | |
571 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i, ++chip) { | |
530 | for (i = 0; i < jz_gpio_num_chips; ++i, ++chip) { | |
572 | 531 | seq_printf(s, "==GPIO %d==\n", i); |
573 | 532 | gpio_seq_reg(s, chip, "Pin", JZ_REG_GPIO_PIN); |
574 | 533 | gpio_seq_reg(s, chip, "Data", JZ_REG_GPIO_DATA); |
arch/mips/jz47xx/jz4740/Makefile | ||
---|---|---|
1 | 1 | |
2 | obj-y += clock.o platform.o time.o | |
2 | obj-y += clock.o platform.o time.o gpio.o | |
3 | 3 | |
4 | 4 | obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o |
5 | 5 | obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o |
arch/mips/jz47xx/jz4740/gpio.c | ||
---|---|---|
1 | #include <linux/init.h> | |
2 | ||
3 | #include <asm/mach-jz47xx/jz4740/irq.h> | |
4 | #include <asm/mach-jz47xx/gpio.h> | |
5 | ||
6 | ||
7 | static struct jz_gpio_chip jz4740_gpio_chips[] = { | |
8 | JZ47XX_GPIO_CHIP("A", 32, JZ4740_IRQ_GPIO0), | |
9 | JZ47XX_GPIO_CHIP("B", 32, JZ4740_IRQ_GPIO1), | |
10 | JZ47XX_GPIO_CHIP("C", 31, JZ4740_IRQ_GPIO2), | |
11 | JZ47XX_GPIO_CHIP("D", 32, JZ4740_IRQ_GPIO3), | |
12 | }; | |
13 | ||
14 | static int __init jz4740_gpio_init(void) | |
15 | { | |
16 | jz47xx_gpio_init(jz4740_gpio_chips, ARRAY_SIZE(jz4740_gpio_chips), | |
17 | JZ4740_IRQ_GPIO(0)); | |
18 | return 0; | |
19 | } | |
20 | arch_initcall(jz4740_gpio_init); | |
21 | ||
22 |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9