Pin control fixes for the v6.1 series:
- 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. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmOKZB4ACgkQQRCzN7AZ XXMsnw/+PSijwUPsikfZYtgp2BTxMb/xr0XKmggqheNzEs1e0xYHBTJO9nLuUCxG v0zfpTMgwhx9/988Y39/fRih/DEKB5s/CMV7Ic5DQCmPo9NC5apeWvW80aQPbEun jwEEmjIUHHx9nX9z4B9CSICZA7XUiTb9vbHIG2KJCX7L3atzkOMmTYNi62qLQ6CU fo6JYZm1V3zdqLX3dD8HlDdVfzyywvG9MAhFlRgxPk/s2E8BMQdRL93rejPYKvWh fFH6aQrJMgEymzgRq+vfI62XRKK0ebE6A4084BMHSxflh+LNpjFwZfaNTotaqPHY uVVmPOGH2wjLHRFit0mp+6xWL9sGjggawJ4Y56gYpsUnNN+aKhkpjdvm9UFscnql 6MZFx6hKbx91czhSD0M5nSWTR7AQwP3YLgOPZnGS0bt7WvuX306eh1CxYcbHlBFq KM4u7B36Q89b0Ac2+CjyXo4rUdXyeMRY6kDFuVaqVGyU1SEIWaqP9wwGDDY5ZXWx Kqc+mP5Zr6TzUbx4Amry/EswynT5zeqr6N8DFWcDZW2VJwiDqPs7g3ZIVxqpv719 OOFzwNGtCkrjYs2SH9o697gC5xPofw2OgIFUeYMFNoCNjmjhegym6qrVAT45IOV1 SYYoRKEFFdof9DbhJrWUmOBkMqtuPhycZClbHpRHoI/309Cq7eo= =bP9I -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
63050a5ca1
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue