summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-generic.c')
-rw-r--r--drivers/gpio/gpio-generic.c473
1 files changed, 327 insertions, 146 deletions
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index e4c4f39b62..1902c83960 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -1,74 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2008 MontaVista Software, Inc.
+// SPDX-FileCopyrightText: 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+
/*
- * Generic driver for memory-mapped GPIO controllers.
- *
- * Based on linux driver by:
- * Copyright 2008 MontaVista Software, Inc.
- * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Generic driver for memory-mapped GPIO controllers, based on the Linux driver.
*/
#include <init.h>
-#include <malloc.h>
#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <errno.h>
#include <linux/log2.h>
-#include <linux/err.h>
+#include <linux/ioport.h>
+#include <io.h>
#include <linux/basic_mmio_gpio.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <driver.h>
+#include <of.h>
+#include <of_device.h>
-static void bgpio_write8(void __iomem *reg, unsigned int data)
+static void bgpio_write8(void __iomem *reg, unsigned long data)
{
writeb(data, reg);
}
-static unsigned int bgpio_read8(void __iomem *reg)
+static unsigned long bgpio_read8(void __iomem *reg)
{
return readb(reg);
}
-static void bgpio_write16(void __iomem *reg, unsigned int data)
+static void bgpio_write16(void __iomem *reg, unsigned long data)
{
writew(data, reg);
}
-static unsigned int bgpio_read16(void __iomem *reg)
+static unsigned long bgpio_read16(void __iomem *reg)
{
return readw(reg);
}
-static void bgpio_write32(void __iomem *reg, unsigned int data)
+static void bgpio_write32(void __iomem *reg, unsigned long data)
{
writel(data, reg);
}
-static unsigned int bgpio_read32(void __iomem *reg)
+static unsigned long bgpio_read32(void __iomem *reg)
{
return readl(reg);
}
-static unsigned int bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
+#if BITS_PER_LONG >= 64
+static void bgpio_write64(void __iomem *reg, unsigned long data)
+{
+ writeq(data, reg);
+}
+
+static unsigned long bgpio_read64(void __iomem *reg)
+{
+ return readq(reg);
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+static void bgpio_write16be(void __iomem *reg, unsigned long data)
+{
+ iowrite16be(data, reg);
+}
+
+static unsigned long bgpio_read16be(void __iomem *reg)
{
- return 1 << pin;
+ return ioread16be(reg);
}
-static unsigned int bgpio_pin2mask_be(struct bgpio_chip *bgc, unsigned int pin)
+static void bgpio_write32be(void __iomem *reg, unsigned long data)
{
- return 1 << (bgc->bits - 1 - pin);
+ iowrite32be(data, reg);
+}
+
+static unsigned long bgpio_read32be(void __iomem *reg)
+{
+ return ioread32be(reg);
+}
+
+static unsigned long bgpio_line2mask(struct bgpio_chip *bgc, unsigned int line)
+{
+ if (bgc->be_bits)
+ return BIT(bgc->bits - 1 - line);
+ return BIT(line);
+}
+
+static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ unsigned long pinmask = bgpio_line2mask(bgc, gpio);
+ bool dir = !!(bgc->dir & pinmask);
+
+ if (dir)
+ return !!(bgc->read_reg(bgc->reg_set) & pinmask);
+ else
+ return !!(bgc->read_reg(bgc->reg_dat) & pinmask);
}
static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ return !!(bgc->read_reg(bgc->reg_dat) & bgpio_line2mask(bgc, gpio));
+}
- return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
+static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
+{
}
static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- unsigned int mask = bgc->pin2mask(bgc, gpio);
+ unsigned long mask = bgpio_line2mask(bgc, gpio);
if (val)
bgc->data |= mask;
@@ -82,7 +131,7 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
int val)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- unsigned int mask = bgc->pin2mask(bgc, gpio);
+ unsigned long mask = bgpio_line2mask(bgc, gpio);
if (val)
bgc->write_reg(bgc->reg_set, mask);
@@ -93,7 +142,7 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- unsigned int mask = bgc->pin2mask(bgc, gpio);
+ unsigned long mask = bgpio_line2mask(bgc, gpio);
if (val)
bgc->data |= mask;
@@ -108,6 +157,12 @@ static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
return 0;
}
+static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
+ int val)
+{
+ return -EINVAL;
+}
+
static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
int val)
{
@@ -120,69 +175,115 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- bgc->dir &= ~bgc->pin2mask(bgc, gpio);
- bgc->write_reg(bgc->reg_dir, bgc->dir);
+ bgc->dir &= ~bgpio_line2mask(bgc, gpio);
+
+ if (bgc->reg_dir_in)
+ bgc->write_reg(bgc->reg_dir_in, ~bgc->dir);
+ if (bgc->reg_dir_out)
+ bgc->write_reg(bgc->reg_dir_out, bgc->dir);
return 0;
}
-static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- gc->ops->set(gc, gpio, val);
+ /* Return 0 if output, 1 if input */
+ if (bgc->dir_unreadable) {
+ if (bgc->dir & bgpio_line2mask(bgc, gpio))
+ return GPIOF_DIR_OUT;
+ return GPIOF_DIR_IN;
+ }
- bgc->dir |= bgc->pin2mask(bgc, gpio);
- bgc->write_reg(bgc->reg_dir, bgc->dir);
+ if (bgc->reg_dir_out) {
+ if (bgc->read_reg(bgc->reg_dir_out) & bgpio_line2mask(bgc, gpio))
+ return GPIOF_DIR_OUT;
+ return GPIOF_DIR_IN;
+ }
- return 0;
+ if (bgc->reg_dir_in)
+ if (!(bgc->read_reg(bgc->reg_dir_in) & bgpio_line2mask(bgc, gpio)))
+ return GPIOF_DIR_OUT;
+
+ return GPIOF_DIR_IN;
}
-static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
+static void bgpio_dir_out(struct bgpio_chip *bgc, unsigned int gpio, int val)
{
- struct bgpio_chip *bgc = to_bgpio_chip(gc);
-
- bgc->dir |= bgc->pin2mask(bgc, gpio);
- bgc->write_reg(bgc->reg_dir, bgc->dir);
+ bgc->dir |= bgpio_line2mask(bgc, gpio);
- return 0;
+ if (bgc->reg_dir_in)
+ bgc->write_reg(bgc->reg_dir_in, ~bgc->dir);
+ if (bgc->reg_dir_out)
+ bgc->write_reg(bgc->reg_dir_out, bgc->dir);
}
-static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
+static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio,
+ int val)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ bgpio_dir_out(bgc, gpio, val);
gc->ops->set(gc, gpio, val);
+ return 0;
+}
- bgc->dir &= ~bgc->pin2mask(bgc, gpio);
- bgc->write_reg(bgc->reg_dir, bgc->dir);
+static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio,
+ int val)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ gc->ops->set(gc, gpio, val);
+ bgpio_dir_out(bgc, gpio, val);
return 0;
}
-static int bgpio_setup_accessors(struct device_d *dev, struct bgpio_chip *bgc,
- bool be)
+static int bgpio_setup_accessors(struct device *dev,
+ struct bgpio_chip *bgc,
+ bool byte_be)
{
+
switch (bgc->bits) {
case 8:
bgc->read_reg = bgpio_read8;
bgc->write_reg = bgpio_write8;
break;
case 16:
- bgc->read_reg = bgpio_read16;
- bgc->write_reg = bgpio_write16;
+ if (byte_be) {
+ bgc->read_reg = bgpio_read16be;
+ bgc->write_reg = bgpio_write16be;
+ } else {
+ bgc->read_reg = bgpio_read16;
+ bgc->write_reg = bgpio_write16;
+ }
break;
case 32:
- bgc->read_reg = bgpio_read32;
- bgc->write_reg = bgpio_write32;
+ if (byte_be) {
+ bgc->read_reg = bgpio_read32be;
+ bgc->write_reg = bgpio_write32be;
+ } else {
+ bgc->read_reg = bgpio_read32;
+ bgc->write_reg = bgpio_write32;
+ }
+ break;
+#if BITS_PER_LONG >= 64
+ case 64:
+ if (byte_be) {
+ dev_err(dev,
+ "64 bit big endian byte order unsupported\n");
+ return -EINVAL;
+ } else {
+ bgc->read_reg = bgpio_read64;
+ bgc->write_reg = bgpio_write64;
+ }
break;
+#endif /* BITS_PER_LONG >= 64 */
default:
- dev_err(dev, "Unsupported data width %u bits\n", bgc->bits);
+ dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
return -EINVAL;
}
- bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
-
return 0;
}
@@ -193,7 +294,7 @@ static int bgpio_setup_accessors(struct device_d *dev, struct bgpio_chip *bgc,
* - single input/output register resource (named "dat").
* - set/clear pair (named "set" and "clr").
* - single output register resource and single input resource ("set" and
- * dat").
+ * dat").
*
* For the single output register, this drives a 1 by setting a bit and a zero
* by clearing a bit. For the set clr pair, this drives a 1 by setting a bit
@@ -211,126 +312,214 @@ static int bgpio_setup_accessors(struct device_d *dev, struct bgpio_chip *bgc,
static int bgpio_setup_io(struct bgpio_chip *bgc,
void __iomem *dat,
void __iomem *set,
- void __iomem *clr)
+ void __iomem *clr,
+ unsigned long flags)
{
- if (!dat)
- return -EINVAL;
+ struct gpio_ops *ops = bgc->gc.ops;
bgc->reg_dat = dat;
+ if (!bgc->reg_dat)
+ return -EINVAL;
if (set && clr) {
bgc->reg_set = set;
bgc->reg_clr = clr;
- bgc->gc.ops->set = bgpio_set_with_clear;
+ ops->set = bgpio_set_with_clear;
} else if (set && !clr) {
bgc->reg_set = set;
- bgc->gc.ops->set = bgpio_set_set;
- } else
- bgc->gc.ops->set = bgpio_set;
+ ops->set = bgpio_set_set;
+ } else if (flags & BGPIOF_NO_OUTPUT) {
+ ops->set = bgpio_set_none;
+ } else {
+ ops->set = bgpio_set;
+ }
- bgc->gc.ops->get = bgpio_get;
+ if (!(flags & BGPIOF_UNREADABLE_REG_SET) && (flags & BGPIOF_READ_OUTPUT_REG_SET))
+ ops->get = bgpio_get_set;
+ else
+ ops->get = bgpio_get;
return 0;
}
static int bgpio_setup_direction(struct bgpio_chip *bgc,
void __iomem *dirout,
- void __iomem *dirin)
+ void __iomem *dirin,
+ unsigned long flags)
{
- if (dirout && dirin)
- return -EINVAL;
-
- if (dirout) {
- bgc->reg_dir = dirout;
- bgc->gc.ops->direction_output = bgpio_dir_out;
- bgc->gc.ops->direction_input = bgpio_dir_in;
- } else if (dirin) {
- bgc->reg_dir = dirin;
- bgc->gc.ops->direction_output = bgpio_dir_out_inv;
- bgc->gc.ops->direction_input = bgpio_dir_in_inv;
+ struct gpio_ops *ops = bgc->gc.ops;
+
+ if (dirout || dirin) {
+ bgc->reg_dir_out = dirout;
+ bgc->reg_dir_in = dirin;
+ if (flags & BGPIOF_NO_SET_ON_INPUT)
+ ops->direction_output = bgpio_dir_out_dir_first;
+ else
+ ops->direction_output = bgpio_dir_out_val_first;
+ ops->direction_input = bgpio_dir_in;
+ ops->get_direction = bgpio_get_dir;
} else {
- bgc->gc.ops->direction_output = bgpio_simple_dir_out;
- bgc->gc.ops->direction_input = bgpio_simple_dir_in;
+ if (flags & BGPIOF_NO_OUTPUT)
+ ops->direction_output = bgpio_dir_out_err;
+ else
+ ops->direction_output = bgpio_simple_dir_out;
+ ops->direction_input = bgpio_simple_dir_in;
}
return 0;
}
-int bgpio_init(struct bgpio_chip *bgc, struct device_d *dev,
+static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
+{
+ if (gpio_pin < chip->ngpio)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * bgpio_init() - Initialize generic GPIO accessor functions
+ * @bgc: the GPIO chip to set up
+ * @dev: the parent device of the new GPIO chip (compulsory)
+ * @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4
+ * @dat: MMIO address for the register to READ the value of the GPIO lines, it
+ * is expected that a 1 in the corresponding bit in this register means the
+ * line is asserted
+ * @set: MMIO address for the register to SET the value of the GPIO lines, it is
+ * expected that we write the line with 1 in this register to drive the GPIO line
+ * high.
+ * @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is
+ * expected that we write the line with 1 in this register to drive the GPIO line
+ * low. It is allowed to leave this address as NULL, in that case the SET register
+ * will be assumed to also clear the GPIO lines, by actively writing the line
+ * with 0.
+ * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed
+ * that setting a line to 1 in this register will turn that line into an
+ * output line. Conversely, setting the line to 0 will turn that line into
+ * an input.
+ * @dirin: MMIO address for the register to set this line as INPUT. It is assumed
+ * that setting a line to 1 in this register will turn that line into an
+ * input line. Conversely, setting the line to 0 will turn that line into
+ * an output.
+ * @flags: Different flags that will affect the behaviour of the device, such as
+ * endianness etc.
+ */
+int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
unsigned int sz, void __iomem *dat, void __iomem *set,
void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
unsigned long flags)
{
+ struct gpio_ops *ops = &bgc->ops;
int ret;
- if ((sz > 4) || !is_power_of_2(sz))
+ if (!is_power_of_2(sz))
return -EINVAL;
bgc->bits = sz * 8;
- bgc->gc.ngpio = bgc->bits;
+ if (bgc->bits > BITS_PER_LONG)
+ return -EINVAL;
+
bgc->gc.base = -1;
+ bgc->gc.ngpio = bgc->bits;
bgc->gc.dev = dev;
- bgc->gc.ops = &bgc->ops;
+ bgc->gc.ops = ops;
+ ops->request = bgpio_request;
+ bgc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN);
- ret = bgpio_setup_io(bgc, dat, set, clr);
+ ret = bgpio_setup_io(bgc, dat, set, clr, flags);
if (ret)
return ret;
- ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN);
+ ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret)
return ret;
- ret = bgpio_setup_direction(bgc, dirout, dirin);
+ ret = bgpio_setup_direction(bgc, dirout, dirin, flags);
if (ret)
return ret;
bgc->data = bgc->read_reg(bgc->reg_dat);
-
- if (bgc->gc.ops->set == bgpio_set_set && !(flags &
- BGPIOF_UNREADABLE_REG_SET))
+ if (ops->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);
+ if (flags & BGPIOF_UNREADABLE_REG_DIR)
+ bgc->dir_unreadable = true;
+
+ /*
+ * Inspect hardware to find initial direction setting.
+ */
+ if ((bgc->reg_dir_out || bgc->reg_dir_in) &&
+ !(flags & BGPIOF_UNREADABLE_REG_DIR)) {
+ if (bgc->reg_dir_out)
+ bgc->dir = bgc->read_reg(bgc->reg_dir_out);
+ else if (bgc->reg_dir_in)
+ bgc->dir = ~bgc->read_reg(bgc->reg_dir_in);
+ /*
+ * If we have two direction registers, synchronise
+ * input setting to output setting, the library
+ * can not handle a line being input and output at
+ * the same time.
+ */
+ if (bgc->reg_dir_out && bgc->reg_dir_in)
+ bgc->write_reg(bgc->reg_dir_in, ~bgc->dir);
+ }
return ret;
}
+EXPORT_SYMBOL_GPL(bgpio_init);
void bgpio_remove(struct bgpio_chip *bgc)
{
gpiochip_remove(&bgc->gc);
free(bgc);
}
+EXPORT_SYMBOL_GPL(bgpio_remove);
#ifdef CONFIG_GPIO_GENERIC_PLATFORM
-static void __iomem *bgpio_map(struct device_d *dev, const char *name,
- resource_size_t sane_sz, int *err)
+static void __iomem *bgpio_map(struct device *dev,
+ const char *name,
+ resource_size_t sane_sz)
{
struct resource *r;
- struct resource *ret;
-
- *err = 0;
+ resource_size_t sz;
- r = dev_get_resource_by_name(dev, IORESOURCE_MEM, name);
+ r = dev_request_mem_resource_by_name(dev, name);
if (IS_ERR(r))
return NULL;
- if (resource_size(r) != sane_sz) {
- *err = -EINVAL;
- return NULL;
- }
+ sz = resource_size(r);
+ if (sz != sane_sz)
+ return IOMEM_ERR_PTR(-EINVAL);
- ret = request_iomem_region(dev_name(dev), r->start, r->end);
- if (IS_ERR(ret)) {
- *err = PTR_ERR(ret);
+ return IOMEM(r->start);
+}
+
+static const struct of_device_id bgpio_of_match[];
+
+static struct bgpio_pdata *bgpio_parse_dt(struct device *dev,
+ unsigned long *flags)
+{
+ struct bgpio_pdata *pdata;
+
+ if (!of_match_device(bgpio_of_match, dev))
return NULL;
- }
- return IOMEM(ret->start);
+ pdata = xzalloc(sizeof(struct bgpio_pdata));
+
+ pdata->base = -1;
+
+ if (of_device_is_big_endian(dev->of_node))
+ *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+
+ if (of_property_read_bool(dev->of_node, "no-output"))
+ *flags |= BGPIOF_NO_OUTPUT;
+
+ return pdata;
}
-static int bgpio_dev_probe(struct device_d *dev)
+static int bgpio_dev_probe(struct device *dev)
{
struct resource *r;
void __iomem *dat;
@@ -342,35 +531,37 @@ static int bgpio_dev_probe(struct device_d *dev)
unsigned long flags = 0;
int err;
struct bgpio_chip *bgc;
- struct bgpio_pdata *pdata = dev->platform_data;
+ struct bgpio_pdata *pdata;
+
+ pdata = bgpio_parse_dt(dev, &flags);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
r = dev_get_resource_by_name(dev, IORESOURCE_MEM, "dat");
- if (IS_ERR(r))
- return PTR_ERR(r);
+ if (!r)
+ return -EINVAL;
sz = resource_size(r);
- dat = bgpio_map(dev, "dat", sz, &err);
- if (!dat)
- return err ? err : -EINVAL;
+ dat = bgpio_map(dev, "dat", sz);
+ if (IS_ERR(dat))
+ return PTR_ERR(dat);
- set = bgpio_map(dev, "set", sz, &err);
- if (err)
- return err;
+ set = bgpio_map(dev, "set", sz);
+ if (IS_ERR(set))
+ return PTR_ERR(set);
- clr = bgpio_map(dev, "clr", sz, &err);
- if (err)
- return err;
+ clr = bgpio_map(dev, "clr", sz);
+ if (IS_ERR(clr))
+ return PTR_ERR(clr);
- dirout = bgpio_map(dev, "dirout", sz, &err);
- if (err)
- return err;
+ dirout = bgpio_map(dev, "dirout", sz);
+ if (IS_ERR(dirout))
+ return PTR_ERR(dirout);
- dirin = bgpio_map(dev, "dirin", sz, &err);
- if (err)
- return err;
-
- dev_get_drvdata(dev, (const void **)&flags);
+ dirin = bgpio_map(dev, "dirin", sz);
+ if (IS_ERR(dirin))
+ return PTR_ERR(dirin);
bgc = xzalloc(sizeof(struct bgpio_chip));
@@ -378,57 +569,47 @@ static int bgpio_dev_probe(struct device_d *dev)
if (err)
return err;
- if (pdata) {
- bgc->gc.base = pdata->base;
- if (pdata->ngpio > 0)
- bgc->gc.ngpio = pdata->ngpio;
- }
+ bgc->gc.base = pdata->base;
+ bgc->gc.dev = dev;
+ bgc->gc.ops = &bgc->ops;
+ if (pdata->ngpio > 0)
+ bgc->gc.ngpio = pdata->ngpio;
dev->priv = bgc;
return gpiochip_add(&bgc->gc);
}
-static void bgpio_dev_remove(struct device_d *dev)
+static void bgpio_dev_remove(struct device *dev)
{
struct bgpio_chip *bgc = dev->priv;
bgpio_remove(bgc);
}
-static struct platform_device_id bgpio_id_table[] = {
+static const struct of_device_id bgpio_of_match[] = {
{
- .name = "basic-mmio-gpio",
- .driver_data = 0,
+ .compatible = "wd,mbl-gpio",
},
{
- .name = "basic-mmio-gpio-be",
- .driver_data = BGPIOF_BIG_ENDIAN,
+ .compatible = "brcm,bcm6345-gpio"
},
- { }
-};
-
-static struct of_device_id __maybe_unused bgpio_of_match[] = {
{
- .compatible = "wd,mbl-gpio",
+ .compatible = "ni,169445-nand-gpio"
}, {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
-static struct driver_d bgpio_driver = {
+static struct driver bgpio_driver = {
.name = "basic-mmio-gpio",
- .id_table = bgpio_id_table,
- .of_compatible = DRV_OF_COMPAT(bgpio_of_match),
+ .of_compatible = bgpio_of_match,
.probe = bgpio_dev_probe,
.remove = bgpio_dev_remove,
};
-static int bgpio_register(void)
-{
- return platform_driver_register(&bgpio_driver);
-}
-coredevice_initcall(bgpio_register);
+coredevice_platform_driver(bgpio_driver);
#endif