MIPS: ath79: Move the GPIO driver to drivers/gpio
[linux-drm-fsl-dcu.git] / drivers / gpio / gpio-ath79.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
28 static void __iomem *ath79_gpio_base;
29 static u32 ath79_gpio_count;
30 static DEFINE_SPINLOCK(ath79_gpio_lock);
31
32 static void __ath79_gpio_set_value(unsigned gpio, int value)
33 {
34         void __iomem *base = ath79_gpio_base;
35
36         if (value)
37                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
38         else
39                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
40 }
41
42 static int __ath79_gpio_get_value(unsigned gpio)
43 {
44         return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
45 }
46
47 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
48 {
49         return __ath79_gpio_get_value(offset);
50 }
51
52 static void ath79_gpio_set_value(struct gpio_chip *chip,
53                                   unsigned offset, int value)
54 {
55         __ath79_gpio_set_value(offset, value);
56 }
57
58 static int ath79_gpio_direction_input(struct gpio_chip *chip,
59                                        unsigned offset)
60 {
61         void __iomem *base = ath79_gpio_base;
62         unsigned long flags;
63
64         spin_lock_irqsave(&ath79_gpio_lock, flags);
65
66         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
67                      base + AR71XX_GPIO_REG_OE);
68
69         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
70
71         return 0;
72 }
73
74 static int ath79_gpio_direction_output(struct gpio_chip *chip,
75                                         unsigned offset, int value)
76 {
77         void __iomem *base = ath79_gpio_base;
78         unsigned long flags;
79
80         spin_lock_irqsave(&ath79_gpio_lock, flags);
81
82         if (value)
83                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
84         else
85                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
86
87         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
88                      base + AR71XX_GPIO_REG_OE);
89
90         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
91
92         return 0;
93 }
94
95 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
96 {
97         void __iomem *base = ath79_gpio_base;
98         unsigned long flags;
99
100         spin_lock_irqsave(&ath79_gpio_lock, flags);
101
102         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
103                      base + AR71XX_GPIO_REG_OE);
104
105         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
106
107         return 0;
108 }
109
110 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
111                                         int value)
112 {
113         void __iomem *base = ath79_gpio_base;
114         unsigned long flags;
115
116         spin_lock_irqsave(&ath79_gpio_lock, flags);
117
118         if (value)
119                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
120         else
121                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
122
123         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
124                      base + AR71XX_GPIO_REG_OE);
125
126         spin_unlock_irqrestore(&ath79_gpio_lock, flags);
127
128         return 0;
129 }
130
131 static struct gpio_chip ath79_gpio_chip = {
132         .label                  = "ath79",
133         .get                    = ath79_gpio_get_value,
134         .set                    = ath79_gpio_set_value,
135         .direction_input        = ath79_gpio_direction_input,
136         .direction_output       = ath79_gpio_direction_output,
137         .base                   = 0,
138 };
139
140 static const struct of_device_id ath79_gpio_of_match[] = {
141         { .compatible = "qca,ar7100-gpio" },
142         { .compatible = "qca,ar9340-gpio" },
143         {},
144 };
145
146 static int ath79_gpio_probe(struct platform_device *pdev)
147 {
148         struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
149         struct device_node *np = pdev->dev.of_node;
150         struct resource *res;
151         bool oe_inverted;
152         int err;
153
154         if (np) {
155                 err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
156                 if (err) {
157                         dev_err(&pdev->dev, "ngpios property is not valid\n");
158                         return err;
159                 }
160                 if (ath79_gpio_count >= 32) {
161                         dev_err(&pdev->dev, "ngpios must be less than 32\n");
162                         return -EINVAL;
163                 }
164                 oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
165         } else if (pdata) {
166                 ath79_gpio_count = pdata->ngpios;
167                 oe_inverted = pdata->oe_inverted;
168         } else {
169                 dev_err(&pdev->dev, "No DT node or platform data found\n");
170                 return -EINVAL;
171         }
172
173         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
174         ath79_gpio_base = devm_ioremap_nocache(
175                 &pdev->dev, res->start, resource_size(res));
176         if (!ath79_gpio_base)
177                 return -ENOMEM;
178
179         ath79_gpio_chip.dev = &pdev->dev;
180         ath79_gpio_chip.ngpio = ath79_gpio_count;
181         if (oe_inverted) {
182                 ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
183                 ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
184         }
185
186         err = gpiochip_add(&ath79_gpio_chip);
187         if (err) {
188                 dev_err(&pdev->dev,
189                         "cannot add AR71xx GPIO chip, error=%d", err);
190                 return err;
191         }
192
193         return 0;
194 }
195
196 static struct platform_driver ath79_gpio_driver = {
197         .driver = {
198                 .name = "ath79-gpio",
199                 .of_match_table = ath79_gpio_of_match,
200         },
201         .probe = ath79_gpio_probe,
202 };
203
204 module_platform_driver(ath79_gpio_driver);
205
206 int gpio_get_value(unsigned gpio)
207 {
208         if (gpio < ath79_gpio_count)
209                 return __ath79_gpio_get_value(gpio);
210
211         return __gpio_get_value(gpio);
212 }
213 EXPORT_SYMBOL(gpio_get_value);
214
215 void gpio_set_value(unsigned gpio, int value)
216 {
217         if (gpio < ath79_gpio_count)
218                 __ath79_gpio_set_value(gpio, value);
219         else
220                 __gpio_set_value(gpio, value);
221 }
222 EXPORT_SYMBOL(gpio_set_value);
223
224 int gpio_to_irq(unsigned gpio)
225 {
226         /* FIXME */
227         return -EINVAL;
228 }
229 EXPORT_SYMBOL(gpio_to_irq);
230
231 int irq_to_gpio(unsigned irq)
232 {
233         /* FIXME */
234         return -EINVAL;
235 }
236 EXPORT_SYMBOL(irq_to_gpio);