[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1302272211-30242-6-git-send-email-jamie@jamieiles.com>
Date: Fri, 8 Apr 2011 15:16:49 +0100
From: Jamie Iles <jamie@...ieiles.com>
To: linux-kernel@...r.kernel.org
Cc: linux@....linux.org.uk, tglx@...utronix.de, cbouatmailru@...il.com,
grant.likely@...retlab.ca, arnd@...db.de, nico@...xnic.net,
Jamie Iles <jamie@...ieiles.com>
Subject: [PATCHv2 5/7] basic_mmio_gpio: detect output method at probe time
Rather than detecting the output method each time in the .set()
callback, do it at probe time and set the appropriate callback.
Signed-off-by: Jamie Iles <jamie@...ieiles.com>
Acked-by: Anton Vorontsov <cbouatmailru@...il.com>
Cc: Grant Likely <grant.likely@...retlab.ca>
---
drivers/gpio/basic_mmio_gpio.c | 88 +++++++++++++++++++++++++++-------------
1 files changed, 59 insertions(+), 29 deletions(-)
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c
index 90f7f89..9be1867 100644
--- a/drivers/gpio/basic_mmio_gpio.c
+++ b/drivers/gpio/basic_mmio_gpio.c
@@ -161,14 +161,6 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
unsigned long mask = bgc->pin2mask(bgc, gpio);
unsigned long flags;
- if (bgc->reg_set) {
- if (val)
- bgc->write_reg(bgc->reg_set, mask);
- else
- bgc->write_reg(bgc->reg_clr, mask);
- return;
- }
-
spin_lock_irqsave(&bgc->lock, flags);
if (val)
@@ -181,6 +173,18 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&bgc->lock, flags);
}
+static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
+ int val)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ unsigned long mask = bgc->pin2mask(bgc, gpio);
+
+ if (val)
+ bgc->write_reg(bgc->reg_set, mask);
+ else
+ bgc->write_reg(bgc->reg_clr, mask);
+}
+
static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
return 0;
@@ -188,7 +192,8 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
- bgpio_set(gc, gpio, val);
+ gc->set(gc, gpio, val);
+
return 0;
}
@@ -238,14 +243,52 @@ static int bgpio_setup_accessors(struct platform_device *pdev,
return 0;
}
+/*
+ * Create the device and allocate the resources. For setting GPIO's there are
+ * two supported configurations:
+ *
+ * - single output register resource (named "dat").
+ * - set/clear pair (named "set" and "clr").
+ *
+ * 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
+ * in the set register and clears it by setting a bit in the clear register.
+ * The configuration is detected by which resources are present.
+ */
+static int bgpio_setup_io(struct platform_device *pdev,
+ struct bgpio_chip *bgc)
+{
+ struct resource *res_set;
+ struct resource *res_clr;
+
+ res_set = platform_get_resource_byname(pdev, IORESOURCE_MEM, "set");
+ res_clr = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clr");
+ if (res_set && res_clr) {
+ if (resource_size(res_set) != resource_size(res_clr) ||
+ resource_size(res_set) != bgc->bits)
+ return -EINVAL;
+
+ bgc->reg_set = bgpio_request_and_map(&pdev->dev, res_set);
+ bgc->reg_clr = bgpio_request_and_map(&pdev->dev, res_clr);
+ if (!bgc->reg_set || !bgc->reg_clr)
+ return -ENOMEM;
+
+ bgc->gc.set = bgpio_set_with_clear;
+ } else if (res_set || res_clr) {
+ return -EINVAL;
+ } else {
+ bgc->gc.set = bgpio_set;
+ }
+
+ return 0;
+}
+
static int __devinit bgpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct bgpio_pdata *pdata = dev_get_platdata(dev);
struct bgpio_chip *bgc;
struct resource *res_dat;
- struct resource *res_set;
- struct resource *res_clr;
resource_size_t dat_sz;
int bits;
int ret;
@@ -272,23 +315,6 @@ static int __devinit bgpio_probe(struct platform_device *pdev)
if (!bgc->reg_dat)
return -ENOMEM;
- res_set = platform_get_resource_byname(pdev, IORESOURCE_MEM, "set");
- res_clr = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clr");
- if (res_set && res_clr) {
- if (resource_size(res_set) != resource_size(res_clr) ||
- resource_size(res_set) != dat_sz)
- return -EINVAL;
-
- bgc->reg_set = bgpio_request_and_map(dev, res_set);
- bgc->reg_clr = bgpio_request_and_map(dev, res_clr);
- if (!bgc->reg_set || !bgc->reg_clr)
- return -ENOMEM;
- } else if (res_set || res_clr) {
- return -EINVAL;
- }
-
- spin_lock_init(&bgc->lock);
-
if (pdata) {
bgc->gc.base = pdata->base;
if (pdata->ngpio > 0)
@@ -302,13 +328,17 @@ static int __devinit bgpio_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = bgpio_setup_io(pdev, bgc);
+ if (ret)
+ return ret;
+
+ spin_lock_init(&bgc->lock);
bgc->data = bgc->read_reg(bgc->reg_dat);
bgc->gc.ngpio = ngpio;
bgc->gc.direction_input = bgpio_dir_in;
bgc->gc.direction_output = bgpio_dir_out;
bgc->gc.get = bgpio_get;
- bgc->gc.set = bgpio_set;
bgc->gc.dev = dev;
bgc->gc.label = dev_name(dev);
--
1.7.4.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists