Commit 63050a5c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:
 "Three driver fixes. The Intel fix looks like the most important.

   - Fix a potential divide by zero in pinctrl-singe (OMAP and
     HiSilicon)

   - Disable IRQs on startup in the Mediatek driver. This is a classic,
     we should be looking out for this more.

   - Save and restore pins in 'direct IRQ' mode in the Intel driver,
     this works around firmware bugs"

* tag 'pinctrl-v6.1-5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: intel: Save and restore pins in "direct IRQ" mode
  pinctrl: meditatek: Startup with the IRQs disabled
  pinctrl: single: Fix potential division by zero
parents 0e15c3c7 6989ea48
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
	writel(value, padcfg0);
}

static int __intel_gpio_get_gpio_mode(u32 value)
{
	return (value & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
}

static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
{
	return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
	return __intel_gpio_get_gpio_mode(readl(padcfg0));
}

static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
@@ -1674,6 +1679,7 @@ EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data);
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
{
	const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
	u32 value;

	if (!pd || !intel_pad_usable(pctrl, pin))
		return false;
@@ -1688,6 +1694,25 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int
	    gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
		return true;

	/*
	 * The firmware on some systems may configure GPIO pins to be
	 * an interrupt source in so called "direct IRQ" mode. In such
	 * cases the GPIO controller driver has no idea if those pins
	 * are being used or not. At the same time, there is a known bug
	 * in the firmwares that don't restore the pin settings correctly
	 * after suspend, i.e. by an unknown reason the Rx value becomes
	 * inverted.
	 *
	 * Hence, let's save and restore the pins that are configured
	 * as GPIOs in the input mode with GPIROUTIOXAPIC bit set.
	 *
	 * See https://bugzilla.kernel.org/show_bug.cgi?id=214749.
	 */
	value = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
	if ((value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
	    (__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO))
		return true;

	return false;
}

+6 −3
Original line number Diff line number Diff line
@@ -303,12 +303,15 @@ static struct irq_chip mtk_eint_irq_chip = {

static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
{
	void __iomem *reg = eint->base + eint->regs->dom_en;
	void __iomem *dom_en = eint->base + eint->regs->dom_en;
	void __iomem *mask_set = eint->base + eint->regs->mask_set;
	unsigned int i;

	for (i = 0; i < eint->hw->ap_num; i += 32) {
		writel(0xffffffff, reg);
		reg += 4;
		writel(0xffffffff, dom_en);
		writel(0xffffffff, mask_set);
		dom_en += 4;
		mask_set += 4;
	}

	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -727,7 +727,7 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)

	mux_bytes = pcs->width / BITS_PER_BYTE;

	if (pcs->bits_per_mux) {
	if (pcs->bits_per_mux && pcs->fmask) {
		pcs->bits_per_pin = fls(pcs->fmask);
		nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
	} else {