Commit 25aadbd2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:

 - Fix an issue in the AMD driver for the UART0 group

 - Fix a glitch issue in the Baytrail pin controller

* tag 'pinctrl-v5.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(..., GPIOD_OUT_HIGH)
  pinctrl: amd: fix npins for uart0 in kerncz_groups
parents 3f883432 f8e99dde
Loading
Loading
Loading
Loading
+53 −14
Original line number Diff line number Diff line
@@ -800,6 +800,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
	pm_runtime_put(vg->dev);
}

static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg,
				      unsigned int offset)
{
	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);

	/*
	 * Before making any direction modifications, do a check if gpio is set
	 * for direct IRQ. On Bay Trail, setting GPIO to output does not make
	 * sense, so let's at least inform the caller before they shoot
	 * 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");
}

static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
				  struct pinctrl_gpio_range *range,
				  unsigned int offset,
@@ -807,7 +822,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
{
	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
	unsigned long flags;
	u32 value;

@@ -817,14 +831,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
	value &= ~BYT_DIR_MASK;
	if (input)
		value |= BYT_OUTPUT_EN;
	else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
		/*
		 * Before making any direction modifications, do a check if gpio
		 * is set for direct IRQ.  On baytrail, setting GPIO to output
		 * does not make sense, so let's at least inform the caller before
		 * they shoot themselves in the foot.
		 */
		dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
	else
		byt_gpio_direct_irq_check(vg, offset);

	writel(value, val_reg);

@@ -1165,19 +1173,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)

static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
	return pinctrl_gpio_direction_input(chip->base + offset);
	struct intel_pinctrl *vg = gpiochip_get_data(chip);
	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
	unsigned long flags;
	u32 reg;

	raw_spin_lock_irqsave(&byt_lock, flags);

	reg = readl(val_reg);
	reg &= ~BYT_DIR_MASK;
	reg |= BYT_OUTPUT_EN;
	writel(reg, val_reg);

	raw_spin_unlock_irqrestore(&byt_lock, flags);
	return 0;
}

/*
 * Note despite the temptation this MUST NOT be converted into a call to
 * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
 * MUST be done as a single BYT_VAL_REG register write.
 * See the commit message of the commit adding this comment for details.
 */
static int byt_gpio_direction_output(struct gpio_chip *chip,
				     unsigned int offset, int value)
{
	int ret = pinctrl_gpio_direction_output(chip->base + offset);
	struct intel_pinctrl *vg = gpiochip_get_data(chip);
	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
	unsigned long flags;
	u32 reg;

	if (ret)
		return ret;
	raw_spin_lock_irqsave(&byt_lock, flags);

	byt_gpio_set(chip, offset, value);
	byt_gpio_direct_irq_check(vg, offset);

	reg = readl(val_reg);
	reg &= ~BYT_DIR_MASK;
	if (value)
		reg |= BYT_LEVEL;
	else
		reg &= ~BYT_LEVEL;

	writel(reg, val_reg);

	raw_spin_unlock_irqrestore(&byt_lock, flags);
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ static const struct amd_pingroup kerncz_groups[] = {
	{
		.name = "uart0",
		.pins = uart0_pins,
		.npins = 9,
		.npins = 5,
	},
	{
		.name = "uart1",