Commit 70f8915e authored by Michal Piekos's avatar Michal Piekos Committed by Linus Walleij
Browse files

pinctrl: sunxi: fix gpiochip_lock_as_irq() failure when pinmux is unknown



Fixes kernel hang during boot due to inability to set up IRQ on AXP313a.

The issue is caused by gpiochip_lock_as_irq() which is failing when gpio
is in uninitialized state.

Solution is to set pinmux to GPIO INPUT in
sunxi_pinctrl_irq_request_resources() if it wasn't initialized
earlier.

Tested on Orange Pi Zero 3.

Fixes: 01e10d02 ("pinctrl: sunxi: Implement gpiochip::get_direction()")
Reviewed-by: default avatarAndre Przywara <andre.przywara@arm.com>
Reviewed-by: default avatarChen-Yu Tsai <wens@kernel.org>
Signed-off-by: default avatarMichal Piekos <michal.piekos@mmpsystems.pl>
Signed-off-by: default avatarLinus Walleij <linusw@kernel.org>
parent 42e06688
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -1092,6 +1092,9 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
{
	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
	struct sunxi_desc_function *func;
	unsigned int offset;
	u32 reg, shift, mask;
	u8 disabled_mux, muxval;
	int ret;

	func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -1099,8 +1102,21 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
	if (!func)
		return -EINVAL;

	ret = gpiochip_lock_as_irq(pctl->chip,
			pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
	offset = pctl->irq_array[d->hwirq] - pctl->desc->pin_base;
	sunxi_mux_reg(pctl, offset, &reg, &shift, &mask);
	muxval = (readl(pctl->membase + reg) & mask) >> shift;

	/* Change muxing to GPIO INPUT mode if at reset value */
	if (pctl->flags & SUNXI_PINCTRL_NEW_REG_LAYOUT)
		disabled_mux = SUN4I_FUNC_DISABLED_NEW;
	else
		disabled_mux = SUN4I_FUNC_DISABLED_OLD;

	if (muxval == disabled_mux)
		sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq],
			      SUN4I_FUNC_INPUT);

	ret = gpiochip_lock_as_irq(pctl->chip, offset);
	if (ret) {
		dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
			irqd_to_hwirq(d));
+2 −0
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@

#define SUN4I_FUNC_INPUT	0
#define SUN4I_FUNC_IRQ		6
#define SUN4I_FUNC_DISABLED_OLD 7
#define SUN4I_FUNC_DISABLED_NEW 15

#define SUNXI_PINCTRL_VARIANT_MASK	GENMASK(7, 0)
#define SUNXI_PINCTRL_NEW_REG_LAYOUT	BIT(8)