Commit 63050a5c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-v6.1-5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

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
...@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input) ...@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
writel(value, padcfg0); 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) 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) static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
...@@ -1674,6 +1679,7 @@ EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data); ...@@ -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) static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
{ {
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin); const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
u32 value;
if (!pd || !intel_pad_usable(pctrl, pin)) if (!pd || !intel_pad_usable(pctrl, pin))
return false; return false;
...@@ -1688,6 +1694,25 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int ...@@ -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))) gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
return true; 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; return false;
} }
......
...@@ -303,12 +303,15 @@ static struct irq_chip mtk_eint_irq_chip = { ...@@ -303,12 +303,15 @@ static struct irq_chip mtk_eint_irq_chip = {
static unsigned int mtk_eint_hw_init(struct mtk_eint *eint) 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; unsigned int i;
for (i = 0; i < eint->hw->ap_num; i += 32) { for (i = 0; i < eint->hw->ap_num; i += 32) {
writel(0xffffffff, reg); writel(0xffffffff, dom_en);
reg += 4; writel(0xffffffff, mask_set);
dom_en += 4;
mask_set += 4;
} }
return 0; return 0;
......
...@@ -727,7 +727,7 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs) ...@@ -727,7 +727,7 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
mux_bytes = pcs->width / BITS_PER_BYTE; 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); pcs->bits_per_pin = fls(pcs->fmask);
nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin; nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment