[PATCH 02/22] gpio: davinci: Redesign driver to accommodate ngpios in one gpio chip
Sascha Hauer
s.hauer at pengutronix.de
Thu Aug 3 03:49:43 PDT 2023
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 at ti.com>
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 at pengutronix.de>
---
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
More information about the barebox
mailing list