Commit ede950b0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:
 "I'm mostly on vacation but what would vacation be without a few
  critical fixes so people can use their gaming laptops when hiding away
  from the sun (or rain)?

   - Fix a really annoying interrupt storm in the AMD driver affecting
     Asus TUF gaming notebooks

   - Fix device tree parsing in the Renesas driver"

* tag 'pinctrl-v6.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: amd: Unify debounce handling into amd_pinconf_set()
  pinctrl: amd: Drop pull up select configuration
  pinctrl: amd: Use amd_pinconf_set() for all config options
  pinctrl: amd: Only use special debounce behavior for GPIO 0
  pinctrl: renesas: rzg2l: Handle non-unique subnode names
  pinctrl: renesas: rzv2m: Handle non-unique subnode names
parents fe756ad0 04e601f2
Loading
Loading
Loading
Loading
+23 −38
Original line number Diff line number Diff line
@@ -116,21 +116,19 @@ static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
	raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}

static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
		unsigned debounce)
static int amd_gpio_set_debounce(struct amd_gpio *gpio_dev, unsigned int offset,
				 unsigned int debounce)
{
	u32 time;
	u32 pin_reg;
	int ret = 0;
	unsigned long flags;
	struct amd_gpio *gpio_dev = gpiochip_get_data(gc);

	raw_spin_lock_irqsave(&gpio_dev->lock, flags);

	/* Use special handling for Pin0 debounce */
	if (offset == 0) {
		pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
		if (pin_reg & INTERNAL_GPIO0_DEBOUNCE)
			debounce = 0;
	}

	pin_reg = readl(gpio_dev->base + offset * 4);

@@ -182,23 +180,10 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
		pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
	}
	writel(pin_reg, gpio_dev->base + offset * 4);
	raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);

	return ret;
}

static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset,
			       unsigned long config)
{
	u32 debounce;

	if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
		return -ENOTSUPP;

	debounce = pinconf_to_config_argument(config);
	return amd_gpio_set_debounce(gc, offset, debounce);
}

#ifdef CONFIG_DEBUG_FS
static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
{
@@ -220,7 +205,6 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
	char *pin_sts;
	char *interrupt_sts;
	char *wake_sts;
	char *pull_up_sel;
	char *orientation;
	char debounce_value[40];
	char *debounce_enable;
@@ -328,12 +312,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
			seq_printf(s, "   %s|", wake_sts);

			if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) {
				if (pin_reg & BIT(PULL_UP_SEL_OFF))
					pull_up_sel = "8k";
				else
					pull_up_sel = "4k";
				seq_printf(s, "%s ↑|",
					   pull_up_sel);
				seq_puts(s, "  ↑ |");
			} else if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF)) {
				seq_puts(s, "  ↓ |");
			} else  {
@@ -761,7 +740,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
		break;

	case PIN_CONFIG_BIAS_PULL_UP:
		arg = (pin_reg >> PULL_UP_SEL_OFF) & (BIT(0) | BIT(1));
		arg = (pin_reg >> PULL_UP_ENABLE_OFF) & BIT(0);
		break;

	case PIN_CONFIG_DRIVE_STRENGTH:
@@ -780,7 +759,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
}

static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
				unsigned long *configs, unsigned num_configs)
			   unsigned long *configs, unsigned int num_configs)
{
	int i;
	u32 arg;
@@ -798,9 +777,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,

		switch (param) {
		case PIN_CONFIG_INPUT_DEBOUNCE:
			pin_reg &= ~DB_TMR_OUT_MASK;
			pin_reg |= arg & DB_TMR_OUT_MASK;
			break;
			ret = amd_gpio_set_debounce(gpio_dev, pin, arg);
			goto out_unlock;

		case PIN_CONFIG_BIAS_PULL_DOWN:
			pin_reg &= ~BIT(PULL_DOWN_ENABLE_OFF);
@@ -808,10 +786,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			break;

		case PIN_CONFIG_BIAS_PULL_UP:
			pin_reg &= ~BIT(PULL_UP_SEL_OFF);
			pin_reg |= (arg & BIT(0)) << PULL_UP_SEL_OFF;
			pin_reg &= ~BIT(PULL_UP_ENABLE_OFF);
			pin_reg |= ((arg>>1) & BIT(0)) << PULL_UP_ENABLE_OFF;
			pin_reg |= (arg & BIT(0)) << PULL_UP_ENABLE_OFF;
			break;

		case PIN_CONFIG_DRIVE_STRENGTH:
@@ -829,6 +805,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,

		writel(pin_reg, gpio_dev->base + pin*4);
	}
out_unlock:
	raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);

	return ret;
@@ -870,6 +847,14 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev,
	return 0;
}

static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin,
			       unsigned long config)
{
	struct amd_gpio *gpio_dev = gpiochip_get_data(gc);

	return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1);
}

static const struct pinconf_ops amd_pinconf_ops = {
	.pin_config_get		= amd_pinconf_get,
	.pin_config_set		= amd_pinconf_set,
+0 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@
#define WAKE_CNTRL_OFF_S4               15
#define PIN_STS_OFF			16
#define DRV_STRENGTH_SEL_OFF		17
#define PULL_UP_SEL_OFF			19
#define PULL_UP_ENABLE_OFF		20
#define PULL_DOWN_ENABLE_OFF		21
#define OUTPUT_VALUE_OFF		22
+20 −8
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ static int rzg2l_map_add_config(struct pinctrl_map *map,

static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
				   struct device_node *np,
				   struct device_node *parent,
				   struct pinctrl_map **map,
				   unsigned int *num_maps,
				   unsigned int *index)
@@ -266,6 +267,7 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
	struct property *prop;
	int ret, gsel, fsel;
	const char **pin_fn;
	const char *name;
	const char *pin;

	pinmux = of_find_property(np, "pinmux", NULL);
@@ -349,8 +351,19 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
		psel_val[i] = MUX_FUNC(value);
	}

	if (parent) {
		name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
				      parent, np);
		if (!name) {
			ret = -ENOMEM;
			goto done;
		}
	} else {
		name = np->name;
	}

	/* Register a single pin group listing all the pins we read from DT */
	gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
	gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
	if (gsel < 0) {
		ret = gsel;
		goto done;
@@ -360,17 +373,16 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
	 * Register a single group function where the 'data' is an array PSEL
	 * register values read from DT.
	 */
	pin_fn[0] = np->name;
	fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
					   psel_val);
	pin_fn[0] = name;
	fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
	if (fsel < 0) {
		ret = fsel;
		goto remove_group;
	}

	maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
	maps[idx].data.mux.group = np->name;
	maps[idx].data.mux.function = np->name;
	maps[idx].data.mux.group = name;
	maps[idx].data.mux.function = name;
	idx++;

	dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -417,7 +429,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
	index = 0;

	for_each_child_of_node(np, child) {
		ret = rzg2l_dt_subnode_to_map(pctldev, child, map,
		ret = rzg2l_dt_subnode_to_map(pctldev, child, np, map,
					      num_maps, &index);
		if (ret < 0) {
			of_node_put(child);
@@ -426,7 +438,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
	}

	if (*num_maps == 0) {
		ret = rzg2l_dt_subnode_to_map(pctldev, np, map,
		ret = rzg2l_dt_subnode_to_map(pctldev, np, NULL, map,
					      num_maps, &index);
		if (ret < 0)
			goto done;
+20 −8
Original line number Diff line number Diff line
@@ -209,6 +209,7 @@ static int rzv2m_map_add_config(struct pinctrl_map *map,

static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
				   struct device_node *np,
				   struct device_node *parent,
				   struct pinctrl_map **map,
				   unsigned int *num_maps,
				   unsigned int *index)
@@ -226,6 +227,7 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
	struct property *prop;
	int ret, gsel, fsel;
	const char **pin_fn;
	const char *name;
	const char *pin;

	pinmux = of_find_property(np, "pinmux", NULL);
@@ -309,8 +311,19 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
		psel_val[i] = MUX_FUNC(value);
	}

	if (parent) {
		name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
				      parent, np);
		if (!name) {
			ret = -ENOMEM;
			goto done;
		}
	} else {
		name = np->name;
	}

	/* Register a single pin group listing all the pins we read from DT */
	gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
	gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
	if (gsel < 0) {
		ret = gsel;
		goto done;
@@ -320,17 +333,16 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
	 * Register a single group function where the 'data' is an array PSEL
	 * register values read from DT.
	 */
	pin_fn[0] = np->name;
	fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
					   psel_val);
	pin_fn[0] = name;
	fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
	if (fsel < 0) {
		ret = fsel;
		goto remove_group;
	}

	maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
	maps[idx].data.mux.group = np->name;
	maps[idx].data.mux.function = np->name;
	maps[idx].data.mux.group = name;
	maps[idx].data.mux.function = name;
	idx++;

	dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -377,7 +389,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
	index = 0;

	for_each_child_of_node(np, child) {
		ret = rzv2m_dt_subnode_to_map(pctldev, child, map,
		ret = rzv2m_dt_subnode_to_map(pctldev, child, np, map,
					      num_maps, &index);
		if (ret < 0) {
			of_node_put(child);
@@ -386,7 +398,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
	}

	if (*num_maps == 0) {
		ret = rzv2m_dt_subnode_to_map(pctldev, np, map,
		ret = rzv2m_dt_subnode_to_map(pctldev, np, NULL, map,
					      num_maps, &index);
		if (ret < 0)
			goto done;