Skip to content

Commit e986f0e

Browse files
semihalf-bartosik-lukaszandy-shev
authored andcommitted
pinctrl: intel: fix unexpected interrupt
ASUS Chromebook C223 with Celeron N3350 crashes sometimes during cold booot. Inspection of the kernel log showed that it gets into an inifite loop logging the following message: ->handle_irq(): 000000009cdb51e8, handle_bad_irq+0x0/0x251 ->irq_data.chip(): 000000005ec212a7, 0xffffa043009d8e7 ->action(): 00000 IRQ_NOPROBE set unexpected IRQ trap at vector 7c The issue happens during cold boot but only if cold boot happens at most several dozen seconds after Chromebook is powered off. For longer intervals between power off and power on (cold boot) the issue does not reproduce. The unexpected interrupt is sourced from INT3452 GPIO pin which is used for SD card detect. Investigation relevealed that when the interval between power off and power on (cold boot) is less than several dozen seconds then values of INT3452 GPIO interrupt enable and interrupt pending registers survive power off and power on sequence and interrupt for SD card detect pin is enabled and pending during probe of SD controller which causes the unexpected IRQ message. "Intel Pentium and Celeron Processor N- and J- Series" volume 3 doc mentions that GPIO interrupt enable and status registers default value is 0x0. The fix clears INT3452 GPIO interrupt enabled and interrupt pending registers in its probe function. Fixes: 7981c00 ("pinctrl: intel: Add Intel Sunrisepoint pin controller and GPIO support") Signed-off-by: Łukasz Bartosik <lb@semihalf.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
1 parent 7731123 commit e986f0e

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

drivers/pinctrl/intel/pinctrl-intel.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,39 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
12161216
return IRQ_RETVAL(ret);
12171217
}
12181218

1219+
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
1220+
{
1221+
int i;
1222+
1223+
for (i = 0; i < pctrl->ncommunities; i++) {
1224+
const struct intel_community *community;
1225+
void __iomem *base;
1226+
unsigned int gpp;
1227+
1228+
community = &pctrl->communities[i];
1229+
base = community->regs;
1230+
1231+
for (gpp = 0; gpp < community->ngpps; gpp++) {
1232+
/* Mask and clear all interrupts */
1233+
writel(0, base + community->ie_offset + gpp * 4);
1234+
writel(0xffff, base + community->is_offset + gpp * 4);
1235+
}
1236+
}
1237+
}
1238+
1239+
static int intel_gpio_irq_init_hw(struct gpio_chip *gc)
1240+
{
1241+
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
1242+
1243+
/*
1244+
* Make sure the interrupt lines are in a proper state before
1245+
* further configuration.
1246+
*/
1247+
intel_gpio_irq_init(pctrl);
1248+
1249+
return 0;
1250+
}
1251+
12191252
static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
12201253
const struct intel_community *community)
12211254
{
@@ -1320,6 +1353,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
13201353
girq->num_parents = 0;
13211354
girq->default_type = IRQ_TYPE_NONE;
13221355
girq->handler = handle_bad_irq;
1356+
girq->init_hw = intel_gpio_irq_init_hw;
13231357

13241358
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
13251359
if (ret) {
@@ -1695,26 +1729,6 @@ int intel_pinctrl_suspend_noirq(struct device *dev)
16951729
}
16961730
EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq);
16971731

1698-
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
1699-
{
1700-
size_t i;
1701-
1702-
for (i = 0; i < pctrl->ncommunities; i++) {
1703-
const struct intel_community *community;
1704-
void __iomem *base;
1705-
unsigned int gpp;
1706-
1707-
community = &pctrl->communities[i];
1708-
base = community->regs;
1709-
1710-
for (gpp = 0; gpp < community->ngpps; gpp++) {
1711-
/* Mask and clear all interrupts */
1712-
writel(0, base + community->ie_offset + gpp * 4);
1713-
writel(0xffff, base + community->is_offset + gpp * 4);
1714-
}
1715-
}
1716-
}
1717-
17181732
static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value)
17191733
{
17201734
u32 curr, updated;

0 commit comments

Comments
 (0)