diff options
author | Andreas Larsson <andreas@gaisler.com> | 2013-04-17 08:36:50 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-04-26 02:50:27 -0400 |
commit | ddb27f3bf771b53e0e7aa93d0186ea5c03381e23 (patch) | |
tree | 19202eaf7b0e2d215c156e86992714f67ce804cc /drivers/gpio | |
parent | 12028d2d216220618f76284af5f8ed510b11da55 (diff) |
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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 9 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-grgpio.c | 149 |
3 files changed, 159 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 704d01d67522..345c6672709c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -309,6 +309,15 @@ config GPIO_LYNXPOINT | |||
309 | driver for GPIO functionality on Intel Lynxpoint PCH chipset | 309 | driver for GPIO functionality on Intel Lynxpoint PCH chipset |
310 | Requires ACPI device enumeration code to set up a platform device. | 310 | Requires ACPI device enumeration code to set up a platform device. |
311 | 311 | ||
312 | config GPIO_GRGPIO | ||
313 | tristate "Aeroflex Gaisler GRGPIO support" | ||
314 | depends on OF | ||
315 | select GPIO_GENERIC | ||
316 | select IRQ_DOMAIN | ||
317 | help | ||
318 | Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB | ||
319 | VHDL IP core library. | ||
320 | |||
312 | comment "I2C GPIO expanders:" | 321 | comment "I2C GPIO expanders:" |
313 | 322 | ||
314 | config GPIO_ARIZONA | 323 | config GPIO_ARIZONA |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 22e07bc9fcb5..3e6be5134122 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | |||
25 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 25 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
26 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 26 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
27 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o | 27 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o |
28 | obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o | ||
28 | obj-$(CONFIG_GPIO_ICH) += gpio-ich.o | 29 | obj-$(CONFIG_GPIO_ICH) += gpio-ich.o |
29 | obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o | 30 | obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o |
30 | obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o | 31 | obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o |
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c new file mode 100644 index 000000000000..466a1c757fae --- /dev/null +++ b/drivers/gpio/gpio-grgpio.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * Driver for Aeroflex Gaisler GRGPIO General Purpose I/O cores. | ||
3 | * | ||
4 | * 2013 (c) Aeroflex Gaisler AB | ||
5 | * | ||
6 | * This driver supports the GRGPIO GPIO core available in the GRLIB VHDL | ||
7 | * IP core library. | ||
8 | * | ||
9 | * Full documentation of the GRGPIO core can be found here: | ||
10 | * http://www.gaisler.com/products/grlib/grip.pdf | ||
11 | * | ||
12 | * See "Documentation/devicetree/bindings/gpio/gpio-grgpio.txt" for | ||
13 | * information on open firmware properties. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * Contributors: Andreas Larsson <andreas@gaisler.com> | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/of_platform.h> | ||
31 | #include <linux/gpio.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/basic_mmio_gpio.h> | ||
35 | |||
36 | #define GRGPIO_MAX_NGPIO 32 | ||
37 | |||
38 | #define GRGPIO_DATA 0x00 | ||
39 | #define GRGPIO_OUTPUT 0x04 | ||
40 | #define GRGPIO_DIR 0x08 | ||
41 | #define GRGPIO_IMASK 0x0c | ||
42 | #define GRGPIO_IPOL 0x10 | ||
43 | #define GRGPIO_IEDGE 0x14 | ||
44 | #define GRGPIO_BYPASS 0x18 | ||
45 | #define GRGPIO_IMAP_BASE 0x20 | ||
46 | |||
47 | struct grgpio_priv { | ||
48 | struct bgpio_chip bgc; | ||
49 | void __iomem *regs; | ||
50 | struct device *dev; | ||
51 | }; | ||
52 | |||
53 | static inline struct grgpio_priv *grgpio_gc_to_priv(struct gpio_chip *gc) | ||
54 | { | ||
55 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
56 | |||
57 | return container_of(bgc, struct grgpio_priv, bgc); | ||
58 | } | ||
59 | |||
60 | static int grgpio_probe(struct platform_device *ofdev) | ||
61 | { | ||
62 | struct device_node *np = ofdev->dev.of_node; | ||
63 | void __iomem *regs; | ||
64 | struct gpio_chip *gc; | ||
65 | struct bgpio_chip *bgc; | ||
66 | struct grgpio_priv *priv; | ||
67 | struct resource *res; | ||
68 | int err; | ||
69 | u32 prop; | ||
70 | |||
71 | priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL); | ||
72 | if (!priv) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); | ||
76 | regs = devm_ioremap_resource(&ofdev->dev, res); | ||
77 | if (IS_ERR(regs)) | ||
78 | return PTR_ERR(regs); | ||
79 | |||
80 | bgc = &priv->bgc; | ||
81 | err = bgpio_init(bgc, &ofdev->dev, 4, regs + GRGPIO_DATA, | ||
82 | regs + GRGPIO_OUTPUT, NULL, regs + GRGPIO_DIR, NULL, | ||
83 | BGPIOF_BIG_ENDIAN_BYTE_ORDER); | ||
84 | if (err) { | ||
85 | dev_err(&ofdev->dev, "bgpio_init() failed\n"); | ||
86 | return err; | ||
87 | } | ||
88 | |||
89 | priv->regs = regs; | ||
90 | priv->dev = &ofdev->dev; | ||
91 | |||
92 | gc = &bgc->gc; | ||
93 | gc->of_node = np; | ||
94 | gc->owner = THIS_MODULE; | ||
95 | gc->label = np->full_name; | ||
96 | gc->base = -1; | ||
97 | |||
98 | err = of_property_read_u32(np, "nbits", &prop); | ||
99 | if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) { | ||
100 | gc->ngpio = GRGPIO_MAX_NGPIO; | ||
101 | dev_dbg(&ofdev->dev, | ||
102 | "No or invalid nbits property: assume %d\n", gc->ngpio); | ||
103 | } else { | ||
104 | gc->ngpio = prop; | ||
105 | } | ||
106 | |||
107 | platform_set_drvdata(ofdev, priv); | ||
108 | |||
109 | err = gpiochip_add(gc); | ||
110 | if (err) { | ||
111 | dev_err(&ofdev->dev, "Could not add gpiochip\n"); | ||
112 | return err; | ||
113 | } | ||
114 | |||
115 | dev_info(&ofdev->dev, "regs=0x%p, base=%d, ngpio=%d\n", | ||
116 | priv->regs, gc->base, gc->ngpio); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int grgpio_remove(struct platform_device *ofdev) | ||
122 | { | ||
123 | struct grgpio_priv *priv = platform_get_drvdata(ofdev); | ||
124 | |||
125 | return gpiochip_remove(&priv->bgc.gc); | ||
126 | } | ||
127 | |||
128 | static struct of_device_id grgpio_match[] = { | ||
129 | {.name = "GAISLER_GPIO"}, | ||
130 | {.name = "01_01a"}, | ||
131 | {}, | ||
132 | }; | ||
133 | |||
134 | MODULE_DEVICE_TABLE(of, grgpio_match); | ||
135 | |||
136 | static struct platform_driver grgpio_driver = { | ||
137 | .driver = { | ||
138 | .name = "grgpio", | ||
139 | .owner = THIS_MODULE, | ||
140 | .of_match_table = grgpio_match, | ||
141 | }, | ||
142 | .probe = grgpio_probe, | ||
143 | .remove = grgpio_remove, | ||
144 | }; | ||
145 | module_platform_driver(grgpio_driver); | ||
146 | |||
147 | MODULE_AUTHOR("Aeroflex Gaisler AB."); | ||
148 | MODULE_DESCRIPTION("Driver for Aeroflex Gaisler GRGPIO"); | ||
149 | MODULE_LICENSE("GPL"); | ||