Pin control fixes for the v7.0 series:
- 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.
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmnYob4ACgkQQRCzN7AZ
XXME3A//QZAEsAOPr/YJ9yHINKPySSvOR14TbK04nZECqYObY7jxR+clKJp/2r4A
ZdNAjIkoochI1mKloOnNvLsixpsFVpNW0aOhc0o/ynLIX/Syxur2gjHEytLUyr1D
At+6eZ4sOkRcjPIhDUdZ6I6jny8P8ELpgKuQ/VMXiOFvqpUZcciYJkZhaE9WRiuj
ymO9ALmepWDyqMn7cK/lhqNwAaBhYyKGRogeajYiM5txomkzpl1oiHt28ScA03ac
f2fN8DikRn5/QAETzWIuBHGZp3d96gMZVsoVo2rWtvCaUhK60kNE4ZtbXMAjkJZX
47KshfVjF/gucruhxIXYj3f6uET+uDIAbHsaP7Xxwf0MnGnihvrDh+FLptUB3MZA
fgaKbiF8oDkNAqO2AT+KfA/NUE7TYnUnH0M+k2EwT2YNl8hSuFmCq7mWSRsl/Rlw
W9AEmqGPqga2og4REOBEn3S02GUVonjGq72pfXzQgdvpBuDPlrB35wz6t/4Mo6qZ
wkbOCS4M3ACOyMxQu7SPtTAqTegHms8gzQguYHtem9RM9UlLo2RzGrOrSzVN9mEC
fK2/jZUzNCphUVXnfbZTfVacRVvBLDnAfNTYLppkcLFBNMCxm3X8NG1/BwmKVZbj
cK9NJPhGulKjEcTYPegRSMlF7CRL0Kq7ATjTLSFuo/UbUAM9PiI=
=WxTb
-----END PGP SIGNATURE-----
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
master
commit
77c3c619d2
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
{ \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue