2ab5dbcf1e8cb5bcd9a53dcc079bba6bd1b203c4
[openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / gpio.c
1 /*
2  *  Atheros AR7XXX/AR9XXX SoC GPIO API support
3  *
4  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify it
8  *  under the terms of the GNU General Public License version 2 as published
9  *  by the Free Software Foundation.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/spinlock.h>
17 #include <linux/io.h>
18 #include <linux/ioport.h>
19 #include <linux/gpio.h>
20
21 #include <asm/mach-ar71xx/ar71xx.h>
22
23 static DEFINE_SPINLOCK(ar71xx_gpio_lock);
24
25 unsigned long ar71xx_gpio_count;
26 EXPORT_SYMBOL(ar71xx_gpio_count);
27
28 void __ar71xx_gpio_set_value(unsigned gpio, int value)
29 {
30         void __iomem *base = ar71xx_gpio_base;
31
32         if (value)
33                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
34         else
35                 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
36 }
37 EXPORT_SYMBOL(__ar71xx_gpio_set_value);
38
39 int __ar71xx_gpio_get_value(unsigned gpio)
40 {
41         return (__raw_readl(ar71xx_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
42 }
43 EXPORT_SYMBOL(__ar71xx_gpio_get_value);
44
45 static int ar71xx_gpio_get_value(struct gpio_chip *chip, unsigned offset)
46 {
47         return __ar71xx_gpio_get_value(offset);
48 }
49
50 static void ar71xx_gpio_set_value(struct gpio_chip *chip,
51                                   unsigned offset, int value)
52 {
53         __ar71xx_gpio_set_value(offset, value);
54 }
55
56 static int ar71xx_gpio_direction_input(struct gpio_chip *chip,
57                                        unsigned offset)
58 {
59         void __iomem *base = ar71xx_gpio_base;
60         unsigned long flags;
61
62         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
63
64         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
65                      base + AR71XX_GPIO_REG_OE);
66
67         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
68
69         return 0;
70 }
71
72 static int ar71xx_gpio_direction_output(struct gpio_chip *chip,
73                                         unsigned offset, int value)
74 {
75         void __iomem *base = ar71xx_gpio_base;
76         unsigned long flags;
77
78         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
79
80         if (value)
81                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
82         else
83                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
84
85         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
86                      base + AR71XX_GPIO_REG_OE);
87
88         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
89
90         return 0;
91 }
92
93 static int ar934x_gpio_direction_input(struct gpio_chip *chip,
94                                        unsigned offset)
95 {
96         void __iomem *base = ar71xx_gpio_base;
97         unsigned long flags;
98
99         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
100
101         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
102                      base + AR71XX_GPIO_REG_OE);
103
104         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
105
106         return 0;
107 }
108
109 static int ar934x_gpio_direction_output(struct gpio_chip *chip,
110                                         unsigned offset, int value)
111 {
112         void __iomem *base = ar71xx_gpio_base;
113         unsigned long flags;
114
115         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
116
117         if (value)
118                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
119         else
120                 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
121
122         __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
123                      base + AR71XX_GPIO_REG_OE);
124
125         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
126
127         return 0;
128 }
129
130 static struct gpio_chip ar71xx_gpio_chip = {
131         .label                  = "ar71xx",
132         .get                    = ar71xx_gpio_get_value,
133         .set                    = ar71xx_gpio_set_value,
134         .direction_input        = ar71xx_gpio_direction_input,
135         .direction_output       = ar71xx_gpio_direction_output,
136         .base                   = 0,
137         .ngpio                  = AR71XX_GPIO_COUNT,
138 };
139
140 void ar71xx_gpio_function_enable(u32 mask)
141 {
142         void __iomem *base = ar71xx_gpio_base;
143         unsigned long flags;
144         unsigned int reg;
145
146         if (ar71xx_soc == AR71XX_SOC_AR9341 ||
147             ar71xx_soc == AR71XX_SOC_AR9342 ||
148             ar71xx_soc == AR71XX_SOC_AR9344) {
149                 reg = AR934X_GPIO_REG_FUNC;
150         } else {
151                 reg = AR71XX_GPIO_REG_FUNC;
152         }
153
154         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
155
156         __raw_writel(__raw_readl(base + reg) | mask, base + reg);
157         /* flush write */
158         (void) __raw_readl(base + reg);
159
160         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
161 }
162
163 void ar71xx_gpio_function_disable(u32 mask)
164 {
165         void __iomem *base = ar71xx_gpio_base;
166         unsigned long flags;
167         unsigned int reg;
168
169         if (ar71xx_soc == AR71XX_SOC_AR9341 ||
170             ar71xx_soc == AR71XX_SOC_AR9342 ||
171             ar71xx_soc == AR71XX_SOC_AR9344) {
172                 reg = AR934X_GPIO_REG_FUNC;
173         } else {
174                 reg = AR71XX_GPIO_REG_FUNC;
175         }
176
177         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
178
179         __raw_writel(__raw_readl(base + reg) & ~mask, base + reg);
180         /* flush write */
181         (void) __raw_readl(base + reg);
182
183         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
184 }
185
186 void ar71xx_gpio_function_setup(u32 set, u32 clear)
187 {
188         void __iomem *base = ar71xx_gpio_base;
189         unsigned long flags;
190         unsigned int reg;
191
192         if (ar71xx_soc == AR71XX_SOC_AR9341 ||
193             ar71xx_soc == AR71XX_SOC_AR9342 ||
194             ar71xx_soc == AR71XX_SOC_AR9344) {
195                 reg = AR934X_GPIO_REG_FUNC;
196         } else {
197                 reg = AR71XX_GPIO_REG_FUNC;
198         }
199
200         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
201
202         __raw_writel((__raw_readl(base + reg) & ~clear) | set, base + reg);
203         /* flush write */
204         (void) __raw_readl(base + reg);
205
206         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
207 }
208 EXPORT_SYMBOL(ar71xx_gpio_function_setup);
209
210 void __init ar71xx_gpio_init(void)
211 {
212         int err;
213
214         if (!request_mem_region(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
215                                 "AR71xx GPIO controller"))
216                 panic("cannot allocate AR71xx GPIO registers page");
217
218         switch (ar71xx_soc) {
219         case AR71XX_SOC_AR7130:
220         case AR71XX_SOC_AR7141:
221         case AR71XX_SOC_AR7161:
222                 ar71xx_gpio_chip.ngpio = AR71XX_GPIO_COUNT;
223                 break;
224
225         case AR71XX_SOC_AR7240:
226         case AR71XX_SOC_AR7241:
227         case AR71XX_SOC_AR7242:
228                 ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT;
229                 break;
230
231         case AR71XX_SOC_AR9130:
232         case AR71XX_SOC_AR9132:
233                 ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT;
234                 break;
235
236         case AR71XX_SOC_AR9330:
237         case AR71XX_SOC_AR9331:
238                 ar71xx_gpio_chip.ngpio = AR933X_GPIO_COUNT;
239                 break;
240
241         case AR71XX_SOC_AR9341:
242         case AR71XX_SOC_AR9342:
243         case AR71XX_SOC_AR9344:
244                 ar71xx_gpio_chip.ngpio = AR934X_GPIO_COUNT;
245                 ar71xx_gpio_chip.direction_input = ar934x_gpio_direction_input;
246                 ar71xx_gpio_chip.direction_output = ar934x_gpio_direction_output;
247                 break;
248
249         default:
250                 BUG();
251         }
252
253         err = gpiochip_add(&ar71xx_gpio_chip);
254         if (err)
255                 panic("cannot add AR71xx GPIO chip, error=%d", err);
256 }