[PATCH 02/22] gpio: davinci: Redesign driver to accommodate ngpios in one gpio chip

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 = &regs->set_data;
-		chips[i].clr_data = &regs->clr_data;
-		chips[i].in_data = &regs->in_data;
-
-		gpiochip_add(gc);
-	}
+	gpiochip_add(gc);
 
 	return 0;
 }
-- 
2.39.2





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux