Skip to content

Commit cf9d052

Browse files
dianderslinusw
authored andcommitted
pinctrl: qcom: Don't clear pending interrupts when enabling
In Linux, if a driver does disable_irq() and later does enable_irq() on its interrupt, I believe it's expecting these properties: * If an interrupt was pending when the driver disabled then it will still be pending after the driver re-enables. * If an edge-triggered interrupt comes in while an interrupt is disabled it should assert when the interrupt is re-enabled. If you think that the above sounds a lot like the disable_irq() and enable_irq() are supposed to be masking/unmasking the interrupt instead of disabling/enabling it then you've made an astute observation. Specifically when talking about interrupts, "mask" usually means to stop posting interrupts but keep tracking them and "disable" means to fully shut off interrupt detection. It's unfortunate that this is so confusing, but presumably this is all the way it is for historical reasons. Perhaps more confusing than the above is that, even though clients of IRQs themselves don't have a way to request mask/unmask vs. disable/enable calls, IRQ chips themselves can implement both. ...and yet more confusing is that if an IRQ chip implements disable/enable then they will be called when a client driver calls disable_irq() / enable_irq(). It does feel like some of the above could be cleared up. However, without any other core interrupt changes it should be clear that when an IRQ chip gets a request to "disable" an IRQ that it has to treat it like a mask of that IRQ. In any case, after that long interlude you can see that the "unmask and clear" can break things. Maulik tried to fix it so that we no longer did "unmask and clear" in commit 71266d9 ("pinctrl: qcom: Move clearing pending IRQ to .irq_request_resources callback"), but it only handled the PDC case and it had problems (it caused sc7180-trogdor devices to fail to suspend). Let's fix. >From my understanding the source of the phantom interrupt in the were these two things: 1. One that could have been introduced in msm_gpio_irq_set_type() (only for the non-PDC case). 2. Edges could have been detected when a GPIO was muxed away. Fixing case #1 is easy. We can just add a clear in msm_gpio_irq_set_type(). Fixing case #2 is harder. Let's use a concrete example. In sc7180-trogdor.dtsi we configure the uart3 to have two pinctrl states, sleep and default, and mux between the two during runtime PM and system suspend (see geni_se_resources_{on,off}() for more details). The difference between the sleep and default state is that the RX pin is muxed to a GPIO during sleep and muxed to the UART otherwise. As per Qualcomm, when we mux the pin over to the UART function the PDC (or the non-PDC interrupt detection logic) is still watching it / latching edges. These edges don't cause interrupts because the current code masks the interrupt unless we're entering suspend. However, as soon as we enter suspend we unmask the interrupt and it's counted as a wakeup. Let's deal with the problem like this: * When we mux away, we'll mask our interrupt. This isn't necessary in the above case since the client already masked us, but it's a good idea in general. * When we mux back will clear any interrupts and unmask. Fixes: 4b7618f ("pinctrl: qcom: Add irq_enable callback for msm gpio") Fixes: 71266d9 ("pinctrl: qcom: Move clearing pending IRQ to .irq_request_resources callback") Signed-off-by: Douglas Anderson <[email protected]> Reviewed-by: Maulik Shah <[email protected]> Tested-by: Maulik Shah <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Link: https://lore.kernel.org/r/20210114191601.v7.4.I7cf3019783720feb57b958c95c2b684940264cd1@changeid Signed-off-by: Linus Walleij <[email protected]>
1 parent a95881d commit cf9d052

File tree

1 file changed

+50
-24
lines changed

1 file changed

+50
-24
lines changed

drivers/pinctrl/qcom/pinctrl-msm.c

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
5252
* detection.
5353
* @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller
54+
* @disabled_for_mux: These IRQs were disabled because we muxed away.
5455
* @soc: Reference to soc_data of platform specific data.
5556
* @regs: Base addresses for the TLMM tiles.
5657
* @phys_base: Physical base address
@@ -72,6 +73,7 @@ struct msm_pinctrl {
7273
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
7374
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
7475
DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO);
76+
DECLARE_BITMAP(disabled_for_mux, MAX_NR_GPIO);
7577

7678
const struct msm_pinctrl_soc_data *soc;
7779
void __iomem *regs[MAX_NR_TILES];
@@ -179,6 +181,10 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
179181
unsigned group)
180182
{
181183
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
184+
struct gpio_chip *gc = &pctrl->chip;
185+
unsigned int irq = irq_find_mapping(gc->irq.domain, group);
186+
struct irq_data *d = irq_get_irq_data(irq);
187+
unsigned int gpio_func = pctrl->soc->gpio_func;
182188
const struct msm_pingroup *g;
183189
unsigned long flags;
184190
u32 val, mask;
@@ -195,6 +201,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
195201
if (WARN_ON(i == g->nfuncs))
196202
return -EINVAL;
197203

204+
/*
205+
* If an GPIO interrupt is setup on this pin then we need special
206+
* handling. Specifically interrupt detection logic will still see
207+
* the pin twiddle even when we're muxed away.
208+
*
209+
* When we see a pin with an interrupt setup on it then we'll disable
210+
* (mask) interrupts on it when we mux away until we mux back. Note
211+
* that disable_irq() refcounts and interrupts are disabled as long as
212+
* at least one disable_irq() has been called.
213+
*/
214+
if (d && i != gpio_func &&
215+
!test_and_set_bit(d->hwirq, pctrl->disabled_for_mux))
216+
disable_irq(irq);
217+
198218
raw_spin_lock_irqsave(&pctrl->lock, flags);
199219

200220
val = msm_readl_ctl(pctrl, g);
@@ -204,6 +224,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
204224

205225
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
206226

227+
if (d && i == gpio_func &&
228+
test_and_clear_bit(d->hwirq, pctrl->disabled_for_mux)) {
229+
/*
230+
* Clear interrupts detected while not GPIO since we only
231+
* masked things.
232+
*/
233+
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
234+
irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
235+
else
236+
msm_ack_intr_status(pctrl, g);
237+
238+
enable_irq(irq);
239+
}
240+
207241
return 0;
208242
}
209243

@@ -781,7 +815,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
781815
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
782816
}
783817

784-
static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
818+
static void msm_gpio_irq_unmask(struct irq_data *d)
785819
{
786820
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
787821
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -799,14 +833,6 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
799833

800834
raw_spin_lock_irqsave(&pctrl->lock, flags);
801835

802-
/*
803-
* clear the interrupt status bit before unmask to avoid
804-
* any erroneous interrupts that would have got latched
805-
* when the interrupt is not in use.
806-
*/
807-
if (status_clear)
808-
msm_ack_intr_status(pctrl, g);
809-
810836
val = msm_readl_intr_cfg(pctrl, g);
811837
val |= BIT(g->intr_raw_status_bit);
812838
val |= BIT(g->intr_enable_bit);
@@ -826,7 +852,7 @@ static void msm_gpio_irq_enable(struct irq_data *d)
826852
irq_chip_enable_parent(d);
827853

828854
if (!test_bit(d->hwirq, pctrl->skip_wake_irqs))
829-
msm_gpio_irq_clear_unmask(d, true);
855+
msm_gpio_irq_unmask(d);
830856
}
831857

832858
static void msm_gpio_irq_disable(struct irq_data *d)
@@ -841,11 +867,6 @@ static void msm_gpio_irq_disable(struct irq_data *d)
841867
msm_gpio_irq_mask(d);
842868
}
843869

844-
static void msm_gpio_irq_unmask(struct irq_data *d)
845-
{
846-
msm_gpio_irq_clear_unmask(d, false);
847-
}
848-
849870
/**
850871
* msm_gpio_update_dual_edge_parent() - Prime next edge for IRQs handled by parent.
851872
* @d: The irq dta.
@@ -934,6 +955,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
934955
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
935956
const struct msm_pingroup *g;
936957
unsigned long flags;
958+
bool was_enabled;
937959
u32 val;
938960

939961
if (msm_gpio_needs_dual_edge_parent_workaround(d, type)) {
@@ -995,6 +1017,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
9951017
* could cause the INTR_STATUS to be set for EDGE interrupts.
9961018
*/
9971019
val = msm_readl_intr_cfg(pctrl, g);
1020+
was_enabled = val & BIT(g->intr_raw_status_bit);
9981021
val |= BIT(g->intr_raw_status_bit);
9991022
if (g->intr_detection_width == 2) {
10001023
val &= ~(3 << g->intr_detection_bit);
@@ -1044,6 +1067,14 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
10441067
}
10451068
msm_writel_intr_cfg(val, pctrl, g);
10461069

1070+
/*
1071+
* The first time we set RAW_STATUS_EN it could trigger an interrupt.
1072+
* Clear the interrupt. This is safe because we have
1073+
* IRQCHIP_SET_TYPE_MASKED.
1074+
*/
1075+
if (!was_enabled)
1076+
msm_ack_intr_status(pctrl, g);
1077+
10471078
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
10481079
msm_gpio_update_dual_edge_pos(pctrl, g, d);
10491080

@@ -1097,16 +1128,11 @@ static int msm_gpio_irq_reqres(struct irq_data *d)
10971128
}
10981129

10991130
/*
1100-
* Clear the interrupt that may be pending before we enable
1101-
* the line.
1102-
* This is especially a problem with the GPIOs routed to the
1103-
* PDC. These GPIOs are direct-connect interrupts to the GIC.
1104-
* Disabling the interrupt line at the PDC does not prevent
1105-
* the interrupt from being latched at the GIC. The state at
1106-
* GIC needs to be cleared before enabling.
1131+
* The disable / clear-enable workaround we do in msm_pinmux_set_mux()
1132+
* only works if disable is not lazy since we only clear any bogus
1133+
* interrupt in hardware. Explicitly mark the interrupt as UNLAZY.
11071134
*/
1108-
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
1109-
irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
1135+
irq_set_status_flags(d->irq, IRQ_DISABLE_UNLAZY);
11101136

11111137
return 0;
11121138
out:

0 commit comments

Comments
 (0)