From 96147db1e1dff83679e71ac92193cbcab761a14c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 18 Sep 2018 18:36:21 +0300 Subject: [PATCH] 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 Signed-off-by: Mika Westerberg Tested-by: Rajat Jain Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-intel.c | 175 ++++++++++++++------------ 1 file changed, 95 insertions(+), 80 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 62b009b27eda..ec8dafc94694 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -747,86 +747,6 @@ static const struct pinctrl_desc intel_pinctrl_desc = { .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 @@ -872,6 +792,101 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset, 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);