diff options
author | Y Vo <yvo@apm.com> | 2015-01-16 02:34:19 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-01-20 04:34:52 -0500 |
commit | b2b35e10892cb1253c93c582e6a3d7ad91ed9f3f (patch) | |
tree | 691b7aa00e6ae2f3c1ca612840e956b936b16f16 | |
parent | 74981fb81d8348b9e405e9acc21c0d5e241d2d69 (diff) |
gpio: Add APM X-Gene standby GPIO controller driver
Driver for standby GPIO controller of APM X-Gene SoCs on arm64.
Signed-off-by: Y Vo <yvo@apm.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/Kconfig | 8 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-xgene-sb.c | 160 |
3 files changed, 169 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8dcd0bd5b0fa..4187fcbc88fd 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -367,6 +367,14 @@ config GPIO_XGENE | |||
367 | the generic flash controller's address and data pins. Say yes | 367 | the generic flash controller's address and data pins. Say yes |
368 | here to enable the GFC GPIO functionality. | 368 | here to enable the GFC GPIO functionality. |
369 | 369 | ||
370 | config GPIO_XGENE_SB | ||
371 | tristate "APM X-Gene GPIO standby controller support" | ||
372 | depends on ARCH_XGENE && OF_GPIO | ||
373 | select GPIO_GENERIC | ||
374 | help | ||
375 | This driver supports the GPIO block within the APM X-Gene | ||
376 | Standby Domain. Say yes here to enable the GPIO functionality. | ||
377 | |||
370 | config GPIO_XILINX | 378 | config GPIO_XILINX |
371 | tristate "Xilinx GPIO support" | 379 | tristate "Xilinx GPIO support" |
372 | depends on OF_GPIO && (PPC_OF || MICROBLAZE || ARCH_ZYNQ || X86) | 380 | depends on OF_GPIO && (PPC_OF || MICROBLAZE || ARCH_ZYNQ || X86) |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 81755f1305e6..3031b19f06ba 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -105,6 +105,7 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o | |||
105 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o | 105 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o |
106 | obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o | 106 | obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o |
107 | obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o | 107 | obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o |
108 | obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o | ||
108 | obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o | 109 | obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o |
109 | obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o | 110 | obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o |
110 | obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o | 111 | obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o |
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c new file mode 100644 index 000000000000..b6a15c39293e --- /dev/null +++ b/drivers/gpio/gpio-xgene-sb.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * AppliedMicro X-Gene SoC GPIO-Standby Driver | ||
3 | * | ||
4 | * Copyright (c) 2014, Applied Micro Circuits Corporation | ||
5 | * Author: Tin Huynh <tnhuynh@apm.com>. | ||
6 | * Y Vo <yvo@apm.com>. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/of_gpio.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/gpio/driver.h> | ||
28 | #include <linux/basic_mmio_gpio.h> | ||
29 | |||
30 | #define XGENE_MAX_GPIO_DS 22 | ||
31 | #define XGENE_MAX_GPIO_DS_IRQ 6 | ||
32 | |||
33 | #define GPIO_MASK(x) (1U << ((x) % 32)) | ||
34 | |||
35 | #define MPA_GPIO_INT_LVL 0x0290 | ||
36 | #define MPA_GPIO_OE_ADDR 0x029c | ||
37 | #define MPA_GPIO_OUT_ADDR 0x02a0 | ||
38 | #define MPA_GPIO_IN_ADDR 0x02a4 | ||
39 | #define MPA_GPIO_SEL_LO 0x0294 | ||
40 | |||
41 | /** | ||
42 | * struct xgene_gpio_sb - GPIO-Standby private data structure. | ||
43 | * @bgc: memory-mapped GPIO controllers. | ||
44 | * @irq: Mapping GPIO pins and interrupt number | ||
45 | * nirq: Number of GPIO pins that supports interrupt | ||
46 | */ | ||
47 | struct xgene_gpio_sb { | ||
48 | struct bgpio_chip bgc; | ||
49 | u32 *irq; | ||
50 | u32 nirq; | ||
51 | }; | ||
52 | |||
53 | static inline struct xgene_gpio_sb *to_xgene_gpio_sb(struct gpio_chip *gc) | ||
54 | { | ||
55 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
56 | |||
57 | return container_of(bgc, struct xgene_gpio_sb, bgc); | ||
58 | } | ||
59 | |||
60 | static void xgene_gpio_set_bit(struct bgpio_chip *bgc, void __iomem *reg, u32 gpio, int val) | ||
61 | { | ||
62 | u32 data; | ||
63 | |||
64 | data = bgc->read_reg(reg); | ||
65 | if (val) | ||
66 | data |= GPIO_MASK(gpio); | ||
67 | else | ||
68 | data &= ~GPIO_MASK(gpio); | ||
69 | bgc->write_reg(reg, data); | ||
70 | } | ||
71 | |||
72 | static int apm_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio) | ||
73 | { | ||
74 | struct xgene_gpio_sb *priv = to_xgene_gpio_sb(gc); | ||
75 | |||
76 | if (priv->irq[gpio]) | ||
77 | return priv->irq[gpio]; | ||
78 | |||
79 | return -ENXIO; | ||
80 | } | ||
81 | |||
82 | static int xgene_gpio_sb_probe(struct platform_device *pdev) | ||
83 | { | ||
84 | struct xgene_gpio_sb *priv; | ||
85 | u32 ret, i; | ||
86 | u32 default_lines[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D}; | ||
87 | struct resource *res; | ||
88 | void __iomem *regs; | ||
89 | |||
90 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
91 | if (!priv) | ||
92 | return -ENOMEM; | ||
93 | |||
94 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
95 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
96 | if (!regs) | ||
97 | return PTR_ERR(regs); | ||
98 | |||
99 | ret = bgpio_init(&priv->bgc, &pdev->dev, 4, | ||
100 | regs + MPA_GPIO_IN_ADDR, | ||
101 | regs + MPA_GPIO_OUT_ADDR, NULL, | ||
102 | regs + MPA_GPIO_OE_ADDR, NULL, 0); | ||
103 | if (ret) | ||
104 | return ret; | ||
105 | |||
106 | priv->bgc.gc.to_irq = apm_gpio_sb_to_irq; | ||
107 | priv->bgc.gc.ngpio = XGENE_MAX_GPIO_DS; | ||
108 | |||
109 | priv->nirq = XGENE_MAX_GPIO_DS_IRQ; | ||
110 | |||
111 | priv->irq = devm_kzalloc(&pdev->dev, sizeof(u32) * XGENE_MAX_GPIO_DS, | ||
112 | GFP_KERNEL); | ||
113 | if (!priv->irq) | ||
114 | return -ENOMEM; | ||
115 | memset(priv->irq, 0, sizeof(u32) * XGENE_MAX_GPIO_DS); | ||
116 | |||
117 | for (i = 0; i < priv->nirq; i++) { | ||
118 | priv->irq[default_lines[i]] = platform_get_irq(pdev, i); | ||
119 | xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_SEL_LO, | ||
120 | default_lines[i] * 2, 1); | ||
121 | xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_INT_LVL, i, 1); | ||
122 | } | ||
123 | |||
124 | platform_set_drvdata(pdev, priv); | ||
125 | |||
126 | ret = gpiochip_add(&priv->bgc.gc); | ||
127 | if (ret) | ||
128 | dev_err(&pdev->dev, "failed to register X-Gene GPIO Standby driver\n"); | ||
129 | else | ||
130 | dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n"); | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int xgene_gpio_sb_remove(struct platform_device *pdev) | ||
136 | { | ||
137 | struct xgene_gpio_sb *priv = platform_get_drvdata(pdev); | ||
138 | |||
139 | return bgpio_remove(&priv->bgc); | ||
140 | } | ||
141 | |||
142 | static const struct of_device_id xgene_gpio_sb_of_match[] = { | ||
143 | {.compatible = "apm,xgene-gpio-sb", }, | ||
144 | {}, | ||
145 | }; | ||
146 | MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match); | ||
147 | |||
148 | static struct platform_driver xgene_gpio_sb_driver = { | ||
149 | .driver = { | ||
150 | .name = "xgene-gpio-sb", | ||
151 | .of_match_table = xgene_gpio_sb_of_match, | ||
152 | }, | ||
153 | .probe = xgene_gpio_sb_probe, | ||
154 | .remove = xgene_gpio_sb_remove, | ||
155 | }; | ||
156 | module_platform_driver(xgene_gpio_sb_driver); | ||
157 | |||
158 | MODULE_AUTHOR("AppliedMicro"); | ||
159 | MODULE_DESCRIPTION("APM X-Gene GPIO Standby driver"); | ||
160 | MODULE_LICENSE("GPL"); | ||