Commit 61471911 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:
 "Only driver fixes:

   - NULL check for the ralink and sunplus drivers

   - Add Jacky Bai as maintainer for the Freescale pin controllers

   - Fix pin config ops for the Ocelot LAN966x and SparX5

   - Disallow AMD pin control to be a module: the GPIO lines need to be
     active in early boot, so no can do

   - Fix the Armada 37xx to use raw spinlocks in the interrupt handler
     path to avoid wait context"

* tag 'pinctrl-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: armada-37xx: use raw spinlocks for regmap to avoid invalid wait context
  pinctrl: armada-37xx: make irq_lock a raw spinlock to avoid invalid wait context
  pinctrl: Don't allow PINCTRL_AMD to be a module
  pinctrl: ocelot: Fix pincfg
  pinctrl: ocelot: Fix pincfg for lan966x
  MAINTAINERS: Update freescale pin controllers maintainer
  pinctrl: sunplus: Add check for kcalloc
  pinctrl: ralink: Check for null return of devm_kcalloc
parents 8f636c6a 45467606
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15849,7 +15849,7 @@ PIN CONTROLLER - FREESCALE
M:	Dong Aisheng <aisheng.dong@nxp.com>
M:	Fabio Estevam <festevam@gmail.com>
M:	Shawn Guo <shawnguo@kernel.org>
M:	Stefan Agner <stefan@agner.ch>
M:	Jacky Bai <ping.bai@nxp.com>
R:	Pengutronix Kernel Team <kernel@pengutronix.de>
L:	linux-gpio@vger.kernel.org
S:	Maintained
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ config DEBUG_PINCTRL
	  Say Y here to add some extra checks and diagnostics to PINCTRL calls.

config PINCTRL_AMD
	tristate "AMD GPIO pin control"
	bool "AMD GPIO pin control"
	depends on HAS_IOMEM
	depends on ACPI || COMPILE_TEST
	select GPIOLIB
+40 −25
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ struct armada_37xx_pinctrl {
	struct device			*dev;
	struct gpio_chip		gpio_chip;
	struct irq_chip			irq_chip;
	spinlock_t			irq_lock;
	raw_spinlock_t			irq_lock;
	struct pinctrl_desc		pctl;
	struct pinctrl_dev		*pctl_dev;
	struct armada_37xx_pin_group	*groups;
@@ -523,9 +523,9 @@ static void armada_37xx_irq_ack(struct irq_data *d)
	unsigned long flags;

	armada_37xx_irq_update_reg(&reg, d);
	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	writel(d->mask, info->base + reg);
	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);
}

static void armada_37xx_irq_mask(struct irq_data *d)
@@ -536,10 +536,10 @@ static void armada_37xx_irq_mask(struct irq_data *d)
	unsigned long flags;

	armada_37xx_irq_update_reg(&reg, d);
	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	val = readl(info->base + reg);
	writel(val & ~d->mask, info->base + reg);
	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);
}

static void armada_37xx_irq_unmask(struct irq_data *d)
@@ -550,10 +550,10 @@ static void armada_37xx_irq_unmask(struct irq_data *d)
	unsigned long flags;

	armada_37xx_irq_update_reg(&reg, d);
	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	val = readl(info->base + reg);
	writel(val | d->mask, info->base + reg);
	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);
}

static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -564,14 +564,14 @@ static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on)
	unsigned long flags;

	armada_37xx_irq_update_reg(&reg, d);
	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	val = readl(info->base + reg);
	if (on)
		val |= (BIT(d->hwirq % GPIO_PER_REG));
	else
		val &= ~(BIT(d->hwirq % GPIO_PER_REG));
	writel(val, info->base + reg);
	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);

	return 0;
}
@@ -583,7 +583,7 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
	u32 val, reg = IRQ_POL;
	unsigned long flags;

	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	armada_37xx_irq_update_reg(&reg, d);
	val = readl(info->base + reg);
	switch (type) {
@@ -607,11 +607,11 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
		break;
	}
	default:
		spin_unlock_irqrestore(&info->irq_lock, flags);
		raw_spin_unlock_irqrestore(&info->irq_lock, flags);
		return -EINVAL;
	}
	writel(val, info->base + reg);
	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);

	return 0;
}
@@ -626,7 +626,7 @@ static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,

	regmap_read(info->regmap, INPUT_VAL + 4*reg_idx, &l);

	spin_lock_irqsave(&info->irq_lock, flags);
	raw_spin_lock_irqsave(&info->irq_lock, flags);
	p = readl(info->base + IRQ_POL + 4 * reg_idx);
	if ((p ^ l) & (1 << bit_num)) {
		/*
@@ -647,7 +647,7 @@ static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,
		ret = -1;
	}

	spin_unlock_irqrestore(&info->irq_lock, flags);
	raw_spin_unlock_irqrestore(&info->irq_lock, flags);
	return ret;
}

@@ -664,11 +664,11 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
		u32 status;
		unsigned long flags;

		spin_lock_irqsave(&info->irq_lock, flags);
		raw_spin_lock_irqsave(&info->irq_lock, flags);
		status = readl_relaxed(info->base + IRQ_STATUS + 4 * i);
		/* Manage only the interrupt that was enabled */
		status &= readl_relaxed(info->base + IRQ_EN + 4 * i);
		spin_unlock_irqrestore(&info->irq_lock, flags);
		raw_spin_unlock_irqrestore(&info->irq_lock, flags);
		while (status) {
			u32 hwirq = ffs(status) - 1;
			u32 virq = irq_find_mapping(d, hwirq +
@@ -695,12 +695,12 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)

update_status:
			/* Update status in case a new IRQ appears */
			spin_lock_irqsave(&info->irq_lock, flags);
			raw_spin_lock_irqsave(&info->irq_lock, flags);
			status = readl_relaxed(info->base +
					       IRQ_STATUS + 4 * i);
			/* Manage only the interrupt that was enabled */
			status &= readl_relaxed(info->base + IRQ_EN + 4 * i);
			spin_unlock_irqrestore(&info->irq_lock, flags);
			raw_spin_unlock_irqrestore(&info->irq_lock, flags);
		}
	}
	chained_irq_exit(chip, desc);
@@ -731,7 +731,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
	struct device *dev = &pdev->dev;
	unsigned int i, nr_irq_parent;

	spin_lock_init(&info->irq_lock);
	raw_spin_lock_init(&info->irq_lock);

	nr_irq_parent = of_irq_count(np);
	if (!nr_irq_parent) {
@@ -1107,25 +1107,40 @@ static const struct of_device_id armada_37xx_pinctrl_of_match[] = {
	{ },
};

static const struct regmap_config armada_37xx_pinctrl_regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
	.use_raw_spinlock = true,
};

static int __init armada_37xx_pinctrl_probe(struct platform_device *pdev)
{
	struct armada_37xx_pinctrl *info;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct regmap *regmap;
	void __iomem *base;
	int ret;

	base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
	if (IS_ERR(base)) {
		dev_err(dev, "failed to ioremap base address: %pe\n", base);
		return PTR_ERR(base);
	}

	regmap = devm_regmap_init_mmio(dev, base,
				       &armada_37xx_pinctrl_regmap_config);
	if (IS_ERR(regmap)) {
		dev_err(dev, "failed to create regmap: %pe\n", regmap);
		return PTR_ERR(regmap);
	}

	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	info->dev = dev;

	regmap = syscon_node_to_regmap(np);
	if (IS_ERR(regmap))
		return dev_err_probe(dev, PTR_ERR(regmap), "cannot get regmap\n");
	info->regmap = regmap;

	info->data = of_device_get_match_data(dev);

	ret = armada_37xx_pinctrl_register(pdev, info);
+137 −77
Original line number Diff line number Diff line
@@ -29,19 +29,12 @@
#define ocelot_clrsetbits(addr, clear, set) \
	writel((readl(addr) & ~(clear)) | (set), (addr))

/* PINCONFIG bits (sparx5 only) */
enum {
	PINCONF_BIAS,
	PINCONF_SCHMITT,
	PINCONF_DRIVE_STRENGTH,
};

#define BIAS_PD_BIT BIT(4)
#define BIAS_PU_BIT BIT(3)
#define BIAS_BITS   (BIAS_PD_BIT|BIAS_PU_BIT)
#define SCHMITT_BIT BIT(2)
#define DRIVE_BITS  GENMASK(1, 0)

/* GPIO standard registers */
#define OCELOT_GPIO_OUT_SET	0x0
#define OCELOT_GPIO_OUT_CLR	0x4
@@ -321,6 +314,13 @@ struct ocelot_pin_caps {
	unsigned char a_functions[OCELOT_FUNC_PER_PIN];	/* Additional functions */
};

struct ocelot_pincfg_data {
	u8 pd_bit;
	u8 pu_bit;
	u8 drive_bits;
	u8 schmitt_bit;
};

struct ocelot_pinctrl {
	struct device *dev;
	struct pinctrl_dev *pctl;
@@ -328,10 +328,16 @@ struct ocelot_pinctrl {
	struct regmap *map;
	struct regmap *pincfg;
	struct pinctrl_desc *desc;
	const struct ocelot_pincfg_data *pincfg_data;
	struct ocelot_pmx_func func[FUNC_MAX];
	u8 stride;
};

struct ocelot_match_data {
	struct pinctrl_desc desc;
	struct ocelot_pincfg_data pincfg_data;
};

#define LUTON_P(p, f0, f1)						\
static struct ocelot_pin_caps luton_pin_##p = {				\
	.pin = p,							\
@@ -1325,24 +1331,27 @@ static int ocelot_hw_get_value(struct ocelot_pinctrl *info,
	int ret = -EOPNOTSUPP;

	if (info->pincfg) {
		const struct ocelot_pincfg_data *opd = info->pincfg_data;
		u32 regcfg;

		ret = regmap_read(info->pincfg, pin, &regcfg);
		ret = regmap_read(info->pincfg,
				  pin * regmap_get_reg_stride(info->pincfg),
				  &regcfg);
		if (ret)
			return ret;

		ret = 0;
		switch (reg) {
		case PINCONF_BIAS:
			*val = regcfg & BIAS_BITS;
			*val = regcfg & (opd->pd_bit | opd->pu_bit);
			break;

		case PINCONF_SCHMITT:
			*val = regcfg & SCHMITT_BIT;
			*val = regcfg & opd->schmitt_bit;
			break;

		case PINCONF_DRIVE_STRENGTH:
			*val = regcfg & DRIVE_BITS;
			*val = regcfg & opd->drive_bits;
			break;

		default:
@@ -1359,14 +1368,18 @@ static int ocelot_pincfg_clrsetbits(struct ocelot_pinctrl *info, u32 regaddr,
	u32 val;
	int ret;

	ret = regmap_read(info->pincfg, regaddr, &val);
	ret = regmap_read(info->pincfg,
			  regaddr * regmap_get_reg_stride(info->pincfg),
			  &val);
	if (ret)
		return ret;

	val &= ~clrbits;
	val |= setbits;

	ret = regmap_write(info->pincfg, regaddr, val);
	ret = regmap_write(info->pincfg,
			   regaddr * regmap_get_reg_stride(info->pincfg),
			   val);

	return ret;
}
@@ -1379,23 +1392,27 @@ static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
	int ret = -EOPNOTSUPP;

	if (info->pincfg) {
		const struct ocelot_pincfg_data *opd = info->pincfg_data;

		ret = 0;
		switch (reg) {
		case PINCONF_BIAS:
			ret = ocelot_pincfg_clrsetbits(info, pin, BIAS_BITS,
			ret = ocelot_pincfg_clrsetbits(info, pin,
						       opd->pd_bit | opd->pu_bit,
						       val);
			break;

		case PINCONF_SCHMITT:
			ret = ocelot_pincfg_clrsetbits(info, pin, SCHMITT_BIT,
			ret = ocelot_pincfg_clrsetbits(info, pin,
						       opd->schmitt_bit,
						       val);
			break;

		case PINCONF_DRIVE_STRENGTH:
			if (val <= 3)
				ret = ocelot_pincfg_clrsetbits(info, pin,
							       DRIVE_BITS, val);
							       opd->drive_bits,
							       val);
			else
				ret = -EINVAL;
			break;
@@ -1425,17 +1442,20 @@ static int ocelot_pinconf_get(struct pinctrl_dev *pctldev,
		if (param == PIN_CONFIG_BIAS_DISABLE)
			val = (val == 0);
		else if (param == PIN_CONFIG_BIAS_PULL_DOWN)
			val = (val & BIAS_PD_BIT ? true : false);
			val = !!(val & info->pincfg_data->pd_bit);
		else    /* PIN_CONFIG_BIAS_PULL_UP */
			val = (val & BIAS_PU_BIT ? true : false);
			val = !!(val & info->pincfg_data->pu_bit);
		break;

	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
		if (!info->pincfg_data->schmitt_bit)
			return -EOPNOTSUPP;

		err = ocelot_hw_get_value(info, pin, PINCONF_SCHMITT, &val);
		if (err)
			return err;

		val = (val & SCHMITT_BIT ? true : false);
		val = !!(val & info->pincfg_data->schmitt_bit);
		break;

	case PIN_CONFIG_DRIVE_STRENGTH:
@@ -1479,6 +1499,7 @@ static int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			      unsigned long *configs, unsigned int num_configs)
{
	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
	const struct ocelot_pincfg_data *opd = info->pincfg_data;
	u32 param, arg, p;
	int cfg, err = 0;

@@ -1491,8 +1512,8 @@ static int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
		case PIN_CONFIG_BIAS_PULL_UP:
		case PIN_CONFIG_BIAS_PULL_DOWN:
			arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
			(param == PIN_CONFIG_BIAS_PULL_UP) ? BIAS_PU_BIT :
			BIAS_PD_BIT;
			      (param == PIN_CONFIG_BIAS_PULL_UP) ?
				opd->pu_bit : opd->pd_bit;

			err = ocelot_hw_set_value(info, pin, PINCONF_BIAS, arg);
			if (err)
@@ -1501,7 +1522,10 @@ static int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			break;

		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
			arg = arg ? SCHMITT_BIT : 0;
			if (!opd->schmitt_bit)
				return -EOPNOTSUPP;

			arg = arg ? opd->schmitt_bit : 0;
			err = ocelot_hw_set_value(info, pin, PINCONF_SCHMITT,
						  arg);
			if (err)
@@ -1562,52 +1586,63 @@ static const struct pinctrl_ops ocelot_pctl_ops = {
	.dt_free_map = pinconf_generic_dt_free_map,
};

static struct pinctrl_desc luton_desc = {
static struct ocelot_match_data luton_desc = {
	.desc = {
		.name = "luton-pinctrl",
		.pins = luton_pins,
		.npins = ARRAY_SIZE(luton_pins),
		.pctlops = &ocelot_pctl_ops,
		.pmxops = &ocelot_pmx_ops,
		.owner = THIS_MODULE,
	},
};

static struct pinctrl_desc serval_desc = {
static struct ocelot_match_data serval_desc = {
	.desc = {
		.name = "serval-pinctrl",
		.pins = serval_pins,
		.npins = ARRAY_SIZE(serval_pins),
		.pctlops = &ocelot_pctl_ops,
		.pmxops = &ocelot_pmx_ops,
		.owner = THIS_MODULE,
	},
};

static struct pinctrl_desc ocelot_desc = {
static struct ocelot_match_data ocelot_desc = {
	.desc = {
		.name = "ocelot-pinctrl",
		.pins = ocelot_pins,
		.npins = ARRAY_SIZE(ocelot_pins),
		.pctlops = &ocelot_pctl_ops,
		.pmxops = &ocelot_pmx_ops,
		.owner = THIS_MODULE,
	},
};

static struct pinctrl_desc jaguar2_desc = {
static struct ocelot_match_data jaguar2_desc = {
	.desc = {
		.name = "jaguar2-pinctrl",
		.pins = jaguar2_pins,
		.npins = ARRAY_SIZE(jaguar2_pins),
		.pctlops = &ocelot_pctl_ops,
		.pmxops = &ocelot_pmx_ops,
		.owner = THIS_MODULE,
	},
};

static struct pinctrl_desc servalt_desc = {
static struct ocelot_match_data servalt_desc = {
	.desc = {
		.name = "servalt-pinctrl",
		.pins = servalt_pins,
		.npins = ARRAY_SIZE(servalt_pins),
		.pctlops = &ocelot_pctl_ops,
		.pmxops = &ocelot_pmx_ops,
		.owner = THIS_MODULE,
	},
};

static struct pinctrl_desc sparx5_desc = {
static struct ocelot_match_data sparx5_desc = {
	.desc = {
		.name = "sparx5-pinctrl",
		.pins = sparx5_pins,
		.npins = ARRAY_SIZE(sparx5_pins),
@@ -1615,9 +1650,17 @@ static struct pinctrl_desc sparx5_desc = {
		.pmxops = &ocelot_pmx_ops,
		.confops = &ocelot_confops,
		.owner = THIS_MODULE,
	},
	.pincfg_data = {
		.pd_bit = BIT(4),
		.pu_bit = BIT(3),
		.drive_bits = GENMASK(1, 0),
		.schmitt_bit = BIT(2),
	},
};

static struct pinctrl_desc lan966x_desc = {
static struct ocelot_match_data lan966x_desc = {
	.desc = {
		.name = "lan966x-pinctrl",
		.pins = lan966x_pins,
		.npins = ARRAY_SIZE(lan966x_pins),
@@ -1625,6 +1668,12 @@ static struct pinctrl_desc lan966x_desc = {
		.pmxops = &lan966x_pmx_ops,
		.confops = &ocelot_confops,
		.owner = THIS_MODULE,
	},
	.pincfg_data = {
		.pd_bit = BIT(3),
		.pu_bit = BIT(2),
		.drive_bits = GENMASK(1, 0),
	},
};

static int ocelot_create_group_func_map(struct device *dev,
@@ -1890,7 +1939,8 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = {
	{},
};

static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev)
static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev,
						   const struct ocelot_pinctrl *info)
{
	void __iomem *base;

@@ -1898,7 +1948,7 @@ static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev)
		.reg_bits = 32,
		.val_bits = 32,
		.reg_stride = 4,
		.max_register = 32,
		.max_register = info->desc->npins * 4,
		.name = "pincfg",
	};

@@ -1913,6 +1963,7 @@ static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev)

static int ocelot_pinctrl_probe(struct platform_device *pdev)
{
	const struct ocelot_match_data *data;
	struct device *dev = &pdev->dev;
	struct ocelot_pinctrl *info;
	struct reset_control *reset;
@@ -1929,7 +1980,16 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
	if (!info)
		return -ENOMEM;

	info->desc = (struct pinctrl_desc *)device_get_match_data(dev);
	data = device_get_match_data(dev);
	if (!data)
		return -EINVAL;

	info->desc = devm_kmemdup(dev, &data->desc, sizeof(*info->desc),
				  GFP_KERNEL);
	if (!info->desc)
		return -ENOMEM;

	info->pincfg_data = &data->pincfg_data;

	reset = devm_reset_control_get_optional_shared(dev, "switch");
	if (IS_ERR(reset))
@@ -1956,7 +2016,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)

	/* Pinconf registers */
	if (info->desc->confops) {
		pincfg = ocelot_pinctrl_create_pincfg(pdev);
		pincfg = ocelot_pinctrl_create_pincfg(pdev, info);
		if (IS_ERR(pincfg))
			dev_dbg(dev, "Failed to create pincfg regmap\n");
		else
+2 −0
Original line number Diff line number Diff line
@@ -266,6 +266,8 @@ static int ralink_pinctrl_pins(struct ralink_priv *p)
						p->func[i]->pin_count,
						sizeof(int),
						GFP_KERNEL);
		if (!p->func[i]->pins)
			return -ENOMEM;
		for (j = 0; j < p->func[i]->pin_count; j++)
			p->func[i]->pins[j] = p->func[i]->pin_first + j;

Loading