diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2012-10-17 12:31:20 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-11-11 13:06:02 -0500 |
commit | a6c45b99a658521291cfb66ecf035cc58b38f206 (patch) | |
tree | 965842ac249c2b786c54d0fab12008276f419121 /drivers/pinctrl/pinctrl-coh901.c | |
parent | d4a31ee8997b2fbd82837182363cf8fa84abf347 (diff) |
pinctrl/coh901: use irqdomain, allocate irqdescs
This switches the COH 901 pinctrl driver to allocate its GPIO
IRQs dynamically, and start to use a linear irqdomain to map
from the hardware IRQs.
This way we can cut away the complex allocation of IRQ numbers
from the <mach/irqs.h> file.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-coh901.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-coh901.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index b446c9641212..152efae3df8f 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/irqdomain.h> | ||
16 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
@@ -67,7 +68,6 @@ struct u300_gpio { | |||
67 | struct resource *memres; | 68 | struct resource *memres; |
68 | void __iomem *base; | 69 | void __iomem *base; |
69 | struct device *dev; | 70 | struct device *dev; |
70 | int irq_base; | ||
71 | u32 stride; | 71 | u32 stride; |
72 | /* Register offsets */ | 72 | /* Register offsets */ |
73 | u32 pcr; | 73 | u32 pcr; |
@@ -83,6 +83,7 @@ struct u300_gpio_port { | |||
83 | struct list_head node; | 83 | struct list_head node; |
84 | struct u300_gpio *gpio; | 84 | struct u300_gpio *gpio; |
85 | char name[8]; | 85 | char name[8]; |
86 | struct irq_domain *domain; | ||
86 | int irq; | 87 | int irq; |
87 | int number; | 88 | int number; |
88 | u8 toggle_edge_mode; | 89 | u8 toggle_edge_mode; |
@@ -314,10 +315,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | |||
314 | static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | 315 | static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
315 | { | 316 | { |
316 | struct u300_gpio *gpio = to_u300_gpio(chip); | 317 | struct u300_gpio *gpio = to_u300_gpio(chip); |
317 | int retirq = gpio->irq_base + offset; | 318 | int portno = offset >> 3; |
319 | struct u300_gpio_port *port = NULL; | ||
320 | struct list_head *p; | ||
321 | int retirq; | ||
318 | 322 | ||
319 | dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset, | 323 | list_for_each(p, &gpio->port_list) { |
320 | retirq); | 324 | port = list_entry(p, struct u300_gpio_port, node); |
325 | if (port->number == portno) | ||
326 | break; | ||
327 | } | ||
328 | if (port == NULL) { | ||
329 | dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n", | ||
330 | offset); | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * The local hwirqs on the port are the lower three bits, there | ||
336 | * are exactly 8 IRQs per port since they are 8-bit | ||
337 | */ | ||
338 | retirq = irq_find_mapping(port->domain, (offset & 0x7)); | ||
339 | |||
340 | dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n", | ||
341 | offset, retirq, port->number); | ||
321 | return retirq; | 342 | return retirq; |
322 | } | 343 | } |
323 | 344 | ||
@@ -467,7 +488,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) | |||
467 | { | 488 | { |
468 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); | 489 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); |
469 | struct u300_gpio *gpio = port->gpio; | 490 | struct u300_gpio *gpio = port->gpio; |
470 | int offset = d->irq - gpio->irq_base; | 491 | int offset = (port->number << 3) + d->hwirq; |
471 | u32 val; | 492 | u32 val; |
472 | 493 | ||
473 | if ((trigger & IRQF_TRIGGER_RISING) && | 494 | if ((trigger & IRQF_TRIGGER_RISING) && |
@@ -503,10 +524,12 @@ static void u300_gpio_irq_enable(struct irq_data *d) | |||
503 | { | 524 | { |
504 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); | 525 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); |
505 | struct u300_gpio *gpio = port->gpio; | 526 | struct u300_gpio *gpio = port->gpio; |
506 | int offset = d->irq - gpio->irq_base; | 527 | int offset = (port->number << 3) + d->hwirq; |
507 | u32 val; | 528 | u32 val; |
508 | unsigned long flags; | 529 | unsigned long flags; |
509 | 530 | ||
531 | dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n", | ||
532 | d->hwirq, port->name, offset); | ||
510 | local_irq_save(flags); | 533 | local_irq_save(flags); |
511 | val = readl(U300_PIN_REG(offset, ien)); | 534 | val = readl(U300_PIN_REG(offset, ien)); |
512 | writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); | 535 | writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); |
@@ -517,7 +540,7 @@ static void u300_gpio_irq_disable(struct irq_data *d) | |||
517 | { | 540 | { |
518 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); | 541 | struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); |
519 | struct u300_gpio *gpio = port->gpio; | 542 | struct u300_gpio *gpio = port->gpio; |
520 | int offset = d->irq - gpio->irq_base; | 543 | int offset = (port->number << 3) + d->hwirq; |
521 | u32 val; | 544 | u32 val; |
522 | unsigned long flags; | 545 | unsigned long flags; |
523 | 546 | ||
@@ -555,8 +578,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
555 | int irqoffset; | 578 | int irqoffset; |
556 | 579 | ||
557 | for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { | 580 | for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { |
558 | int pin_irq = gpio->irq_base + (port->number << 3) | 581 | int pin_irq = irq_find_mapping(port->domain, irqoffset); |
559 | + irqoffset; | ||
560 | int offset = pinoffset + irqoffset; | 582 | int offset = pinoffset + irqoffset; |
561 | 583 | ||
562 | dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", | 584 | dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", |
@@ -631,6 +653,8 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio) | |||
631 | list_for_each_safe(p, n, &gpio->port_list) { | 653 | list_for_each_safe(p, n, &gpio->port_list) { |
632 | port = list_entry(p, struct u300_gpio_port, node); | 654 | port = list_entry(p, struct u300_gpio_port, node); |
633 | list_del(&port->node); | 655 | list_del(&port->node); |
656 | if (port->domain) | ||
657 | irq_domain_remove(port->domain); | ||
634 | kfree(port); | 658 | kfree(port); |
635 | } | 659 | } |
636 | } | 660 | } |
@@ -653,7 +677,6 @@ static int __init u300_gpio_probe(struct platform_device *pdev) | |||
653 | 677 | ||
654 | gpio->chip = u300_gpio_chip; | 678 | gpio->chip = u300_gpio_chip; |
655 | gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; | 679 | gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; |
656 | gpio->irq_base = plat->gpio_irq_base; | ||
657 | gpio->chip.dev = &pdev->dev; | 680 | gpio->chip.dev = &pdev->dev; |
658 | gpio->chip.base = plat->gpio_base; | 681 | gpio->chip.base = plat->gpio_base; |
659 | gpio->dev = &pdev->dev; | 682 | gpio->dev = &pdev->dev; |
@@ -732,18 +755,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev) | |||
732 | port->irq = platform_get_irq_byname(pdev, | 755 | port->irq = platform_get_irq_byname(pdev, |
733 | port->name); | 756 | port->name); |
734 | 757 | ||
735 | dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq, | 758 | dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq, |
736 | port->name); | 759 | port->name); |
737 | 760 | ||
761 | port->domain = irq_domain_add_linear(pdev->dev.of_node, | ||
762 | U300_GPIO_PINS_PER_PORT, | ||
763 | &irq_domain_simple_ops, | ||
764 | port); | ||
765 | if (!port->domain) | ||
766 | goto err_no_domain; | ||
767 | |||
738 | irq_set_chained_handler(port->irq, u300_gpio_irq_handler); | 768 | irq_set_chained_handler(port->irq, u300_gpio_irq_handler); |
739 | irq_set_handler_data(port->irq, port); | 769 | irq_set_handler_data(port->irq, port); |
740 | 770 | ||
741 | /* For each GPIO pin set the unique IRQ handler */ | 771 | /* For each GPIO pin set the unique IRQ handler */ |
742 | for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { | 772 | for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { |
743 | int irqno = gpio->irq_base + (portno << 3) + i; | 773 | int irqno = irq_create_mapping(port->domain, i); |
744 | 774 | ||
745 | dev_dbg(gpio->dev, "handler for IRQ %d on %s\n", | 775 | dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n", |
746 | irqno, port->name); | 776 | gpio->chip.base + (port->number << 3) + i, |
777 | port->name, irqno); | ||
747 | irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, | 778 | irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, |
748 | handle_simple_irq); | 779 | handle_simple_irq); |
749 | set_irq_flags(irqno, IRQF_VALID); | 780 | set_irq_flags(irqno, IRQF_VALID); |
@@ -776,6 +807,7 @@ static int __init u300_gpio_probe(struct platform_device *pdev) | |||
776 | err_no_pinctrl: | 807 | err_no_pinctrl: |
777 | err = gpiochip_remove(&gpio->chip); | 808 | err = gpiochip_remove(&gpio->chip); |
778 | err_no_chip: | 809 | err_no_chip: |
810 | err_no_domain: | ||
779 | err_no_port: | 811 | err_no_port: |
780 | u300_gpio_free_ports(gpio); | 812 | u300_gpio_free_ports(gpio); |
781 | iounmap(gpio->base); | 813 | iounmap(gpio->base); |