diff options
Diffstat (limited to 'drivers/gpio/gpio-mvebu.c')
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 100 |
1 files changed, 59 insertions, 41 deletions
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7bc3e9b288f3..d0bc123c7975 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #define GPIO_LEVEL_MASK_OFF 0x001c | 59 | #define GPIO_LEVEL_MASK_OFF 0x001c |
60 | 60 | ||
61 | /* The MV78200 has per-CPU registers for edge mask and level mask */ | 61 | /* The MV78200 has per-CPU registers for edge mask and level mask */ |
62 | #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) | 62 | #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) |
63 | #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) | 63 | #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) |
64 | 64 | ||
65 | /* The Armada XP has per-CPU registers for interrupt cause, interrupt | 65 | /* The Armada XP has per-CPU registers for interrupt cause, interrupt |
@@ -69,11 +69,11 @@ | |||
69 | #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) | 69 | #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) |
70 | #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) | 70 | #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) |
71 | 71 | ||
72 | #define MVEBU_GPIO_SOC_VARIANT_ORION 0x1 | 72 | #define MVEBU_GPIO_SOC_VARIANT_ORION 0x1 |
73 | #define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2 | 73 | #define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2 |
74 | #define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3 | 74 | #define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3 |
75 | 75 | ||
76 | #define MVEBU_MAX_GPIO_PER_BANK 32 | 76 | #define MVEBU_MAX_GPIO_PER_BANK 32 |
77 | 77 | ||
78 | struct mvebu_gpio_chip { | 78 | struct mvebu_gpio_chip { |
79 | struct gpio_chip chip; | 79 | struct gpio_chip chip; |
@@ -82,9 +82,9 @@ struct mvebu_gpio_chip { | |||
82 | void __iomem *percpu_membase; | 82 | void __iomem *percpu_membase; |
83 | int irqbase; | 83 | int irqbase; |
84 | struct irq_domain *domain; | 84 | struct irq_domain *domain; |
85 | int soc_variant; | 85 | int soc_variant; |
86 | 86 | ||
87 | /* Used to preserve GPIO registers accross suspend/resume */ | 87 | /* Used to preserve GPIO registers across suspend/resume */ |
88 | u32 out_reg; | 88 | u32 out_reg; |
89 | u32 io_conf_reg; | 89 | u32 io_conf_reg; |
90 | u32 blink_en_reg; | 90 | u32 blink_en_reg; |
@@ -107,7 +107,8 @@ static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) | |||
107 | return mvchip->membase + GPIO_BLINK_EN_OFF; | 107 | return mvchip->membase + GPIO_BLINK_EN_OFF; |
108 | } | 108 | } |
109 | 109 | ||
110 | static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) | 110 | static inline void __iomem * |
111 | mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) | ||
111 | { | 112 | { |
112 | return mvchip->membase + GPIO_IO_CONF_OFF; | 113 | return mvchip->membase + GPIO_IO_CONF_OFF; |
113 | } | 114 | } |
@@ -117,12 +118,14 @@ static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) | |||
117 | return mvchip->membase + GPIO_IN_POL_OFF; | 118 | return mvchip->membase + GPIO_IN_POL_OFF; |
118 | } | 119 | } |
119 | 120 | ||
120 | static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) | 121 | static inline void __iomem * |
122 | mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) | ||
121 | { | 123 | { |
122 | return mvchip->membase + GPIO_DATA_IN_OFF; | 124 | return mvchip->membase + GPIO_DATA_IN_OFF; |
123 | } | 125 | } |
124 | 126 | ||
125 | static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) | 127 | static inline void __iomem * |
128 | mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) | ||
126 | { | 129 | { |
127 | int cpu; | 130 | int cpu; |
128 | 131 | ||
@@ -132,13 +135,15 @@ static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvc | |||
132 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; | 135 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; |
133 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | 136 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: |
134 | cpu = smp_processor_id(); | 137 | cpu = smp_processor_id(); |
135 | return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu); | 138 | return mvchip->percpu_membase + |
139 | GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu); | ||
136 | default: | 140 | default: |
137 | BUG(); | 141 | BUG(); |
138 | } | 142 | } |
139 | } | 143 | } |
140 | 144 | ||
141 | static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) | 145 | static inline void __iomem * |
146 | mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) | ||
142 | { | 147 | { |
143 | int cpu; | 148 | int cpu; |
144 | 149 | ||
@@ -150,7 +155,8 @@ static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvch | |||
150 | return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu); | 155 | return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu); |
151 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | 156 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: |
152 | cpu = smp_processor_id(); | 157 | cpu = smp_processor_id(); |
153 | return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu); | 158 | return mvchip->percpu_membase + |
159 | GPIO_EDGE_MASK_ARMADAXP_OFF(cpu); | ||
154 | default: | 160 | default: |
155 | BUG(); | 161 | BUG(); |
156 | } | 162 | } |
@@ -168,7 +174,8 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | |||
168 | return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu); | 174 | return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu); |
169 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | 175 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: |
170 | cpu = smp_processor_id(); | 176 | cpu = smp_processor_id(); |
171 | return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu); | 177 | return mvchip->percpu_membase + |
178 | GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu); | ||
172 | default: | 179 | default: |
173 | BUG(); | 180 | BUG(); |
174 | } | 181 | } |
@@ -364,22 +371,22 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) | |||
364 | * value of the line or the opposite value. | 371 | * value of the line or the opposite value. |
365 | * | 372 | * |
366 | * Level IRQ handlers: DATA_IN is used directly as cause register. | 373 | * Level IRQ handlers: DATA_IN is used directly as cause register. |
367 | * Interrupt are masked by LEVEL_MASK registers. | 374 | * Interrupt are masked by LEVEL_MASK registers. |
368 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. | 375 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. |
369 | * Interrupt are masked by EDGE_MASK registers. | 376 | * Interrupt are masked by EDGE_MASK registers. |
370 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps | 377 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps |
371 | * the polarity to catch the next line transaction. | 378 | * the polarity to catch the next line transaction. |
372 | * This is a race condition that might not perfectly | 379 | * This is a race condition that might not perfectly |
373 | * work on some use cases. | 380 | * work on some use cases. |
374 | * | 381 | * |
375 | * Every eight GPIO lines are grouped (OR'ed) before going up to main | 382 | * Every eight GPIO lines are grouped (OR'ed) before going up to main |
376 | * cause register. | 383 | * cause register. |
377 | * | 384 | * |
378 | * EDGE cause mask | 385 | * EDGE cause mask |
379 | * data-in /--------| |-----| |----\ | 386 | * data-in /--------| |-----| |----\ |
380 | * -----| |----- ---- to main cause reg | 387 | * -----| |----- ---- to main cause reg |
381 | * X \----------------| |----/ | 388 | * X \----------------| |----/ |
382 | * polarity LEVEL mask | 389 | * polarity LEVEL mask |
383 | * | 390 | * |
384 | ****************************************************************************/ | 391 | ****************************************************************************/ |
385 | 392 | ||
@@ -394,9 +401,8 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
394 | pin = d->hwirq; | 401 | pin = d->hwirq; |
395 | 402 | ||
396 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin); | 403 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin); |
397 | if (!u) { | 404 | if (!u) |
398 | return -EINVAL; | 405 | return -EINVAL; |
399 | } | ||
400 | 406 | ||
401 | type &= IRQ_TYPE_SENSE_MASK; | 407 | type &= IRQ_TYPE_SENSE_MASK; |
402 | if (type == IRQ_TYPE_NONE) | 408 | if (type == IRQ_TYPE_NONE) |
@@ -529,13 +535,13 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
529 | (data_in ^ in_pol) & msk ? "hi" : "lo", | 535 | (data_in ^ in_pol) & msk ? "hi" : "lo", |
530 | in_pol & msk ? "lo" : "hi"); | 536 | in_pol & msk ? "lo" : "hi"); |
531 | if (!((edg_msk | lvl_msk) & msk)) { | 537 | if (!((edg_msk | lvl_msk) & msk)) { |
532 | seq_printf(s, " disabled\n"); | 538 | seq_puts(s, " disabled\n"); |
533 | continue; | 539 | continue; |
534 | } | 540 | } |
535 | if (edg_msk & msk) | 541 | if (edg_msk & msk) |
536 | seq_printf(s, " edge "); | 542 | seq_puts(s, " edge "); |
537 | if (lvl_msk & msk) | 543 | if (lvl_msk & msk) |
538 | seq_printf(s, " level"); | 544 | seq_puts(s, " level"); |
539 | seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); | 545 | seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); |
540 | } | 546 | } |
541 | } | 547 | } |
@@ -546,15 +552,15 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
546 | static const struct of_device_id mvebu_gpio_of_match[] = { | 552 | static const struct of_device_id mvebu_gpio_of_match[] = { |
547 | { | 553 | { |
548 | .compatible = "marvell,orion-gpio", | 554 | .compatible = "marvell,orion-gpio", |
549 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, | 555 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, |
550 | }, | 556 | }, |
551 | { | 557 | { |
552 | .compatible = "marvell,mv78200-gpio", | 558 | .compatible = "marvell,mv78200-gpio", |
553 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200, | 559 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200, |
554 | }, | 560 | }, |
555 | { | 561 | { |
556 | .compatible = "marvell,armadaxp-gpio", | 562 | .compatible = "marvell,armadaxp-gpio", |
557 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, | 563 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, |
558 | }, | 564 | }, |
559 | { | 565 | { |
560 | /* sentinel */ | 566 | /* sentinel */ |
@@ -661,6 +667,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
661 | unsigned int ngpios; | 667 | unsigned int ngpios; |
662 | int soc_variant; | 668 | int soc_variant; |
663 | int i, cpu, id; | 669 | int i, cpu, id; |
670 | int err; | ||
664 | 671 | ||
665 | match = of_match_device(mvebu_gpio_of_match, &pdev->dev); | 672 | match = of_match_device(mvebu_gpio_of_match, &pdev->dev); |
666 | if (match) | 673 | if (match) |
@@ -668,7 +675,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
668 | else | 675 | else |
669 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; | 676 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; |
670 | 677 | ||
671 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); | 678 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), |
679 | GFP_KERNEL); | ||
672 | if (!mvchip) | 680 | if (!mvchip) |
673 | return -ENOMEM; | 681 | return -ENOMEM; |
674 | 682 | ||
@@ -767,8 +775,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
767 | * interrupt handlers, with each handler dealing with 8 GPIO | 775 | * interrupt handlers, with each handler dealing with 8 GPIO |
768 | * pins. */ | 776 | * pins. */ |
769 | for (i = 0; i < 4; i++) { | 777 | for (i = 0; i < 4; i++) { |
770 | int irq; | 778 | int irq = platform_get_irq(pdev, i); |
771 | irq = platform_get_irq(pdev, i); | 779 | |
772 | if (irq < 0) | 780 | if (irq < 0) |
773 | continue; | 781 | continue; |
774 | irq_set_handler_data(irq, mvchip); | 782 | irq_set_handler_data(irq, mvchip); |
@@ -778,14 +786,16 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
778 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); | 786 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); |
779 | if (mvchip->irqbase < 0) { | 787 | if (mvchip->irqbase < 0) { |
780 | dev_err(&pdev->dev, "no irqs\n"); | 788 | dev_err(&pdev->dev, "no irqs\n"); |
781 | return mvchip->irqbase; | 789 | err = mvchip->irqbase; |
790 | goto err_gpiochip_add; | ||
782 | } | 791 | } |
783 | 792 | ||
784 | gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, | 793 | gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, |
785 | mvchip->membase, handle_level_irq); | 794 | mvchip->membase, handle_level_irq); |
786 | if (!gc) { | 795 | if (!gc) { |
787 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); | 796 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); |
788 | return -ENOMEM; | 797 | err = -ENOMEM; |
798 | goto err_gpiochip_add; | ||
789 | } | 799 | } |
790 | 800 | ||
791 | gc->private = mvchip; | 801 | gc->private = mvchip; |
@@ -816,18 +826,26 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
816 | if (!mvchip->domain) { | 826 | if (!mvchip->domain) { |
817 | dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", | 827 | dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", |
818 | mvchip->chip.label); | 828 | mvchip->chip.label); |
819 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | 829 | err = -ENODEV; |
820 | IRQ_LEVEL | IRQ_NOPROBE); | 830 | goto err_generic_chip; |
821 | kfree(gc); | ||
822 | return -ENODEV; | ||
823 | } | 831 | } |
824 | 832 | ||
825 | return 0; | 833 | return 0; |
834 | |||
835 | err_generic_chip: | ||
836 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | ||
837 | IRQ_LEVEL | IRQ_NOPROBE); | ||
838 | kfree(gc); | ||
839 | |||
840 | err_gpiochip_add: | ||
841 | gpiochip_remove(&mvchip->chip); | ||
842 | |||
843 | return err; | ||
826 | } | 844 | } |
827 | 845 | ||
828 | static struct platform_driver mvebu_gpio_driver = { | 846 | static struct platform_driver mvebu_gpio_driver = { |
829 | .driver = { | 847 | .driver = { |
830 | .name = "mvebu-gpio", | 848 | .name = "mvebu-gpio", |
831 | .of_match_table = mvebu_gpio_of_match, | 849 | .of_match_table = mvebu_gpio_of_match, |
832 | }, | 850 | }, |
833 | .probe = mvebu_gpio_probe, | 851 | .probe = mvebu_gpio_probe, |