Commit 77c3c619 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 9a9c8ce3 db5b8cec
Loading
Loading
Loading
Loading
+26 −10
Original line number Diff line number Diff line
@@ -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;
	}
+1 −0
Original line number Diff line number Diff line
@@ -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)		\
	{							\
+9 −0
Original line number Diff line number Diff line
@@ -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;