Commit 9f0648f1 authored by Linus Walleij's avatar Linus Walleij
Browse files

Merge tag 'intel-pinctrl-v6.5-1' of...

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

intel-pinctrl for v6.5-1

* Fix of OPEN DRAIN pin mode setting in a few drivers
* Reduce a scope of spin lock in the Bay Trail driver
* Decrease a code footprint by refactoring in a few drivers
* Expand string choices and reuse that in the Bay Trail driver

The following is an automated git shortlog grouped by driver:

baytrail:
 -  invert if condition
 -  add warning for BYT_VAL_REG retrieval failure
 -  reduce scope of spinlock in ->dbg_show() hook
 -  Use str_hi_lo() helper
 -  Use BIT() in BYT_PULL_ASSIGN_* definitions
 -  Unify style of error and debug messages

cherryview:
 -  Drop goto label
 -  Return correct value if pin in push-pull mode
 -  Don't use IRQ core constanst for invalid IRQ

intel:
 -  refine ->irq_set_type() hook
 -  refine ->set_mux() hook
 -  Add Intel Meteor Lake-S pin controller support

lib/string_helpers:
 -  Add str_high_low() helper
 -  Split out string_choices.h
 -  Add missing header files to MAINTAINERS database

merrifield:
 -  Use BUFCFG_PINMODE_GPIO in ->pin_dbg_show()
 -  Fix open-drain pin mode configuration

moorefield:
 -  Use BUFCFG_PINMODE_GPIO in ->pin_dbg_show()
 -  Fix open-drain pin mode configuration
parents d18b2a0f 9314d053
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -8670,6 +8670,9 @@ F: drivers/input/touchscreen/resistive-adc-touch.c
GENERIC STRING LIBRARY
R:	Andy Shevchenko <andy@kernel.org>
S:	Maintained
F:	include/linux/string.h
F:	include/linux/string_choices.h
F:	include/linux/string_helpers.h
F:	lib/string.c
F:	lib/string_helpers.c
F:	lib/test_string.c
+46 −58
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/seq_file.h>
#include <linux/string_helpers.h>

#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -52,10 +53,9 @@
#define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
#define BYT_PULL_ASSIGN_SHIFT	7
#define BYT_PULL_ASSIGN_MASK	GENMASK(8, 7)
#define BYT_PULL_ASSIGN_UP	(1 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PULL_ASSIGN_DOWN	(2 << BYT_PULL_ASSIGN_SHIFT)
#define BYT_PULL_ASSIGN_DOWN	BIT(8)
#define BYT_PULL_ASSIGN_UP	BIT(7)
#define BYT_PIN_MUX		GENMASK(2, 0)

/* BYT_VAL_REG register bits */
@@ -668,8 +668,7 @@ static void byt_set_group_simple_mux(struct intel_pinctrl *vg,

		padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
		if (!padcfg0) {
			dev_warn(vg->dev,
				 "Group %s, pin %i not muxed (no padcfg0)\n",
			dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
				 group.grp.name, i);
			continue;
		}
@@ -698,8 +697,7 @@ static void byt_set_group_mixed_mux(struct intel_pinctrl *vg,

		padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
		if (!padcfg0) {
			dev_warn(vg->dev,
				 "Group %s, pin %i not muxed (no padcfg0)\n",
			dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
				 group.grp.name, i);
			continue;
		}
@@ -755,9 +753,7 @@ static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int off
	value = readl(reg);

	/* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */
	if (value & BYT_DIRECT_IRQ_EN)
		/* nothing to do */ ;
	else
	if (!(value & BYT_DIRECT_IRQ_EN))
		value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);

	writel(value, reg);
@@ -791,7 +787,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
		value |= gpio_mux;
		writel(value, reg);

		dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset);
		dev_warn(vg->dev, FW_BUG "Pin %i: forcibly re-configured as GPIO\n", offset);
	}

	raw_spin_unlock_irqrestore(&byt_lock, flags);
@@ -823,7 +819,9 @@ static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg,
	 * themselves in the foot.
	 */
	if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
		dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
		dev_info_once(vg->dev,
			      "Potential Error: Pin %i: forcibly set GPIO with DIRECT_IRQ_EN to output\n",
			      offset);
}

static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
@@ -1026,9 +1024,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
			if (val & BYT_INPUT_EN) {
				val &= ~BYT_INPUT_EN;
				writel(val, val_reg);
				dev_warn(vg->dev,
					 "pin %u forcibly set to input mode\n",
					 offset);
				dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset);
			}

			conf &= ~BYT_PULL_ASSIGN_MASK;
@@ -1048,9 +1044,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
			if (val & BYT_INPUT_EN) {
				val &= ~BYT_INPUT_EN;
				writel(val, val_reg);
				dev_warn(vg->dev,
					 "pin %u forcibly set to input mode\n",
					 offset);
				dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset);
			}

			conf &= ~BYT_PULL_ASSIGN_MASK;
@@ -1245,39 +1239,35 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)

	for (i = 0; i < vg->soc->npins; i++) {
		const struct intel_community *comm;
		void __iomem *conf_reg, *val_reg;
		const char *pull_str = NULL;
		const char *pull = NULL;
		void __iomem *reg;
		unsigned long flags;
		const char *label;
		unsigned int pin;

		raw_spin_lock_irqsave(&byt_lock, flags);
		pin = vg->soc->pins[i].number;
		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
		if (!reg) {
			seq_printf(s,
				   "Could not retrieve pin %i conf0 reg\n",
				   pin);
			raw_spin_unlock_irqrestore(&byt_lock, flags);

		conf_reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
		if (!conf_reg) {
			seq_printf(s, "Pin %i: can't retrieve CONF0\n", pin);
			continue;
		}
		conf0 = readl(reg);

		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
		if (!reg) {
			seq_printf(s,
				   "Could not retrieve pin %i val reg\n", pin);
			raw_spin_unlock_irqrestore(&byt_lock, flags);
		val_reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
		if (!val_reg) {
			seq_printf(s, "Pin %i: can't retrieve VAL\n", pin);
			continue;
		}
		val = readl(reg);

		raw_spin_lock_irqsave(&byt_lock, flags);
		conf0 = readl(conf_reg);
		val = readl(val_reg);
		raw_spin_unlock_irqrestore(&byt_lock, flags);

		comm = byt_get_community(vg, pin);
		if (!comm) {
			seq_printf(s,
				   "Could not get community for pin %i\n", pin);
			seq_printf(s, "Pin %i: can't retrieve community\n", pin);
			continue;
		}
		label = gpiochip_is_requested(chip, i);
@@ -1314,7 +1304,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
			   label,
			   val & BYT_INPUT_EN ? "  " : "in",
			   val & BYT_OUTPUT_EN ? "   " : "out",
			   val & BYT_LEVEL ? "hi" : "lo",
			   str_hi_lo(val & BYT_LEVEL),
			   comm->pad_map[i], comm->pad_map[i] * 16,
			   conf0 & 0x7,
			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
@@ -1429,7 +1419,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
	value = readl(reg);

	WARN(value & BYT_DIRECT_IRQ_EN,
	     "Bad pad config for io mode, force direct_irq_en bit clearing");
	     "Bad pad config for IO mode, force DIRECT_IRQ_EN bit clearing");

	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
	 * are used to indicate high and low level triggering
@@ -1476,9 +1466,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);

		if (!reg) {
			dev_warn(vg->dev,
				 "Pin %i: could not retrieve interrupt status register\n",
				 base);
			dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
			continue;
		}

@@ -1501,7 +1489,7 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c
		      sizeof(direct_irq_mux));
	match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux));
	if (!match) {
		dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin);
		dev_warn(vg->dev, FW_BUG "Pin %i: DIRECT_IRQ_EN set but no IRQ assigned, clearing\n", pin);
		return false;
	}

@@ -1528,7 +1516,8 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c
	trig = conf0 & BYT_TRIG_MASK;
	if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) &&
	    trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) {
		dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n",
		dev_warn(vg->dev,
			 FW_BUG "Pin %i: DIRECT_IRQ_EN set without trigger (CONF0: %#08x), clearing\n",
			 pin, conf0);
		return false;
	}
@@ -1555,9 +1544,7 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip,

		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
		if (!reg) {
			dev_warn(vg->dev,
				 "Pin %i: could not retrieve conf0 register\n",
				 i);
			dev_warn(vg->dev, "Pin %i: could not retrieve CONF0\n", i);
			continue;
		}

@@ -1588,9 +1575,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);

		if (!reg) {
			dev_warn(vg->dev,
				 "Pin %i: could not retrieve irq status reg\n",
				 base);
			dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
			continue;
		}

@@ -1600,7 +1585,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
		value = readl(reg);
		if (value)
			dev_err(vg->dev,
				"GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
				"GPIO interrupt error, pins misconfigured. INT_STAT%u: %#08x\n",
				base / 32, value);
	}

@@ -1764,15 +1749,17 @@ static int byt_gpio_suspend(struct device *dev)

		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
		if (!reg) {
			dev_warn(vg->dev,
				 "Pin %i: could not retrieve conf0 register\n",
				 i);
			dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
			continue;
		}
		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
		vg->context.pads[i].conf0 = value;

		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
		if (!reg) {
			dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
			continue;
		}
		value = readl(reg) & BYT_VAL_RESTORE_MASK;
		vg->context.pads[i].val = value;
	}
@@ -1796,9 +1783,7 @@ static int byt_gpio_resume(struct device *dev)

		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
		if (!reg) {
			dev_warn(vg->dev,
				 "Pin %i: could not retrieve conf0 register\n",
				 i);
			dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
			continue;
		}
		value = readl(reg);
@@ -1807,10 +1792,14 @@ static int byt_gpio_resume(struct device *dev)
			value &= ~BYT_CONF0_RESTORE_MASK;
			value |= vg->context.pads[i].conf0;
			writel(value, reg);
			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
			dev_info(dev, "restored pin %d CONF0 %#08x", i, value);
		}

		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
		if (!reg) {
			dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
			continue;
		}
		value = readl(reg);
		if ((value & BYT_VAL_RESTORE_MASK) !=
		     vg->context.pads[i].val) {
@@ -1820,8 +1809,7 @@ static int byt_gpio_resume(struct device *dev)
			v |= vg->context.pads[i].val;
			if (v != value) {
				writel(v, reg);
				dev_dbg(dev, "restored pin %d val %#08x\n",
					i, v);
				dev_dbg(dev, "restored pin %d VAL %#08x\n", i, v);
			}
		}
	}
+16 −10
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ struct intel_pad_context {
	u32 padctrl1;
};

#define CHV_INVALID_HWIRQ	((unsigned int)INVALID_HWIRQ)
#define CHV_INVALID_HWIRQ	(~0U)

/**
 * struct intel_community_context - community context for Cherryview
@@ -949,11 +949,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,

		break;

	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		if (!(ctrl1 & CHV_PADCTRL1_ODEN))
			return -EINVAL;
		break;

	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: {
		u32 cfg;

@@ -963,6 +958,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
			return -EINVAL;

		break;

	case PIN_CONFIG_DRIVE_PUSH_PULL:
		if (ctrl1 & CHV_PADCTRL1_ODEN)
			return -EINVAL;
		break;

	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		if (!(ctrl1 & CHV_PADCTRL1_ODEN))
			return -EINVAL;
		break;
	}

	default:
@@ -1408,8 +1413,10 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
	raw_spin_lock_irqsave(&chv_lock, flags);

	ret = chv_gpio_set_intr_line(pctrl, hwirq);
	if (ret)
		goto out_unlock;
	if (ret) {
		raw_spin_unlock_irqrestore(&chv_lock, flags);
		return ret;
	}

	/*
	 * Pins which can be used as shared interrupt are configured in
@@ -1450,10 +1457,9 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
	else if (type & IRQ_TYPE_LEVEL_MASK)
		irq_set_handler_locked(d, handle_level_irq);

out_unlock:
	raw_spin_unlock_irqrestore(&chv_lock, flags);

	return ret;
	return 0;
}

static const struct irq_chip chv_gpio_irq_chip = {
+29 −25
Original line number Diff line number Diff line
@@ -55,12 +55,11 @@

/* Offset from pad_regs */
#define PADCFG0				0x000
#define PADCFG0_RXEVCFG_SHIFT		25
#define PADCFG0_RXEVCFG_MASK		GENMASK(26, 25)
#define PADCFG0_RXEVCFG_LEVEL		0
#define PADCFG0_RXEVCFG_EDGE		1
#define PADCFG0_RXEVCFG_DISABLED	2
#define PADCFG0_RXEVCFG_EDGE_BOTH	3
#define PADCFG0_RXEVCFG_LEVEL		(0 << 25)
#define PADCFG0_RXEVCFG_EDGE		(1 << 25)
#define PADCFG0_RXEVCFG_DISABLED	(2 << 25)
#define PADCFG0_RXEVCFG_EDGE_BOTH	(3 << 25)
#define PADCFG0_PREGFRXSEL		BIT(24)
#define PADCFG0_RXINV			BIT(23)
#define PADCFG0_GPIROUTIOXAPIC		BIT(20)
@@ -411,18 +410,19 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
	/* Now enable the mux setting for each pin in the group */
	for (i = 0; i < grp->grp.npins; i++) {
		void __iomem *padcfg0;
		u32 value;
		u32 value, pmode;

		padcfg0 = intel_get_padcfg(pctrl, grp->grp.pins[i], PADCFG0);
		value = readl(padcfg0);

		value = readl(padcfg0);
		value &= ~PADCFG0_PMODE_MASK;

		if (grp->modes)
			value |= grp->modes[i] << PADCFG0_PMODE_SHIFT;
			pmode = grp->modes[i];
		else
			value |= grp->mode << PADCFG0_PMODE_SHIFT;
			pmode = grp->mode;

		value |= pmode << PADCFG0_PMODE_SHIFT;
		writel(value, padcfg0);
	}

@@ -1126,9 +1126,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
	unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
	u32 rxevcfg, rxinv, value;
	unsigned long flags;
	void __iomem *reg;
	u32 value;

	reg = intel_get_padcfg(pctrl, pin, PADCFG0);
	if (!reg)
@@ -1144,28 +1144,32 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
		return -EPERM;
	}

	raw_spin_lock_irqsave(&pctrl->lock, flags);

	intel_gpio_set_gpio_mode(reg);

	value = readl(reg);

	value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);

	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
		value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT;
		rxevcfg = PADCFG0_RXEVCFG_EDGE_BOTH;
	} else if (type & IRQ_TYPE_EDGE_FALLING) {
		value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
		value |= PADCFG0_RXINV;
		rxevcfg = PADCFG0_RXEVCFG_EDGE;
	} else if (type & IRQ_TYPE_EDGE_RISING) {
		value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
		rxevcfg = PADCFG0_RXEVCFG_EDGE;
	} else if (type & IRQ_TYPE_LEVEL_MASK) {
		if (type & IRQ_TYPE_LEVEL_LOW)
			value |= PADCFG0_RXINV;
		rxevcfg = PADCFG0_RXEVCFG_LEVEL;
	} else {
		value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT;
		rxevcfg = PADCFG0_RXEVCFG_DISABLED;
	}

	if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW)
		rxinv = PADCFG0_RXINV;
	else
		rxinv = 0;

	raw_spin_lock_irqsave(&pctrl->lock, flags);

	intel_gpio_set_gpio_mode(reg);

	value = readl(reg);

	value = (value & ~PADCFG0_RXEVCFG_MASK) | rxevcfg;
	value = (value & ~PADCFG0_RXINV) | rxinv;

	writel(value, reg);

	if (type & IRQ_TYPE_EDGE_BOTH)
+13 −3
Original line number Diff line number Diff line
@@ -549,7 +549,7 @@ static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
	}

	mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
	if (!mode)
	if (mode == BUFCFG_PINMODE_GPIO)
		seq_puts(s, "GPIO ");
	else
		seq_printf(s, "mode %d ", mode);
@@ -710,6 +710,11 @@ static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,

		break;

	case PIN_CONFIG_DRIVE_PUSH_PULL:
		if (value & BUFCFG_OD_EN)
			return -EINVAL;
		break;

	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		if (!(value & BUFCFG_OD_EN))
			return -EINVAL;
@@ -791,9 +796,13 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin,

		break;

	case PIN_CONFIG_DRIVE_PUSH_PULL:
		mask |= BUFCFG_OD_EN;
		bits &= ~BUFCFG_OD_EN;
		break;

	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		mask |= BUFCFG_OD_EN;
		if (arg)
		bits |= BUFCFG_OD_EN;
		break;

@@ -826,6 +835,7 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
		case PIN_CONFIG_BIAS_DISABLE:
		case PIN_CONFIG_BIAS_PULL_UP:
		case PIN_CONFIG_BIAS_PULL_DOWN:
		case PIN_CONFIG_DRIVE_PUSH_PULL:
		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		case PIN_CONFIG_SLEW_RATE:
			ret = mrfld_config_set_pin(mp, pin, configs[i]);
Loading