The davinci GPIO devices have up to 144 GPIOs per chip. Current driver creates one chip for every 32 GPIOs in a controller. With this translation of DT GPIO handles into GPIO chip/numbers does not work correctly. This patch fixes that by registering all GPIOs of a controller in a single GPIO chip. Based on Linux commit: commit b5cf3fd827d2e11355c126b44ea625650ebf4d39 Author: Keerthy <j-keerthy@xxxxxx> Date: Fri Jan 13 09:50:12 2017 +0530 gpio: davinci: Redesign driver to accommodate ngpios in one gpio chip Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/gpio/gpio-davinci.c | 68 ++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 6a839fb5cd..841a06e4a0 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -30,40 +30,42 @@ struct davinci_gpio_controller { struct gpio_chip chip; /* Serialize access to GPIO registers */ void __iomem *regs; - void __iomem *set_data; - void __iomem *clr_data; - void __iomem *in_data; }; #define chip2controller(chip) \ container_of(chip, struct davinci_gpio_controller, chip) -static struct davinci_gpio_regs __iomem *gpio2regs(void __iomem *gpio_base, - unsigned gpio) +static struct davinci_gpio_regs __iomem *gpio2regs(struct davinci_gpio_controller *d, + unsigned gpio) { void __iomem *ptr; if (gpio < 32 * 1) - ptr = gpio_base + 0x10; + ptr = d->regs + 0x10; else if (gpio < 32 * 2) - ptr = gpio_base + 0x38; + ptr = d->regs + 0x38; else if (gpio < 32 * 3) - ptr = gpio_base + 0x60; + ptr = d->regs + 0x60; else if (gpio < 32 * 4) - ptr = gpio_base + 0x88; + ptr = d->regs + 0x88; else if (gpio < 32 * 5) - ptr = gpio_base + 0xb0; + ptr = d->regs + 0xb0; else ptr = NULL; return ptr; } +static inline u32 __gpio_mask(unsigned gpio) +{ + return 1 << (gpio % 32); +} + static int davinci_get_direction(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g = gpio2regs(d, offset); - return ((readl_relaxed(&g->dir)) & (1 << offset)) ? + return ((readl_relaxed(&g->dir)) & __gpio_mask(offset)) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; } @@ -71,9 +73,9 @@ static inline int __davinci_direction(struct gpio_chip *chip, unsigned offset, bool out, int value) { struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g = gpio2regs(d, offset); u32 temp; - u32 mask = 1 << offset; + u32 mask = __gpio_mask(offset); temp = readl_relaxed(&g->dir); if (out) { @@ -108,9 +110,9 @@ davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g = gpio2regs(d, offset); - return ((1 << offset) & readl_relaxed(&g->in_data)) ? 1 : 0; + return (__gpio_mask(offset) & readl_relaxed(&g->in_data)) ? 1 : 0; } /* @@ -120,9 +122,9 @@ static void davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct davinci_gpio_controller *d = chip2controller(chip); - struct davinci_gpio_regs __iomem *g = d->regs; + struct davinci_gpio_regs __iomem *g = gpio2regs(d, offset); - writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data); + writel_relaxed(__gpio_mask(offset), value ? &g->set_data : &g->clr_data); } static struct gpio_ops davinci_gpio_ops = { @@ -139,9 +141,9 @@ static int davinci_gpio_probe(struct device *dev) void __iomem *gpio_base; int ret; u32 val; - int i, base; unsigned ngpio; struct davinci_gpio_controller *chips; + struct gpio_chip *gc; ret = of_property_read_u32(dev->of_node, "ti,ngpio", &val); if (ret) { @@ -154,7 +156,7 @@ static int davinci_gpio_probe(struct device *dev) if (WARN_ON(ARCH_NR_GPIOS < ngpio)) ngpio = ARCH_NR_GPIOS; - chips = xzalloc((ngpio / 32 + 1) * sizeof(*chips)); + chips = xzalloc(sizeof(*chips)); iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) { @@ -163,27 +165,15 @@ static int davinci_gpio_probe(struct device *dev) } gpio_base = IOMEM(iores->start); - for (i = 0, base = 0; base < ngpio; i++, base += 32) { - struct davinci_gpio_regs __iomem *regs; - struct gpio_chip *gc; + gc = &chips->chip; + gc->ops = &davinci_gpio_ops; + gc->dev = dev; + gc->ngpio = ngpio; + gc->base = -1; - gc = &chips[i].chip; - gc->ops = &davinci_gpio_ops; + chips->regs = gpio_base; - gc->dev = dev; - gc->base = base; - gc->ngpio = ngpio - base; - if (gc->ngpio > 32) - gc->ngpio = 32; - - regs = gpio2regs(gpio_base, base); - chips[i].regs = regs; - chips[i].set_data = ®s->set_data; - chips[i].clr_data = ®s->clr_data; - chips[i].in_data = ®s->in_data; - - gpiochip_add(gc); - } + gpiochip_add(gc); return 0; } -- 2.39.2