Merge tag 'tpm-fixes-for-4.2-rc2' of https://github.com/PeterHuewe/linux-tpmdd into...
[linux-drm-fsl-dcu.git] / arch / mips / ath79 / gpio.c
1 /*
2  *  Atheros AR71XX/AR724X/AR913X GPIO API support
3  *
4  *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7  *
8  *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
9  *
10  *  This program is free software; you can redistribute it and/or modify it
11  *  under the terms of the GNU General Public License version 2 as published
12  *  by the Free Software Foundation.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/spinlock.h>
20 #include <linux/io.h>
21 #include <linux/ioport.h>
22 #include <linux/gpio.h>
23 #include <linux/platform_data/gpio-ath79.h>
24 #include <linux/of_device.h>
25
26 #include <asm/mach-ath79/ar71xx_regs.h>
27 #include <asm/mach-ath79/ath79.h>
28 #include "common.h"
29
30 static void __iomem *ath79_gpio_base;
31 static u32 ath79_gpio_count;
32 static DEFINE_SPINLOCK(ath79_gpio_lock);
33
34 static void __ath79_gpio_set_value(unsigned gpio, int value)
35 {
36         void __iomem *base = ath79_gpio_base;
37
38         if (value)
39                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
40         else
41                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
42 }
43
44 static int __ath79_gpio_get_value(unsigned gpio)
45 {
46         return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
47 }
48
49 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
50 {
51         return __ath79_gpio_get_value(offset);
52 }
53
54 static void ath79_gpio_set_value(struct gpio_chip *chip,
55                                   unsigned offset, int value)
56 {
57         __ath79_gpio_set_value(offset, value);
58 }
59
60 static int ath79_gpio_direction_input(struct gpio_chip *chip,
61                                        unsigned offset)
62 {
63         void __iomem *base = ath79_gpio_base;
64         unsigned long flags;
65
66         spin_lock_irqsave(&ath79_gpio_lock, flags);
67
68         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
69                      base + AR71XX_GPIO_REG_OE);
70
71         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
72
73         return 0;
74 }
75
76 static int ath79_gpio_direction_output(struct gpio_chip *chip,
77                                         unsigned offset, int value)
78 {
79         void __iomem *base = ath79_gpio_base;
80         unsigned long flags;
81
82         spin_lock_irqsave(&ath79_gpio_lock, flags);
83
84         if (value)
85                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
86         else
87                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
88
89         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
90                      base + AR71XX_GPIO_REG_OE);
91
92         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
93
94         return 0;
95 }
96
97 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
98 {
99         void __iomem *base = ath79_gpio_base;
100         unsigned long flags;
101
102         spin_lock_irqsave(&ath79_gpio_lock, flags);
103
104         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
105                      base + AR71XX_GPIO_REG_OE);
106
107         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
108
109         return 0;
110 }
111
112 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
113                                         int value)
114 {
115         void __iomem *base = ath79_gpio_base;
116         unsigned long flags;
117
118         spin_lock_irqsave(&ath79_gpio_lock, flags);
119
120         if (value)
121                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
122         else
123                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
124
125         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
126                      base + AR71XX_GPIO_REG_OE);
127
128         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
129
130         return 0;
131 }
132
133 static struct gpio_chip ath79_gpio_chip = {
134         .label                  = "ath79",
135         .get                    = ath79_gpio_get_value,
136         .set                    = ath79_gpio_set_value,
137         .direction_input        = ath79_gpio_direction_input,
138         .direction_output       = ath79_gpio_direction_output,
139         .base                   = 0,
140 };
141
142 static void __iomem *ath79_gpio_get_function_reg(void)
143 {
144         u32 reg = 0;
145
146         if (soc_is_ar71xx() ||
147             soc_is_ar724x() ||
148             soc_is_ar913x() ||
149             soc_is_ar933x())
150                 reg = AR71XX_GPIO_REG_FUNC;
151         else if (soc_is_ar934x())
152                 reg = AR934X_GPIO_REG_FUNC;
153         else
154                 BUG();
155
156         return ath79_gpio_base + reg;
157 }
158
159 void ath79_gpio_function_setup(u32 set, u32 clear)
160 {
161         void __iomem *reg = ath79_gpio_get_function_reg();
162         unsigned long flags;
163
164         spin_lock_irqsave(&ath79_gpio_lock, flags);
165
166         __raw_writel((__raw_readl(reg) & ~clear) | set, reg);
167         /* flush write */
168         __raw_readl(reg);
169
170         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
171 }
172
173 void ath79_gpio_function_enable(u32 mask)
174 {
175         ath79_gpio_function_setup(mask, 0);
176 }
177
178 void ath79_gpio_function_disable(u32 mask)
179 {
180         ath79_gpio_function_setup(0, mask);
181 }
182
183 static const struct of_device_id ath79_gpio_of_match[] = {
184         { .compatible = "qca,ar7100-gpio" },
185         { .compatible = "qca,ar9340-gpio" },
186         {},
187 };
188
189 static int ath79_gpio_probe(struct platform_device *pdev)
190 {
191         struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
192         struct device_node *np = pdev->dev.of_node;
193         struct resource *res;
194         bool oe_inverted;
195         int err;
196
197         if (np) {
198                 err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
199                 if (err) {
200                         dev_err(&pdev->dev, "ngpios property is not valid\n");
201                         return err;
202                 }
203                 if (ath79_gpio_count >= 32) {
204                         dev_err(&pdev->dev, "ngpios must be less than 32\n");
205                         return -EINVAL;
206                 }
207                 oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
208         } else if (pdata) {
209                 ath79_gpio_count = pdata->ngpios;
210                 oe_inverted = pdata->oe_inverted;
211         } else {
212                 dev_err(&pdev->dev, "No DT node or platform data found\n");
213                 return -EINVAL;
214         }
215
216         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
217         ath79_gpio_base = devm_ioremap_nocache(
218                 &pdev->dev, res->start, resource_size(res));
219         if (!ath79_gpio_base)
220                 return -ENOMEM;
221
222         ath79_gpio_chip.dev = &pdev->dev;
223         ath79_gpio_chip.ngpio = ath79_gpio_count;
224         if (oe_inverted) {
225                 ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
226                 ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
227         }
228
229         err = gpiochip_add(&ath79_gpio_chip);
230         if (err) {
231                 dev_err(&pdev->dev,
232                         "cannot add AR71xx GPIO chip, error=%d", err);
233                 return err;
234         }
235
236         return 0;
237 }
238
239 static struct platform_driver ath79_gpio_driver = {
240         .driver = {
241                 .name = "ath79-gpio",
242                 .of_match_table = ath79_gpio_of_match,
243         },
244         .probe = ath79_gpio_probe,
245 };
246
247 module_platform_driver(ath79_gpio_driver);
248
249 int gpio_get_value(unsigned gpio)
250 {
251         if (gpio < ath79_gpio_count)
252                 return __ath79_gpio_get_value(gpio);
253
254         return __gpio_get_value(gpio);
255 }
256 EXPORT_SYMBOL(gpio_get_value);
257
258 void gpio_set_value(unsigned gpio, int value)
259 {
260         if (gpio < ath79_gpio_count)
261                 __ath79_gpio_set_value(gpio, value);
262         else
263                 __gpio_set_value(gpio, value);
264 }
265 EXPORT_SYMBOL(gpio_set_value);
266
267 int gpio_to_irq(unsigned gpio)
268 {
269         /* FIXME */
270         return -EINVAL;
271 }
272 EXPORT_SYMBOL(gpio_to_irq);
273
274 int irq_to_gpio(unsigned irq)
275 {
276         /* FIXME */
277         return -EINVAL;
278 }
279 EXPORT_SYMBOL(irq_to_gpio);