gpio/generic: initialize basic_mmio_gpio shadow variables properly
authorShawn Guo <shawn.guo@linaro.org>
Sat, 19 May 2012 13:34:58 +0000 (21:34 +0800)
committerGrant Likely <grant.likely@secretlab.ca>
Sat, 19 May 2012 18:17:35 +0000 (12:17 -0600)
It fixes the issue in gpio-generic that commit fb14921 (gpio/mxc: add
missing initialization of basic_mmio_gpio shadow variables) manged to
fix in gpio-mxc driver, so that other platform specific drivers do not
suffer from the same problem over and over again.

Changes since v1:
* Turn the last parameter of bgpio_init() "bool big_endian" into
  "unsigned long flags" and give those really quirky hardwares a
  chance to tell that reg_set and reg_dir are unreadable.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
[grant.likely: Fix big-endian usage to explicitly set BBGPIOF_BIG_ENDIAN]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-generic.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-sodaville.c
include/linux/basic_mmio_gpio.h

index 776b772523e5039f81440d412397aaabac49c544..9fe5b8fe9be895de23f4f31b7315b49d7a37c6e0 100644 (file)
@@ -325,7 +325,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
        void __iomem *dir =  mmio_base + bank->dir;
        int err;
 
-       err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
+       err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, 0);
        if (err)
                return err;
 
index e38dd0c31973f52bc8e8be45937ae3f8a2709c41..82e2e4fe599ebd6934fba12494c5d1206fdb1270 100644 (file)
@@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(bgpio_remove);
 int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
               unsigned long sz, void __iomem *dat, void __iomem *set,
               void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
-              bool big_endian)
+              unsigned long flags)
 {
        int ret;
 
@@ -385,7 +385,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
        if (ret)
                return ret;
 
-       ret = bgpio_setup_accessors(dev, bgc, big_endian);
+       ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN);
        if (ret)
                return ret;
 
@@ -394,6 +394,11 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
                return ret;
 
        bgc->data = bgc->read_reg(bgc->reg_dat);
+       if (bgc->gc.set == bgpio_set_set &&
+                       !(flags & BGPIOF_UNREADABLE_REG_SET))
+               bgc->data = bgc->read_reg(bgc->reg_set);
+       if (bgc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR))
+               bgc->dir = bgc->read_reg(bgc->reg_dir);
 
        return ret;
 }
@@ -449,7 +454,7 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
        void __iomem *dirout;
        void __iomem *dirin;
        unsigned long sz;
-       bool be;
+       unsigned long flags = 0;
        int err;
        struct bgpio_chip *bgc;
        struct bgpio_pdata *pdata = dev_get_platdata(dev);
@@ -480,13 +485,14 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be");
+       if (!strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"))
+               flags |= BGPIOF_BIG_ENDIAN;
 
        bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
        if (!bgc)
                return -ENOMEM;
 
-       err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be);
+       err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, flags);
        if (err)
                return err;
 
index e79147634573683a27b46953b0a90e2d995a5a5f..c337143b18f8f97d1fa80c61d84cfe9149b75aff 100644 (file)
@@ -417,7 +417,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        err = bgpio_init(&port->bgc, &pdev->dev, 4,
                         port->base + GPIO_PSR,
                         port->base + GPIO_DR, NULL,
-                        port->base + GPIO_GDIR, NULL, false);
+                        port->base + GPIO_GDIR, NULL, 0);
        if (err)
                goto out_iounmap;
 
index 385c58e8405b7d4c5ebbd4eafbf92e637e034651..b4136501abd82e43d6752deb2265767bf97ee60a 100644 (file)
@@ -244,7 +244,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
        err = bgpio_init(&port->bgc, &pdev->dev, 4,
                         port->base + PINCTRL_DIN(port->id),
                         port->base + PINCTRL_DOUT(port->id), NULL,
-                        port->base + PINCTRL_DOE(port->id), NULL, false);
+                        port->base + PINCTRL_DOE(port->id), NULL, 0);
        if (err)
                goto out_iounmap;
 
index 820209c420e300ceb47979ae6a121db8f55cdf03..9d9891f7a607f44c69d5b2598461ba96efb3a616 100644 (file)
@@ -224,7 +224,7 @@ static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
 
        ret = bgpio_init(&sd->bgpio, &pdev->dev, 4,
                        sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR,
-                       NULL, sd->gpio_pub_base + GPOER, NULL, false);
+                       NULL, sd->gpio_pub_base + GPOER, NULL, 0);
        if (ret)
                goto unmap;
        sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS;
index feb9121967458e8c99515389d2923cb573547535..1c504ca5bdb344154dc69b0c6068c3494bdc05da 100644 (file)
@@ -67,6 +67,10 @@ int bgpio_remove(struct bgpio_chip *bgc);
 int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
               unsigned long sz, void __iomem *dat, void __iomem *set,
               void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
-              bool big_endian);
+              unsigned long flags);
+
+#define BGPIOF_BIG_ENDIAN              BIT(0)
+#define BGPIOF_UNREADABLE_REG_SET      BIT(1) /* reg_set is unreadable */
+#define BGPIOF_UNREADABLE_REG_DIR      BIT(2) /* reg_dir is unreadable */
 
 #endif /* __BASIC_MMIO_GPIO_H */