diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-10 18:26:40 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-10 18:26:40 +0300 |
| commit | 77c3c619d2af2540b15e63dca768c0d86be746c9 (patch) | |
| tree | 0697b90ea3652206ab89c71ae59eae15727065f2 /drivers | |
| parent | 9a9c8ce300cd3859cc87b408ef552cd697cc2ab7 (diff) | |
| parent | db5b8cecbdf479ad13156af750377e5b43853fab (diff) | |
| download | linux-77c3c619d2af2540b15e63dca768c0d86be746c9.tar.xz | |
Merge tag 'pinctrl-v7.0-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control fixes from Linus Walleij:
"Some late pin control fixes. I'm not happy to have bugs so late in the
kernel cycle, but they are all driver specifics so I guess it's how it
is.
- Three fixes for the Intel pin control driver fixing the feature set
for the new silicon
- One fix for an IRQ storm in the MCP23S08 pin controller/GPIO
expander"
* tag 'pinctrl-v7.0-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
pinctrl: mcp23s08: Disable all pin interrupts during probe
pinctrl: intel: Enable 3-bit PAD_OWN feature
pinctrl: intel: Fix the revision for new features (1kOhm PD, HW debouncer)
pinctrl: intel: Improve capability support
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.c | 36 | ||||
| -rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.h | 1 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-mcp23s08.c | 9 |
3 files changed, 36 insertions, 10 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 9d32bb8bc13a..97bf5ec78db4 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -53,8 +53,6 @@ #define PADOWN_MASK(p) (GENMASK(3, 0) << PADOWN_SHIFT(p)) #define PADOWN_GPP(p) ((p) / 8) -#define PWMC 0x204 - /* Offset from pad_regs */ #define PADCFG0 0x000 #define PADCFG0_RXEVCFG_MASK GENMASK(26, 25) @@ -205,19 +203,25 @@ static bool intel_pad_owned_by_host(const struct intel_pinctrl *pctrl, unsigned community = intel_get_community(pctrl, pin); if (!community) return false; - if (!community->padown_offset) + + /* If padown_offset is not provided, assume host ownership */ + padown = community->regs + community->padown_offset; + if (padown == community->regs) return true; + /* New HW generations have extended PAD_OWN registers */ + if (community->features & PINCTRL_FEATURE_3BIT_PAD_OWN) + return !(readl(padown + pin_to_padno(community, pin) * 4) & 7); + padgrp = intel_community_get_padgroup(community, pin); if (!padgrp) return false; gpp_offset = padgroup_offset(padgrp, pin); gpp = PADOWN_GPP(gpp_offset); - offset = community->padown_offset + padgrp->padown_num * 4 + gpp * 4; - padown = community->regs + offset; + offset = padgrp->padown_num * 4 + gpp * 4; - return !(readl(padown) & PADOWN_MASK(gpp_offset)); + return !(readl(padown + offset) & PADOWN_MASK(gpp_offset)); } static bool intel_pad_acpi_mode(const struct intel_pinctrl *pctrl, unsigned int pin) @@ -1549,8 +1553,10 @@ static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl) } static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl, - struct intel_community *community) + struct intel_community *community, + unsigned short capability_offset) { + void __iomem *base = community->regs + capability_offset + 4; static const struct pwm_lpss_boardinfo info = { .clk_rate = 19200000, .npwm = 1, @@ -1564,7 +1570,7 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl, if (!IS_REACHABLE(CONFIG_PWM_LPSS)) return 0; - chip = devm_pwm_lpss_probe(pctrl->dev, community->regs + PWMC, &info); + chip = devm_pwm_lpss_probe(pctrl->dev, base, &info); return PTR_ERR_OR_ZERO(chip); } @@ -1595,7 +1601,9 @@ int intel_pinctrl_probe(struct platform_device *pdev, for (i = 0; i < pctrl->ncommunities; i++) { struct intel_community *community = &pctrl->communities[i]; + unsigned short capability_offset[6]; void __iomem *regs; + u32 revision; u32 offset; u32 value; @@ -1610,10 +1618,14 @@ int intel_pinctrl_probe(struct platform_device *pdev, value = readl(regs + REVID); if (value == ~0u) return -ENODEV; - if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) { + + revision = (value & REVID_MASK) >> REVID_SHIFT; + if (revision >= 0x092) { community->features |= PINCTRL_FEATURE_DEBOUNCE; community->features |= PINCTRL_FEATURE_1K_PD; } + if (revision >= 0x110) + community->features |= PINCTRL_FEATURE_3BIT_PAD_OWN; /* Determine community features based on the capabilities */ offset = CAPLIST; @@ -1622,15 +1634,19 @@ int intel_pinctrl_probe(struct platform_device *pdev, switch ((value & CAPLIST_ID_MASK) >> CAPLIST_ID_SHIFT) { case CAPLIST_ID_GPIO_HW_INFO: community->features |= PINCTRL_FEATURE_GPIO_HW_INFO; + capability_offset[CAPLIST_ID_GPIO_HW_INFO] = offset; break; case CAPLIST_ID_PWM: community->features |= PINCTRL_FEATURE_PWM; + capability_offset[CAPLIST_ID_PWM] = offset; break; case CAPLIST_ID_BLINK: community->features |= PINCTRL_FEATURE_BLINK; + capability_offset[CAPLIST_ID_BLINK] = offset; break; case CAPLIST_ID_EXP: community->features |= PINCTRL_FEATURE_EXP; + capability_offset[CAPLIST_ID_EXP] = offset; break; default: break; @@ -1653,7 +1669,7 @@ int intel_pinctrl_probe(struct platform_device *pdev, if (ret) return ret; - ret = intel_pinctrl_probe_pwm(pctrl, community); + ret = intel_pinctrl_probe_pwm(pctrl, community, capability_offset[CAPLIST_ID_PWM]); if (ret) return ret; } diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index 2f37109d5860..b5476b9de0db 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -150,6 +150,7 @@ struct intel_community { #define PINCTRL_FEATURE_PWM BIT(3) #define PINCTRL_FEATURE_BLINK BIT(4) #define PINCTRL_FEATURE_EXP BIT(5) +#define PINCTRL_FEATURE_3BIT_PAD_OWN BIT(6) #define __INTEL_COMMUNITY(b, s, e, g, n, gs, gn, soc) \ { \ diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index 586f2f67c617..b89b3169e8be 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -664,6 +664,15 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, if (mcp->irq && mcp->irq_controller) { struct gpio_irq_chip *girq = &mcp->chip.irq; + /* + * Disable all pin interrupts, to prevent the interrupt handler from + * calling nested handlers for any currently-enabled interrupts that + * do not (yet) have an actual handler. + */ + ret = mcp_write(mcp, MCP_GPINTEN, 0); + if (ret < 0) + return dev_err_probe(dev, ret, "can't disable interrupts\n"); + gpio_irq_chip_set_chip(girq, &mcp23s08_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; |
