FROMLIST: pinctrl: intel: Do pin translation in other GPIO operations as well
For some reason I thought GPIOLIB handles translation from GPIO ranges
to pinctrl pins but it turns out not to be the case. This means that
when GPIOs operations are performed for a pin controller having a custom
GPIO base such as Cannon Lake and Ice Lake incorrect pin number gets
used internally.
Fix this in the same way we did for lock/unlock IRQ operations and
translate the GPIO number to pin before using it.
Fixes: a60eac3239f0 ("pinctrl: intel: Allow custom GPIO base for pad groups")
Reported-by: Rajat Jain <rajatja@google.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
(am from https://lore.kernel.org/patchwork/patch/988007/)
BUG=b:112056767
TEST=verify that the driver starts writing to correct offset.
Change-Id: I6f7621351e53826f40a95028e1cf9e62b6417062
Reviewed-on: https://chromium-review.googlesource.com/1232322
Tested-by: Rajat Jain <rajatja@chromium.org>
Tested-by: Casey G Bowman <casey.g.bowman@intel.com>
Reviewed-by: Matthew S Atwood <matthew.s.atwood@intel.corp-partner.google.com>
Reviewed-by: Dmitry Torokhov <dtor@chromium.org>
Commit-Queue: Rajat Jain <rajatja@chromium.org>
Trybot-Ready: Rajat Jain <rajatja@chromium.org>
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 5fd6b07..fbd1639 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -750,86 +750,6 @@
.owner = THIS_MODULE,
};
-static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
- void __iomem *reg;
- u32 padcfg0;
-
- reg = intel_get_padcfg(pctrl, offset, PADCFG0);
- if (!reg)
- return -EINVAL;
-
- padcfg0 = readl(reg);
- if (!(padcfg0 & PADCFG0_GPIOTXDIS))
- return !!(padcfg0 & PADCFG0_GPIOTXSTATE);
-
- return !!(padcfg0 & PADCFG0_GPIORXSTATE);
-}
-
-static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
- unsigned long flags;
- void __iomem *reg;
- u32 padcfg0;
-
- reg = intel_get_padcfg(pctrl, offset, PADCFG0);
- if (!reg)
- return;
-
- raw_spin_lock_irqsave(&pctrl->lock, flags);
- padcfg0 = readl(reg);
- if (value)
- padcfg0 |= PADCFG0_GPIOTXSTATE;
- else
- padcfg0 &= ~PADCFG0_GPIOTXSTATE;
- writel(padcfg0, reg);
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
-static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
-{
- struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
- void __iomem *reg;
- u32 padcfg0;
-
- reg = intel_get_padcfg(pctrl, offset, PADCFG0);
- if (!reg)
- return -EINVAL;
-
- padcfg0 = readl(reg);
-
- if (padcfg0 & PADCFG0_PMODE_MASK)
- return -EINVAL;
-
- return !!(padcfg0 & PADCFG0_GPIOTXDIS);
-}
-
-static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_gpio_direction_input(chip->base + offset);
-}
-
-static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- intel_gpio_set(chip, offset, value);
- return pinctrl_gpio_direction_output(chip->base + offset);
-}
-
-static const struct gpio_chip intel_gpio_chip = {
- .owner = THIS_MODULE,
- .request = gpiochip_generic_request,
- .free = gpiochip_generic_free,
- .get_direction = intel_gpio_get_direction,
- .direction_input = intel_gpio_direction_input,
- .direction_output = intel_gpio_direction_output,
- .get = intel_gpio_get,
- .set = intel_gpio_set,
- .set_config = gpiochip_generic_config,
-};
-
/**
* intel_gpio_to_pin() - Translate from GPIO offset to pin number
* @pctrl: Pinctrl structure
@@ -875,6 +795,101 @@
return -EINVAL;
}
+static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
+ void __iomem *reg;
+ u32 padcfg0;
+ int pin;
+
+ pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
+ if (pin < 0)
+ return -EINVAL;
+
+ reg = intel_get_padcfg(pctrl, pin, PADCFG0);
+ if (!reg)
+ return -EINVAL;
+
+ padcfg0 = readl(reg);
+ if (!(padcfg0 & PADCFG0_GPIOTXDIS))
+ return !!(padcfg0 & PADCFG0_GPIOTXSTATE);
+
+ return !!(padcfg0 & PADCFG0_GPIORXSTATE);
+}
+
+static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
+ unsigned long flags;
+ void __iomem *reg;
+ u32 padcfg0;
+ int pin;
+
+ pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
+ if (pin < 0)
+ return;
+
+ reg = intel_get_padcfg(pctrl, pin, PADCFG0);
+ if (!reg)
+ return;
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
+ padcfg0 = readl(reg);
+ if (value)
+ padcfg0 |= PADCFG0_GPIOTXSTATE;
+ else
+ padcfg0 &= ~PADCFG0_GPIOTXSTATE;
+ writel(padcfg0, reg);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
+ void __iomem *reg;
+ u32 padcfg0;
+ int pin;
+
+ pin = intel_gpio_to_pin(pctrl, offset, NULL, NULL);
+ if (pin < 0)
+ return -EINVAL;
+
+ reg = intel_get_padcfg(pctrl, pin, PADCFG0);
+ if (!reg)
+ return -EINVAL;
+
+ padcfg0 = readl(reg);
+
+ if (padcfg0 & PADCFG0_PMODE_MASK)
+ return -EINVAL;
+
+ return !!(padcfg0 & PADCFG0_GPIOTXDIS);
+}
+
+static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ intel_gpio_set(chip, offset, value);
+ return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static const struct gpio_chip intel_gpio_chip = {
+ .owner = THIS_MODULE,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
+ .get_direction = intel_gpio_get_direction,
+ .direction_input = intel_gpio_direction_input,
+ .direction_output = intel_gpio_direction_output,
+ .get = intel_gpio_get,
+ .set = intel_gpio_set,
+ .set_config = gpiochip_generic_config,
+};
+
static int intel_gpio_irq_reqres(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);