diff options
Diffstat (limited to 'drivers/gpio/gpio-mvebu.c')
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 61a6fde6c089..bf69a7eff370 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -117,7 +117,7 @@ static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvc | |||
117 | { | 117 | { |
118 | int cpu; | 118 | int cpu; |
119 | 119 | ||
120 | switch(mvchip->soc_variant) { | 120 | switch (mvchip->soc_variant) { |
121 | case MVEBU_GPIO_SOC_VARIANT_ORION: | 121 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
122 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | 122 | case MVEBU_GPIO_SOC_VARIANT_MV78200: |
123 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; | 123 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; |
@@ -133,7 +133,7 @@ static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvch | |||
133 | { | 133 | { |
134 | int cpu; | 134 | int cpu; |
135 | 135 | ||
136 | switch(mvchip->soc_variant) { | 136 | switch (mvchip->soc_variant) { |
137 | case MVEBU_GPIO_SOC_VARIANT_ORION: | 137 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
138 | return mvchip->membase + GPIO_EDGE_MASK_OFF; | 138 | return mvchip->membase + GPIO_EDGE_MASK_OFF; |
139 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | 139 | case MVEBU_GPIO_SOC_VARIANT_MV78200: |
@@ -151,7 +151,7 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | |||
151 | { | 151 | { |
152 | int cpu; | 152 | int cpu; |
153 | 153 | ||
154 | switch(mvchip->soc_variant) { | 154 | switch (mvchip->soc_variant) { |
155 | case MVEBU_GPIO_SOC_VARIANT_ORION: | 155 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
156 | return mvchip->membase + GPIO_LEVEL_MASK_OFF; | 156 | return mvchip->membase + GPIO_LEVEL_MASK_OFF; |
157 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | 157 | case MVEBU_GPIO_SOC_VARIANT_MV78200: |
@@ -401,7 +401,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
401 | /* | 401 | /* |
402 | * Configure interrupt polarity. | 402 | * Configure interrupt polarity. |
403 | */ | 403 | */ |
404 | switch(type) { | 404 | switch (type) { |
405 | case IRQ_TYPE_EDGE_RISING: | 405 | case IRQ_TYPE_EDGE_RISING: |
406 | case IRQ_TYPE_LEVEL_HIGH: | 406 | case IRQ_TYPE_LEVEL_HIGH: |
407 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | 407 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); |
@@ -470,18 +470,76 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
470 | } | 470 | } |
471 | } | 471 | } |
472 | 472 | ||
473 | #ifdef CONFIG_DEBUG_FS | ||
474 | #include <linux/seq_file.h> | ||
475 | |||
476 | static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | ||
477 | { | ||
478 | struct mvebu_gpio_chip *mvchip = | ||
479 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
480 | u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk; | ||
481 | int i; | ||
482 | |||
483 | out = readl_relaxed(mvebu_gpioreg_out(mvchip)); | ||
484 | io_conf = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | ||
485 | blink = readl_relaxed(mvebu_gpioreg_blink(mvchip)); | ||
486 | in_pol = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
487 | data_in = readl_relaxed(mvebu_gpioreg_data_in(mvchip)); | ||
488 | cause = readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)); | ||
489 | edg_msk = readl_relaxed(mvebu_gpioreg_edge_mask(mvchip)); | ||
490 | lvl_msk = readl_relaxed(mvebu_gpioreg_level_mask(mvchip)); | ||
491 | |||
492 | for (i = 0; i < chip->ngpio; i++) { | ||
493 | const char *label; | ||
494 | u32 msk; | ||
495 | bool is_out; | ||
496 | |||
497 | label = gpiochip_is_requested(chip, i); | ||
498 | if (!label) | ||
499 | continue; | ||
500 | |||
501 | msk = 1 << i; | ||
502 | is_out = !(io_conf & msk); | ||
503 | |||
504 | seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label); | ||
505 | |||
506 | if (is_out) { | ||
507 | seq_printf(s, " out %s %s\n", | ||
508 | out & msk ? "hi" : "lo", | ||
509 | blink & msk ? "(blink )" : ""); | ||
510 | continue; | ||
511 | } | ||
512 | |||
513 | seq_printf(s, " in %s (act %s) - IRQ", | ||
514 | (data_in ^ in_pol) & msk ? "hi" : "lo", | ||
515 | in_pol & msk ? "lo" : "hi"); | ||
516 | if (!((edg_msk | lvl_msk) & msk)) { | ||
517 | seq_printf(s, " disabled\n"); | ||
518 | continue; | ||
519 | } | ||
520 | if (edg_msk & msk) | ||
521 | seq_printf(s, " edge "); | ||
522 | if (lvl_msk & msk) | ||
523 | seq_printf(s, " level"); | ||
524 | seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); | ||
525 | } | ||
526 | } | ||
527 | #else | ||
528 | #define mvebu_gpio_dbg_show NULL | ||
529 | #endif | ||
530 | |||
473 | static struct of_device_id mvebu_gpio_of_match[] = { | 531 | static struct of_device_id mvebu_gpio_of_match[] = { |
474 | { | 532 | { |
475 | .compatible = "marvell,orion-gpio", | 533 | .compatible = "marvell,orion-gpio", |
476 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_ORION, | 534 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, |
477 | }, | 535 | }, |
478 | { | 536 | { |
479 | .compatible = "marvell,mv78200-gpio", | 537 | .compatible = "marvell,mv78200-gpio", |
480 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200, | 538 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200, |
481 | }, | 539 | }, |
482 | { | 540 | { |
483 | .compatible = "marvell,armadaxp-gpio", | 541 | .compatible = "marvell,armadaxp-gpio", |
484 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, | 542 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, |
485 | }, | 543 | }, |
486 | { | 544 | { |
487 | /* sentinel */ | 545 | /* sentinel */ |
@@ -509,13 +567,13 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
509 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; | 567 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; |
510 | 568 | ||
511 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 569 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
512 | if (! res) { | 570 | if (!res) { |
513 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | 571 | dev_err(&pdev->dev, "Cannot get memory resource\n"); |
514 | return -ENODEV; | 572 | return -ENODEV; |
515 | } | 573 | } |
516 | 574 | ||
517 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); | 575 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); |
518 | if (! mvchip){ | 576 | if (!mvchip) { |
519 | dev_err(&pdev->dev, "Cannot allocate memory\n"); | 577 | dev_err(&pdev->dev, "Cannot allocate memory\n"); |
520 | return -ENOMEM; | 578 | return -ENOMEM; |
521 | } | 579 | } |
@@ -550,6 +608,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
550 | mvchip->chip.ngpio = ngpios; | 608 | mvchip->chip.ngpio = ngpios; |
551 | mvchip->chip.can_sleep = 0; | 609 | mvchip->chip.can_sleep = 0; |
552 | mvchip->chip.of_node = np; | 610 | mvchip->chip.of_node = np; |
611 | mvchip->chip.dbg_show = mvebu_gpio_dbg_show; | ||
553 | 612 | ||
554 | spin_lock_init(&mvchip->lock); | 613 | spin_lock_init(&mvchip->lock); |
555 | mvchip->membase = devm_ioremap_resource(&pdev->dev, res); | 614 | mvchip->membase = devm_ioremap_resource(&pdev->dev, res); |
@@ -560,21 +619,21 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
560 | * per-CPU registers */ | 619 | * per-CPU registers */ |
561 | if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { | 620 | if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { |
562 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 621 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
563 | if (! res) { | 622 | if (!res) { |
564 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | 623 | dev_err(&pdev->dev, "Cannot get memory resource\n"); |
565 | return -ENODEV; | 624 | return -ENODEV; |
566 | } | 625 | } |
567 | 626 | ||
568 | mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev, | 627 | mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev, |
569 | res); | 628 | res); |
570 | if (IS_ERR(mvchip->percpu_membase)) | 629 | if (IS_ERR(mvchip->percpu_membase)) |
571 | return PTR_ERR(mvchip->percpu_membase); | 630 | return PTR_ERR(mvchip->percpu_membase); |
572 | } | 631 | } |
573 | 632 | ||
574 | /* | 633 | /* |
575 | * Mask and clear GPIO interrupts. | 634 | * Mask and clear GPIO interrupts. |
576 | */ | 635 | */ |
577 | switch(soc_variant) { | 636 | switch (soc_variant) { |
578 | case MVEBU_GPIO_SOC_VARIANT_ORION: | 637 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
579 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | 638 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); |
580 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); | 639 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); |
@@ -632,7 +691,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
632 | 691 | ||
633 | gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, | 692 | gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, |
634 | mvchip->membase, handle_level_irq); | 693 | mvchip->membase, handle_level_irq); |
635 | if (! gc) { | 694 | if (!gc) { |
636 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); | 695 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); |
637 | return -ENOMEM; | 696 | return -ENOMEM; |
638 | } | 697 | } |