summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sunxi
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2016-03-12 13:44:57 -0500
committerLinus Walleij <linus.walleij@linaro.org>2016-03-30 04:57:52 -0400
commit5e7515ba78fff2f5407eaa2f97c1d5c07801ac3d (patch)
tree4782fca73c49328bf1de288206ef4cc4432fd2ec /drivers/pinctrl/sunxi
parente9adb336d0bf391be23e820975ca5cd12c31d781 (diff)
pinctrl: sunxi: Fix A33 external interrupts not working
pinctrl-sun8i-a33.c (and the dts) declare only 2 interrupt banks, where as the closely related a23 has 3 banks. This matches with the datasheet for the A33 where only interrupt banks B and G are specified where as the A23 has banks A, B and G. However the A33 being the A23 derative it is means that the interrupt configure/status io-addresses for the 2 banks it has are not changed from the A23, iow they have the same address as if bank A was still present. Where as the sunxi pinctrl currently tries to use the A23 bank A addresses for bank B, since the pinctrl code does not know about the removed bank A. Add a irq_bank_base parameter and use this where appropriate to take the missing bank A into account. This fixes external interrupts not working on the A33 (tested with an i2c touchscreen controller which uses an external interrupt). Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/sunxi')
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c17
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.h21
3 files changed, 22 insertions, 17 deletions
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
index 00265f0435a7..8b381d69df86 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
@@ -485,6 +485,7 @@ static const struct sunxi_pinctrl_desc sun8i_a33_pinctrl_data = {
485 .pins = sun8i_a33_pins, 485 .pins = sun8i_a33_pins,
486 .npins = ARRAY_SIZE(sun8i_a33_pins), 486 .npins = ARRAY_SIZE(sun8i_a33_pins),
487 .irq_banks = 2, 487 .irq_banks = 2,
488 .irq_bank_base = 1,
488}; 489};
489 490
490static int sun8i_a33_pinctrl_probe(struct platform_device *pdev) 491static int sun8i_a33_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 12a1dfabb1af..3b017dbd289c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -579,7 +579,7 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
579static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type) 579static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
580{ 580{
581 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 581 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
582 u32 reg = sunxi_irq_cfg_reg(d->hwirq); 582 u32 reg = sunxi_irq_cfg_reg(d->hwirq, pctl->desc->irq_bank_base);
583 u8 index = sunxi_irq_cfg_offset(d->hwirq); 583 u8 index = sunxi_irq_cfg_offset(d->hwirq);
584 unsigned long flags; 584 unsigned long flags;
585 u32 regval; 585 u32 regval;
@@ -626,7 +626,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
626static void sunxi_pinctrl_irq_ack(struct irq_data *d) 626static void sunxi_pinctrl_irq_ack(struct irq_data *d)
627{ 627{
628 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 628 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
629 u32 status_reg = sunxi_irq_status_reg(d->hwirq); 629 u32 status_reg = sunxi_irq_status_reg(d->hwirq,
630 pctl->desc->irq_bank_base);
630 u8 status_idx = sunxi_irq_status_offset(d->hwirq); 631 u8 status_idx = sunxi_irq_status_offset(d->hwirq);
631 632
632 /* Clear the IRQ */ 633 /* Clear the IRQ */
@@ -636,7 +637,7 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d)
636static void sunxi_pinctrl_irq_mask(struct irq_data *d) 637static void sunxi_pinctrl_irq_mask(struct irq_data *d)
637{ 638{
638 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 639 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
639 u32 reg = sunxi_irq_ctrl_reg(d->hwirq); 640 u32 reg = sunxi_irq_ctrl_reg(d->hwirq, pctl->desc->irq_bank_base);
640 u8 idx = sunxi_irq_ctrl_offset(d->hwirq); 641 u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
641 unsigned long flags; 642 unsigned long flags;
642 u32 val; 643 u32 val;
@@ -653,7 +654,7 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
653static void sunxi_pinctrl_irq_unmask(struct irq_data *d) 654static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
654{ 655{
655 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 656 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
656 u32 reg = sunxi_irq_ctrl_reg(d->hwirq); 657 u32 reg = sunxi_irq_ctrl_reg(d->hwirq, pctl->desc->irq_bank_base);
657 u8 idx = sunxi_irq_ctrl_offset(d->hwirq); 658 u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
658 unsigned long flags; 659 unsigned long flags;
659 u32 val; 660 u32 val;
@@ -745,7 +746,7 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
745 if (bank == pctl->desc->irq_banks) 746 if (bank == pctl->desc->irq_banks)
746 return; 747 return;
747 748
748 reg = sunxi_irq_status_reg_from_bank(bank); 749 reg = sunxi_irq_status_reg_from_bank(bank, pctl->desc->irq_bank_base);
749 val = readl(pctl->membase + reg); 750 val = readl(pctl->membase + reg);
750 751
751 if (val) { 752 if (val) {
@@ -1024,9 +1025,11 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
1024 1025
1025 for (i = 0; i < pctl->desc->irq_banks; i++) { 1026 for (i = 0; i < pctl->desc->irq_banks; i++) {
1026 /* Mask and clear all IRQs before registering a handler */ 1027 /* Mask and clear all IRQs before registering a handler */
1027 writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i)); 1028 writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i,
1029 pctl->desc->irq_bank_base));
1028 writel(0xffffffff, 1030 writel(0xffffffff,
1029 pctl->membase + sunxi_irq_status_reg_from_bank(i)); 1031 pctl->membase + sunxi_irq_status_reg_from_bank(i,
1032 pctl->desc->irq_bank_base));
1030 1033
1031 irq_set_chained_handler_and_data(pctl->irq[i], 1034 irq_set_chained_handler_and_data(pctl->irq[i],
1032 sunxi_pinctrl_irq_handler, 1035 sunxi_pinctrl_irq_handler,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index e248e81a0f9e..0afce1ab12d0 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -97,6 +97,7 @@ struct sunxi_pinctrl_desc {
97 int npins; 97 int npins;
98 unsigned pin_base; 98 unsigned pin_base;
99 unsigned irq_banks; 99 unsigned irq_banks;
100 unsigned irq_bank_base;
100 bool irq_read_needs_mux; 101 bool irq_read_needs_mux;
101}; 102};
102 103
@@ -233,12 +234,12 @@ static inline u32 sunxi_pull_offset(u16 pin)
233 return pin_num * PULL_PINS_BITS; 234 return pin_num * PULL_PINS_BITS;
234} 235}
235 236
236static inline u32 sunxi_irq_cfg_reg(u16 irq) 237static inline u32 sunxi_irq_cfg_reg(u16 irq, unsigned bank_base)
237{ 238{
238 u8 bank = irq / IRQ_PER_BANK; 239 u8 bank = irq / IRQ_PER_BANK;
239 u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04; 240 u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04;
240 241
241 return IRQ_CFG_REG + bank * IRQ_MEM_SIZE + reg; 242 return IRQ_CFG_REG + (bank_base + bank) * IRQ_MEM_SIZE + reg;
242} 243}
243 244
244static inline u32 sunxi_irq_cfg_offset(u16 irq) 245static inline u32 sunxi_irq_cfg_offset(u16 irq)
@@ -247,16 +248,16 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
247 return irq_num * IRQ_CFG_IRQ_BITS; 248 return irq_num * IRQ_CFG_IRQ_BITS;
248} 249}
249 250
250static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank) 251static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank, unsigned bank_base)
251{ 252{
252 return IRQ_CTRL_REG + bank * IRQ_MEM_SIZE; 253 return IRQ_CTRL_REG + (bank_base + bank) * IRQ_MEM_SIZE;
253} 254}
254 255
255static inline u32 sunxi_irq_ctrl_reg(u16 irq) 256static inline u32 sunxi_irq_ctrl_reg(u16 irq, unsigned bank_base)
256{ 257{
257 u8 bank = irq / IRQ_PER_BANK; 258 u8 bank = irq / IRQ_PER_BANK;
258 259
259 return sunxi_irq_ctrl_reg_from_bank(bank); 260 return sunxi_irq_ctrl_reg_from_bank(bank, bank_base);
260} 261}
261 262
262static inline u32 sunxi_irq_ctrl_offset(u16 irq) 263static inline u32 sunxi_irq_ctrl_offset(u16 irq)
@@ -265,16 +266,16 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
265 return irq_num * IRQ_CTRL_IRQ_BITS; 266 return irq_num * IRQ_CTRL_IRQ_BITS;
266} 267}
267 268
268static inline u32 sunxi_irq_status_reg_from_bank(u8 bank) 269static inline u32 sunxi_irq_status_reg_from_bank(u8 bank, unsigned bank_base)
269{ 270{
270 return IRQ_STATUS_REG + bank * IRQ_MEM_SIZE; 271 return IRQ_STATUS_REG + (bank_base + bank) * IRQ_MEM_SIZE;
271} 272}
272 273
273static inline u32 sunxi_irq_status_reg(u16 irq) 274static inline u32 sunxi_irq_status_reg(u16 irq, unsigned bank_base)
274{ 275{
275 u8 bank = irq / IRQ_PER_BANK; 276 u8 bank = irq / IRQ_PER_BANK;
276 277
277 return sunxi_irq_status_reg_from_bank(bank); 278 return sunxi_irq_status_reg_from_bank(bank, bank_base);
278} 279}
279 280
280static inline u32 sunxi_irq_status_offset(u16 irq) 281static inline u32 sunxi_irq_status_offset(u16 irq)