abd77472670359a512c1f0dda158816745c836f0
[openwrt/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
145 spin_lock_irqsave(&ar71xx_gpio_lock, flags);
146
147 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
148 base + AR71XX_GPIO_REG_FUNC);
149 /* flush write */
150 (void) __raw_readl(base + AR71XX_GPIO_REG_FUNC);
151
152 spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
153 }
154
155 void ar71xx_gpio_function_disable(u32 mask)
156 {
157 void __iomem *base = ar71xx_gpio_base;
158 unsigned long flags;
159
160 spin_lock_irqsave(&ar71xx_gpio_lock, flags);
161
162 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
163 base + AR71XX_GPIO_REG_FUNC);
164 /* flush write */
165 (void) __raw_readl(base + AR71XX_GPIO_REG_FUNC);
166
167 spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
168 }
169
170 void ar71xx_gpio_function_setup(u32 set, u32 clear)
171 {
172 void __iomem *base = ar71xx_gpio_base;
173 unsigned long flags;
174
175 spin_lock_irqsave(&ar71xx_gpio_lock, flags);
176
177 __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
178 base + AR71XX_GPIO_REG_FUNC);
179 /* flush write */
180 (void) __raw_readl(base + AR71XX_GPIO_REG_FUNC);
181
182 spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
183 }
184 EXPORT_SYMBOL(ar71xx_gpio_function_setup);
185
186 void __init ar71xx_gpio_init(void)
187 {
188 int err;
189
190 if (!request_mem_region(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
191 "AR71xx GPIO controller"))
192 panic("cannot allocate AR71xx GPIO registers page");
193
194 switch (ar71xx_soc) {
195 case AR71XX_SOC_AR7130:
196 case AR71XX_SOC_AR7141:
197 case AR71XX_SOC_AR7161:
198 ar71xx_gpio_chip.ngpio = AR71XX_GPIO_COUNT;
199 break;
200
201 case AR71XX_SOC_AR7240:
202 case AR71XX_SOC_AR7241:
203 case AR71XX_SOC_AR7242:
204 ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT;
205 break;
206
207 case AR71XX_SOC_AR9130:
208 case AR71XX_SOC_AR9132:
209 ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT;
210 break;
211
212 case AR71XX_SOC_AR9330:
213 case AR71XX_SOC_AR9331:
214 ar71xx_gpio_chip.ngpio = AR933X_GPIO_COUNT;
215 break;
216
217 case AR71XX_SOC_AR9341:
218 case AR71XX_SOC_AR9342:
219 case AR71XX_SOC_AR9344:
220 ar71xx_gpio_chip.ngpio = AR934X_GPIO_COUNT;
221 ar71xx_gpio_chip.direction_input = ar934x_gpio_direction_input;
222 ar71xx_gpio_chip.direction_output = ar934x_gpio_direction_output;
223 break;
224
225 default:
226 BUG();
227 }
228
229 err = gpiochip_add(&ar71xx_gpio_chip);
230 if (err)
231 panic("cannot add AR71xx GPIO chip, error=%d", err);
232 }