-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gpio: grgpio: Add device driver for GRGPIO cores
This driver supports GRGPIO gpio cores available in the GRLIB VHDL IP core library from Aeroflex Gaisler. Signed-off-by: Andreas Larsson <andreas@gaisler.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
- Loading branch information
Andreas Larsson
authored and
Linus Walleij
committed
Apr 26, 2013
1 parent
12028d2
commit ddb27f3
Showing
4 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Aeroflex Gaisler GRGPIO General Purpose I/O cores. | ||
|
||
The GRGPIO GPIO core is available in the GRLIB VHDL IP core library. | ||
|
||
Note: In the ordinary environment for the GRGPIO core, a Leon SPARC system, | ||
these properties are built from information in the AMBA plug&play. | ||
|
||
Required properties: | ||
|
||
- name : Should be "GAISLER_GPIO" or "01_01a" | ||
|
||
- reg : Address and length of the register set for the device | ||
|
||
- interrupts : Interrupt numbers for this device | ||
|
||
Optional properties: | ||
|
||
- nbits : The number of gpio lines. If not present driver assumes 32 lines. | ||
|
||
For further information look in the documentation for the GLIB IP core library: | ||
http://www.gaisler.com/products/grlib/grip.pdf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
/* | ||
* Driver for Aeroflex Gaisler GRGPIO General Purpose I/O cores. | ||
* | ||
* 2013 (c) Aeroflex Gaisler AB | ||
* | ||
* This driver supports the GRGPIO GPIO core available in the GRLIB VHDL | ||
* IP core library. | ||
* | ||
* Full documentation of the GRGPIO core can be found here: | ||
* http://www.gaisler.com/products/grlib/grip.pdf | ||
* | ||
* See "Documentation/devicetree/bindings/gpio/gpio-grgpio.txt" for | ||
* information on open firmware properties. | ||
* | ||
* 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. | ||
* | ||
* Contributors: Andreas Larsson <andreas@gaisler.com> | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/init.h> | ||
#include <linux/spinlock.h> | ||
#include <linux/io.h> | ||
#include <linux/of.h> | ||
#include <linux/of_gpio.h> | ||
#include <linux/of_platform.h> | ||
#include <linux/gpio.h> | ||
#include <linux/slab.h> | ||
#include <linux/err.h> | ||
#include <linux/basic_mmio_gpio.h> | ||
|
||
#define GRGPIO_MAX_NGPIO 32 | ||
|
||
#define GRGPIO_DATA 0x00 | ||
#define GRGPIO_OUTPUT 0x04 | ||
#define GRGPIO_DIR 0x08 | ||
#define GRGPIO_IMASK 0x0c | ||
#define GRGPIO_IPOL 0x10 | ||
#define GRGPIO_IEDGE 0x14 | ||
#define GRGPIO_BYPASS 0x18 | ||
#define GRGPIO_IMAP_BASE 0x20 | ||
|
||
struct grgpio_priv { | ||
struct bgpio_chip bgc; | ||
void __iomem *regs; | ||
struct device *dev; | ||
}; | ||
|
||
static inline struct grgpio_priv *grgpio_gc_to_priv(struct gpio_chip *gc) | ||
{ | ||
struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
|
||
return container_of(bgc, struct grgpio_priv, bgc); | ||
} | ||
|
||
static int grgpio_probe(struct platform_device *ofdev) | ||
{ | ||
struct device_node *np = ofdev->dev.of_node; | ||
void __iomem *regs; | ||
struct gpio_chip *gc; | ||
struct bgpio_chip *bgc; | ||
struct grgpio_priv *priv; | ||
struct resource *res; | ||
int err; | ||
u32 prop; | ||
|
||
priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL); | ||
if (!priv) | ||
return -ENOMEM; | ||
|
||
res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); | ||
regs = devm_ioremap_resource(&ofdev->dev, res); | ||
if (IS_ERR(regs)) | ||
return PTR_ERR(regs); | ||
|
||
bgc = &priv->bgc; | ||
err = bgpio_init(bgc, &ofdev->dev, 4, regs + GRGPIO_DATA, | ||
regs + GRGPIO_OUTPUT, NULL, regs + GRGPIO_DIR, NULL, | ||
BGPIOF_BIG_ENDIAN_BYTE_ORDER); | ||
if (err) { | ||
dev_err(&ofdev->dev, "bgpio_init() failed\n"); | ||
return err; | ||
} | ||
|
||
priv->regs = regs; | ||
priv->dev = &ofdev->dev; | ||
|
||
gc = &bgc->gc; | ||
gc->of_node = np; | ||
gc->owner = THIS_MODULE; | ||
gc->label = np->full_name; | ||
gc->base = -1; | ||
|
||
err = of_property_read_u32(np, "nbits", &prop); | ||
if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) { | ||
gc->ngpio = GRGPIO_MAX_NGPIO; | ||
dev_dbg(&ofdev->dev, | ||
"No or invalid nbits property: assume %d\n", gc->ngpio); | ||
} else { | ||
gc->ngpio = prop; | ||
} | ||
|
||
platform_set_drvdata(ofdev, priv); | ||
|
||
err = gpiochip_add(gc); | ||
if (err) { | ||
dev_err(&ofdev->dev, "Could not add gpiochip\n"); | ||
return err; | ||
} | ||
|
||
dev_info(&ofdev->dev, "regs=0x%p, base=%d, ngpio=%d\n", | ||
priv->regs, gc->base, gc->ngpio); | ||
|
||
return 0; | ||
} | ||
|
||
static int grgpio_remove(struct platform_device *ofdev) | ||
{ | ||
struct grgpio_priv *priv = platform_get_drvdata(ofdev); | ||
|
||
return gpiochip_remove(&priv->bgc.gc); | ||
} | ||
|
||
static struct of_device_id grgpio_match[] = { | ||
{.name = "GAISLER_GPIO"}, | ||
{.name = "01_01a"}, | ||
{}, | ||
}; | ||
|
||
MODULE_DEVICE_TABLE(of, grgpio_match); | ||
|
||
static struct platform_driver grgpio_driver = { | ||
.driver = { | ||
.name = "grgpio", | ||
.owner = THIS_MODULE, | ||
.of_match_table = grgpio_match, | ||
}, | ||
.probe = grgpio_probe, | ||
.remove = grgpio_remove, | ||
}; | ||
module_platform_driver(grgpio_driver); | ||
|
||
MODULE_AUTHOR("Aeroflex Gaisler AB."); | ||
MODULE_DESCRIPTION("Driver for Aeroflex Gaisler GRGPIO"); | ||
MODULE_LICENSE("GPL"); |