Commit a4e6f95a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:
 "Some few pin control fixes for the v5.15 kernel cycle. The most
  critical is the AMD fixes.

   - Fix wakeup interrupts in the AMD driver affecting AMD laptops.

   - Fix parent irqspec translation in the Qualcomm SPMI GPIO driver.

   - Fix deferred probe handling in the Rockchip driver, this is a
     stopgap solution while we look for something more elegant.

   - Add PM suspend callbacks to the Qualcomm SC7280 driver.

   - Some minor doc fix (should have come in earlier, sorry)"

* tag 'pinctrl-v5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: qcom: sc7280: Add PM suspend callbacks
  gpio/rockchip: fetch deferred output settings on probe
  pinctrl/rockchip: add a queue for deferred pin output settings on probe
  pinctrl: qcom: spmi-gpio: correct parent irqspec translation
  pinctrl: amd: Handle wake-up interrupt
  pinctrl: amd: Add irq field data
  pinctrl: core: Remove duplicated word from devm_pinctrl_unregister()
parents 62da74a7 28406a21
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -689,6 +689,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
	struct device_node *pctlnp = of_get_parent(np);
	struct pinctrl_dev *pctldev = NULL;
	struct rockchip_pin_bank *bank = NULL;
	struct rockchip_pin_output_deferred *cfg;
	static int gpio;
	int id, ret;

@@ -716,12 +717,33 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	/*
	 * Prevent clashes with a deferred output setting
	 * being added right at this moment.
	 */
	mutex_lock(&bank->deferred_lock);

	ret = rockchip_gpiolib_register(bank);
	if (ret) {
		clk_disable_unprepare(bank->clk);
		mutex_unlock(&bank->deferred_lock);
		return ret;
	}

	while (!list_empty(&bank->deferred_output)) {
		cfg = list_first_entry(&bank->deferred_output,
				       struct rockchip_pin_output_deferred, head);
		list_del(&cfg->head);

		ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg);
		if (ret)
			dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg);

		kfree(cfg);
	}

	mutex_unlock(&bank->deferred_lock);

	platform_set_drvdata(pdev, bank);
	dev_info(dev, "probed %pOF\n", np);

+1 −1
Original line number Diff line number Diff line
@@ -2306,7 +2306,7 @@ EXPORT_SYMBOL_GPL(devm_pinctrl_register_and_init);

/**
 * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister().
 * @dev: device for which which resource was allocated
 * @dev: device for which resource was allocated
 * @pctldev: the pinctrl device to unregister.
 */
void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev)
+14 −5
Original line number Diff line number Diff line
@@ -445,6 +445,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
	u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
	int err;

	raw_spin_lock_irqsave(&gpio_dev->lock, flags);
	pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
@@ -457,6 +458,15 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
	writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
	raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);

	if (on)
		err = enable_irq_wake(gpio_dev->irq);
	else
		err = disable_irq_wake(gpio_dev->irq);

	if (err)
		dev_err(&gpio_dev->pdev->dev, "failed to %s wake-up interrupt\n",
			on ? "enable" : "disable");

	return 0;
}

@@ -902,7 +912,6 @@ static struct pinctrl_desc amd_pinctrl_desc = {
static int amd_gpio_probe(struct platform_device *pdev)
{
	int ret = 0;
	int irq_base;
	struct resource *res;
	struct amd_gpio *gpio_dev;
	struct gpio_irq_chip *girq;
@@ -925,9 +934,9 @@ static int amd_gpio_probe(struct platform_device *pdev)
	if (!gpio_dev->base)
		return -ENOMEM;

	irq_base = platform_get_irq(pdev, 0);
	if (irq_base < 0)
		return irq_base;
	gpio_dev->irq = platform_get_irq(pdev, 0);
	if (gpio_dev->irq < 0)
		return gpio_dev->irq;

#ifdef CONFIG_PM_SLEEP
	gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
@@ -987,7 +996,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
		goto out2;
	}

	ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler,
	ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
			       IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
	if (ret)
		goto out2;
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ struct amd_gpio {
	struct resource         *res;
	struct platform_device  *pdev;
	u32			*saved_regs;
	int			irq;
};

/*  KERNCZ configuration*/
+67 −0
Original line number Diff line number Diff line
@@ -2092,6 +2092,23 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
	return false;
}

static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank,
					 unsigned int pin, u32 arg)
{
	struct rockchip_pin_output_deferred *cfg;

	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
	if (!cfg)
		return -ENOMEM;

	cfg->pin = pin;
	cfg->arg = arg;

	list_add_tail(&cfg->head, &bank->deferred_output);

	return 0;
}

/* set the pin config settings for a specified pin */
static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
				unsigned long *configs, unsigned num_configs)
@@ -2136,6 +2153,22 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
			if (rc != RK_FUNC_GPIO)
				return -EINVAL;

			/*
			 * Check for gpio driver not being probed yet.
			 * The lock makes sure that either gpio-probe has completed
			 * or the gpio driver hasn't probed yet.
			 */
			mutex_lock(&bank->deferred_lock);
			if (!gpio || !gpio->direction_output) {
				rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg);
				mutex_unlock(&bank->deferred_lock);
				if (rc)
					return rc;

				break;
			}
			mutex_unlock(&bank->deferred_lock);

			rc = gpio->direction_output(gpio, pin - bank->pin_base,
						    arg);
			if (rc)
@@ -2204,6 +2237,11 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
		if (rc != RK_FUNC_GPIO)
			return -EINVAL;

		if (!gpio || !gpio->get) {
			arg = 0;
			break;
		}

		rc = gpio->get(gpio, pin - bank->pin_base);
		if (rc < 0)
			return rc;
@@ -2450,6 +2488,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
						pin_bank->name, pin);
			pdesc++;
		}

		INIT_LIST_HEAD(&pin_bank->deferred_output);
		mutex_init(&pin_bank->deferred_lock);
	}

	ret = rockchip_pinctrl_parse_dt(pdev, info);
@@ -2716,6 +2757,31 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
	return 0;
}

static int rockchip_pinctrl_remove(struct platform_device *pdev)
{
	struct rockchip_pinctrl *info = platform_get_drvdata(pdev);
	struct rockchip_pin_bank *bank;
	struct rockchip_pin_output_deferred *cfg;
	int i;

	of_platform_depopulate(&pdev->dev);

	for (i = 0; i < info->ctrl->nr_banks; i++) {
		bank = &info->ctrl->pin_banks[i];

		mutex_lock(&bank->deferred_lock);
		while (!list_empty(&bank->deferred_output)) {
			cfg = list_first_entry(&bank->deferred_output,
					       struct rockchip_pin_output_deferred, head);
			list_del(&cfg->head);
			kfree(cfg);
		}
		mutex_unlock(&bank->deferred_lock);
	}

	return 0;
}

static struct rockchip_pin_bank px30_pin_banks[] = {
	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
					     IOMUX_SOURCE_PMU,
@@ -3175,6 +3241,7 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {

static struct platform_driver rockchip_pinctrl_driver = {
	.probe		= rockchip_pinctrl_probe,
	.remove		= rockchip_pinctrl_remove,
	.driver = {
		.name	= "rockchip-pinctrl",
		.pm = &rockchip_pinctrl_dev_pm_ops,
Loading