71 lines
2.6 KiB
Diff
71 lines
2.6 KiB
Diff
|
From 23305d0eaad752788bae70db64f933febcbced82 Mon Sep 17 00:00:00 2001
|
||
|
From: Gabriel Krisman Bertazi <krisman@collabora.com>
|
||
|
Date: Wed, 5 May 2021 22:12:17 -0400
|
||
|
Subject: [PATCH 20/21] pinctrl-amd: Add quirk to timeout irq pin
|
||
|
reconfiguration
|
||
|
|
||
|
Since commit 37b635b47124 ("Add support for AMD SPI controller-1 (v2)"),
|
||
|
which enabled the SPI bus on jupiter, the probe of cs35l41 hangs the
|
||
|
entire kernel, because pinctrl-amd spins forever when attempting to
|
||
|
reconfigure the cs35l41 irq pin with interrupts disabled and holding the
|
||
|
spinlock of the irq controller. The infinite loop happens because of a
|
||
|
board design issue (according to AMD), that tries to use a pin that
|
||
|
can't even trigger the interruption that would otherwise signal the
|
||
|
reconfiguratiion completion.
|
||
|
|
||
|
This patch detects the condition and aborts the reconfiguration when the
|
||
|
problem occurs, failing the probe of the device, but allowing the kernel
|
||
|
to recover.
|
||
|
|
||
|
With this patch, it should be safe to reenable CONFIG_SPI_AMD.
|
||
|
|
||
|
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
|
||
|
[Fwd-ported to v6.5]
|
||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||
|
---
|
||
|
drivers/pinctrl/pinctrl-amd.c | 11 +++++++++--
|
||
|
1 file changed, 9 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
|
||
|
index 49f89b70dcec..16d544bb0626 100644
|
||
|
--- a/drivers/pinctrl/pinctrl-amd.c
|
||
|
+++ b/drivers/pinctrl/pinctrl-amd.c
|
||
|
@@ -31,6 +31,7 @@
|
||
|
#include <linux/pinctrl/pinconf-generic.h>
|
||
|
#include <linux/pinctrl/pinmux.h>
|
||
|
#include <linux/suspend.h>
|
||
|
+#include <linux/delay.h>
|
||
|
|
||
|
#include "core.h"
|
||
|
#include "pinctrl-utils.h"
|
||
|
@@ -484,6 +485,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||
|
unsigned long flags;
|
||
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||
|
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
|
||
|
+ int timeout = 100;
|
||
|
|
||
|
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
|
||
|
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
|
||
|
@@ -553,11 +555,16 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||
|
pin_reg_irq_en |= mask;
|
||
|
pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
|
||
|
writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
|
||
|
- while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
|
||
|
- continue;
|
||
|
+ while (((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask) && timeout--)
|
||
|
+ udelay(100);
|
||
|
+
|
||
|
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
|
||
|
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
|
||
|
|
||
|
+ if (timeout <= 0)
|
||
|
+ printk("%s: applying Cirrus quirk after timeout when setting irq pin\n",
|
||
|
+ __func__);
|
||
|
+
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.44.0
|
||
|
|