Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 251963
b: refs/heads/master
c: e027d6f
h: refs/heads/master
i:
  251961: ac4ce32
  251959: a2ffabf
v: v3
  • Loading branch information
Jamie Iles authored and Grant Likely committed May 20, 2011
1 parent 5e6b1fc commit c328cbf
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 32 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 364b5e871839fafffa851bbff9ecf64ac641023c
refs/heads/master: e027d6f9d52d9ccabb307d0cb0265de3481b1e9e
90 changes: 59 additions & 31 deletions trunk/drivers/gpio/basic_mmio_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -181,14 +173,27 @@ 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;
}

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;
}

Expand Down Expand Up @@ -238,18 +243,25 @@ static int bgpio_setup_accessors(struct platform_device *pdev,
return 0;
}

static int __devinit bgpio_probe(struct platform_device *pdev)
/*
* 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 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;
struct resource *res_dat;
resource_size_t dat_sz;
int bits;
int ret;
int ngpio;

res_dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
if (!res_dat)
Expand All @@ -259,36 +271,53 @@ static int __devinit bgpio_probe(struct platform_device *pdev)
if (!is_power_of_2(dat_sz))
return -EINVAL;

bits = dat_sz * 8;
ngpio = bits;
if (bits > BITS_PER_LONG)
bgc->bits = dat_sz * 8;
if (bgc->bits > BITS_PER_LONG)
return -EINVAL;

bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
return -ENOMEM;

bgc->reg_dat = bgpio_request_and_map(dev, res_dat);
bgc->reg_dat = bgpio_request_and_map(&pdev->dev, res_dat);
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)
resource_size(res_set) != resource_size(res_dat))
return -EINVAL;

bgc->reg_set = bgpio_request_and_map(dev, res_set);
bgc->reg_clr = bgpio_request_and_map(dev, res_clr);
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;
}

spin_lock_init(&bgc->lock);
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;
int ret;
int ngpio;

bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
return -ENOMEM;

ret = bgpio_setup_io(pdev, bgc);
if (ret)
return ret;

ngpio = bgc->bits;
if (pdata) {
bgc->gc.base = pdata->base;
if (pdata->ngpio > 0)
Expand All @@ -297,18 +326,17 @@ static int __devinit bgpio_probe(struct platform_device *pdev)
bgc->gc.base = -1;
}

bgc->bits = bits;
ret = bgpio_setup_accessors(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);

Expand Down

0 comments on commit c328cbf

Please sign in to comment.