diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-05-29 05:18:48 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-06-19 03:35:12 -0400 |
commit | 22763bf527446fe1f25ac365d846b02fd040e19c (patch) | |
tree | 77fee62e21bae80c0158cd05b81a928b3a23644e /drivers/pinctrl/spear | |
parent | aebdc8abc9db86e2bd33070fc2f961012fff74b4 (diff) |
pinctrl: spear: switch plgpio to irqchip helpers
This switches the SPEAr PLGPIO driver over to using the irqchip
helpers.
As part of this effort, also get rid of the strange irq_base
calculation and failure to use d->hwirq for obtaining a local
irqchip offset.
Cc: Viresh Kumar <viresh.linux@gmail.com>
Cc: Shiraz Hashim <shiraz.linux.kernel@gmail.com>
Cc: spear-devel@list.st.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/spear')
-rw-r--r-- | drivers/pinctrl/spear/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pinctrl/spear/pinctrl-plgpio.c | 81 |
2 files changed, 31 insertions, 51 deletions
diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig index 04d93e602674..9ef18eb958e1 100644 --- a/drivers/pinctrl/spear/Kconfig +++ b/drivers/pinctrl/spear/Kconfig | |||
@@ -48,6 +48,7 @@ config PINCTRL_SPEAR1340 | |||
48 | config PINCTRL_SPEAR_PLGPIO | 48 | config PINCTRL_SPEAR_PLGPIO |
49 | bool "SPEAr SoC PLGPIO Controller" | 49 | bool "SPEAr SoC PLGPIO Controller" |
50 | depends on GPIOLIB && PINCTRL_SPEAR | 50 | depends on GPIOLIB && PINCTRL_SPEAR |
51 | select GPIOLIB_IRQCHIP | ||
51 | help | 52 | help |
52 | Say yes here to support PLGPIO controller on ST Microelectronics SPEAr | 53 | Say yes here to support PLGPIO controller on ST Microelectronics SPEAr |
53 | SoCs. | 54 | SoCs. |
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c index ff2940e9f2a7..3a20cdc65810 100644 --- a/drivers/pinctrl/spear/pinctrl-plgpio.c +++ b/drivers/pinctrl/spear/pinctrl-plgpio.c | |||
@@ -11,12 +11,11 @@ | |||
11 | 11 | ||
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio/driver.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/irq.h> | ||
17 | #include <linux/irqdomain.h> | ||
18 | #include <linux/irqchip/chained_irq.h> | ||
19 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_platform.h> | ||
20 | #include <linux/pinctrl/consumer.h> | 19 | #include <linux/pinctrl/consumer.h> |
21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
22 | #include <linux/pm.h> | 21 | #include <linux/pm.h> |
@@ -54,7 +53,6 @@ struct plgpio_regs { | |||
54 | * | 53 | * |
55 | * lock: lock for guarding gpio registers | 54 | * lock: lock for guarding gpio registers |
56 | * base: base address of plgpio block | 55 | * base: base address of plgpio block |
57 | * irq_base: irq number of plgpio0 | ||
58 | * chip: gpio framework specific chip information structure | 56 | * chip: gpio framework specific chip information structure |
59 | * p2o: function ptr for pin to offset conversion. This is required only for | 57 | * p2o: function ptr for pin to offset conversion. This is required only for |
60 | * machines where mapping b/w pin and offset is not 1-to-1. | 58 | * machines where mapping b/w pin and offset is not 1-to-1. |
@@ -68,8 +66,6 @@ struct plgpio { | |||
68 | spinlock_t lock; | 66 | spinlock_t lock; |
69 | void __iomem *base; | 67 | void __iomem *base; |
70 | struct clk *clk; | 68 | struct clk *clk; |
71 | unsigned irq_base; | ||
72 | struct irq_domain *irq_domain; | ||
73 | struct gpio_chip chip; | 69 | struct gpio_chip chip; |
74 | int (*p2o)(int pin); /* pin_to_offset */ | 70 | int (*p2o)(int pin); /* pin_to_offset */ |
75 | int (*o2p)(int offset); /* offset_to_pin */ | 71 | int (*o2p)(int offset); /* offset_to_pin */ |
@@ -280,21 +276,12 @@ disable_clk: | |||
280 | pinctrl_free_gpio(gpio); | 276 | pinctrl_free_gpio(gpio); |
281 | } | 277 | } |
282 | 278 | ||
283 | static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
284 | { | ||
285 | struct plgpio *plgpio = container_of(chip, struct plgpio, chip); | ||
286 | |||
287 | if (IS_ERR_VALUE(plgpio->irq_base)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | return irq_find_mapping(plgpio->irq_domain, offset); | ||
291 | } | ||
292 | |||
293 | /* PLGPIO IRQ */ | 279 | /* PLGPIO IRQ */ |
294 | static void plgpio_irq_disable(struct irq_data *d) | 280 | static void plgpio_irq_disable(struct irq_data *d) |
295 | { | 281 | { |
296 | struct plgpio *plgpio = irq_data_get_irq_chip_data(d); | 282 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
297 | int offset = d->irq - plgpio->irq_base; | 283 | struct plgpio *plgpio = container_of(gc, struct plgpio, chip); |
284 | int offset = d->hwirq; | ||
298 | unsigned long flags; | 285 | unsigned long flags; |
299 | 286 | ||
300 | /* get correct offset for "offset" pin */ | 287 | /* get correct offset for "offset" pin */ |
@@ -311,8 +298,9 @@ static void plgpio_irq_disable(struct irq_data *d) | |||
311 | 298 | ||
312 | static void plgpio_irq_enable(struct irq_data *d) | 299 | static void plgpio_irq_enable(struct irq_data *d) |
313 | { | 300 | { |
314 | struct plgpio *plgpio = irq_data_get_irq_chip_data(d); | 301 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
315 | int offset = d->irq - plgpio->irq_base; | 302 | struct plgpio *plgpio = container_of(gc, struct plgpio, chip); |
303 | int offset = d->hwirq; | ||
316 | unsigned long flags; | 304 | unsigned long flags; |
317 | 305 | ||
318 | /* get correct offset for "offset" pin */ | 306 | /* get correct offset for "offset" pin */ |
@@ -329,8 +317,9 @@ static void plgpio_irq_enable(struct irq_data *d) | |||
329 | 317 | ||
330 | static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger) | 318 | static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger) |
331 | { | 319 | { |
332 | struct plgpio *plgpio = irq_data_get_irq_chip_data(d); | 320 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
333 | int offset = d->irq - plgpio->irq_base; | 321 | struct plgpio *plgpio = container_of(gc, struct plgpio, chip); |
322 | int offset = d->hwirq; | ||
334 | void __iomem *reg_off; | 323 | void __iomem *reg_off; |
335 | unsigned int supported_type = 0, val; | 324 | unsigned int supported_type = 0, val; |
336 | 325 | ||
@@ -369,7 +358,8 @@ static struct irq_chip plgpio_irqchip = { | |||
369 | 358 | ||
370 | static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc) | 359 | static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc) |
371 | { | 360 | { |
372 | struct plgpio *plgpio = irq_get_handler_data(irq); | 361 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
362 | struct plgpio *plgpio = container_of(gc, struct plgpio, chip); | ||
373 | struct irq_chip *irqchip = irq_desc_get_chip(desc); | 363 | struct irq_chip *irqchip = irq_desc_get_chip(desc); |
374 | int regs_count, count, pin, offset, i = 0; | 364 | int regs_count, count, pin, offset, i = 0; |
375 | unsigned long pending; | 365 | unsigned long pending; |
@@ -410,7 +400,8 @@ static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
410 | 400 | ||
411 | /* get correct irq line number */ | 401 | /* get correct irq line number */ |
412 | pin = i * MAX_GPIO_PER_REG + pin; | 402 | pin = i * MAX_GPIO_PER_REG + pin; |
413 | generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin)); | 403 | generic_handle_irq( |
404 | irq_find_mapping(gc->irqdomain, pin)); | ||
414 | } | 405 | } |
415 | } | 406 | } |
416 | chained_irq_exit(irqchip, desc); | 407 | chained_irq_exit(irqchip, desc); |
@@ -523,10 +514,9 @@ end: | |||
523 | } | 514 | } |
524 | static int plgpio_probe(struct platform_device *pdev) | 515 | static int plgpio_probe(struct platform_device *pdev) |
525 | { | 516 | { |
526 | struct device_node *np = pdev->dev.of_node; | ||
527 | struct plgpio *plgpio; | 517 | struct plgpio *plgpio; |
528 | struct resource *res; | 518 | struct resource *res; |
529 | int ret, irq, i; | 519 | int ret, irq; |
530 | 520 | ||
531 | plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL); | 521 | plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL); |
532 | if (!plgpio) { | 522 | if (!plgpio) { |
@@ -563,7 +553,6 @@ static int plgpio_probe(struct platform_device *pdev) | |||
563 | platform_set_drvdata(pdev, plgpio); | 553 | platform_set_drvdata(pdev, plgpio); |
564 | spin_lock_init(&plgpio->lock); | 554 | spin_lock_init(&plgpio->lock); |
565 | 555 | ||
566 | plgpio->irq_base = -1; | ||
567 | plgpio->chip.base = -1; | 556 | plgpio->chip.base = -1; |
568 | plgpio->chip.request = plgpio_request; | 557 | plgpio->chip.request = plgpio_request; |
569 | plgpio->chip.free = plgpio_free; | 558 | plgpio->chip.free = plgpio_free; |
@@ -571,10 +560,10 @@ static int plgpio_probe(struct platform_device *pdev) | |||
571 | plgpio->chip.direction_output = plgpio_direction_output; | 560 | plgpio->chip.direction_output = plgpio_direction_output; |
572 | plgpio->chip.get = plgpio_get_value; | 561 | plgpio->chip.get = plgpio_get_value; |
573 | plgpio->chip.set = plgpio_set_value; | 562 | plgpio->chip.set = plgpio_set_value; |
574 | plgpio->chip.to_irq = plgpio_to_irq; | ||
575 | plgpio->chip.label = dev_name(&pdev->dev); | 563 | plgpio->chip.label = dev_name(&pdev->dev); |
576 | plgpio->chip.dev = &pdev->dev; | 564 | plgpio->chip.dev = &pdev->dev; |
577 | plgpio->chip.owner = THIS_MODULE; | 565 | plgpio->chip.owner = THIS_MODULE; |
566 | plgpio->chip.of_node = pdev->dev.of_node; | ||
578 | 567 | ||
579 | if (!IS_ERR(plgpio->clk)) { | 568 | if (!IS_ERR(plgpio->clk)) { |
580 | ret = clk_prepare(plgpio->clk); | 569 | ret = clk_prepare(plgpio->clk); |
@@ -592,35 +581,25 @@ static int plgpio_probe(struct platform_device *pdev) | |||
592 | 581 | ||
593 | irq = platform_get_irq(pdev, 0); | 582 | irq = platform_get_irq(pdev, 0); |
594 | if (irq < 0) { | 583 | if (irq < 0) { |
595 | dev_info(&pdev->dev, "irqs not supported\n"); | 584 | dev_info(&pdev->dev, "PLGPIO registered without IRQs\n"); |
596 | return 0; | ||
597 | } | ||
598 | |||
599 | plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0); | ||
600 | if (IS_ERR_VALUE(plgpio->irq_base)) { | ||
601 | /* we would not support irq for gpio */ | ||
602 | dev_warn(&pdev->dev, "couldn't allocate irq base\n"); | ||
603 | return 0; | 585 | return 0; |
604 | } | 586 | } |
605 | 587 | ||
606 | plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio, | 588 | ret = gpiochip_irqchip_add(&plgpio->chip, |
607 | plgpio->irq_base, 0, &irq_domain_simple_ops, NULL); | 589 | &plgpio_irqchip, |
608 | if (WARN_ON(!plgpio->irq_domain)) { | 590 | 0, |
609 | dev_err(&pdev->dev, "irq domain init failed\n"); | 591 | handle_simple_irq, |
610 | irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio); | 592 | IRQ_TYPE_NONE); |
611 | ret = -ENXIO; | 593 | if (ret) { |
594 | dev_err(&pdev->dev, "failed to add irqchip to gpiochip\n"); | ||
612 | goto remove_gpiochip; | 595 | goto remove_gpiochip; |
613 | } | 596 | } |
614 | 597 | ||
615 | irq_set_chained_handler(irq, plgpio_irq_handler); | 598 | gpiochip_set_chained_irqchip(&plgpio->chip, |
616 | for (i = 0; i < plgpio->chip.ngpio; i++) { | 599 | &plgpio_irqchip, |
617 | irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip, | 600 | irq, |
618 | handle_simple_irq); | 601 | plgpio_irq_handler); |
619 | set_irq_flags(i + plgpio->irq_base, IRQF_VALID); | ||
620 | irq_set_chip_data(i + plgpio->irq_base, plgpio); | ||
621 | } | ||
622 | 602 | ||
623 | irq_set_handler_data(irq, plgpio); | ||
624 | dev_info(&pdev->dev, "PLGPIO registered with IRQs\n"); | 603 | dev_info(&pdev->dev, "PLGPIO registered with IRQs\n"); |
625 | 604 | ||
626 | return 0; | 605 | return 0; |