345aa415ab82a20ff9d1902d6d9baa35eb373267
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-3.3 / 502-bcm47xx-rewrite-gpio-handling.patch
1 --- a/arch/mips/Kconfig
2 +++ b/arch/mips/Kconfig
3 @@ -92,6 +92,7 @@ config ATH79
4
5 config BCM47XX
6 bool "Broadcom BCM47XX based boards"
7 + select ARCH_REQUIRE_GPIOLIB
8 select BOOT_RAW
9 select CEVT_R4K
10 select CSRC_R4K
11 @@ -100,7 +101,6 @@ config BCM47XX
12 select IRQ_CPU
13 select SYS_SUPPORTS_32BIT_KERNEL
14 select SYS_SUPPORTS_LITTLE_ENDIAN
15 - select GENERIC_GPIO
16 select CFE
17 help
18 Support for BCM47XX based boards
19 --- a/arch/mips/bcm47xx/gpio.c
20 +++ b/arch/mips/bcm47xx/gpio.c
21 @@ -4,83 +4,150 @@
22 * for more details.
23 *
24 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
25 + * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
26 + *
27 + * Parts of this file are based on Atheros AR71XX/AR724X/AR913X GPIO
28 */
29
30 #include <linux/export.h>
31 +#include <linux/gpio.h>
32 #include <linux/ssb/ssb.h>
33 -#include <linux/ssb/ssb_driver_chipcommon.h>
34 -#include <linux/ssb/ssb_driver_extif.h>
35 -#include <asm/mach-bcm47xx/bcm47xx.h>
36 -#include <asm/mach-bcm47xx/gpio.h>
37 +#include <linux/ssb/ssb_embedded.h>
38 +#include <linux/bcma/bcma.h>
39 +#include <linux/bcma/bcma_driver_gpio.h>
40 +
41 +#include <bcm47xx.h>
42
43 -#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
44 -static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
45 -#else
46 -static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
47 -#endif
48
49 -int gpio_request(unsigned gpio, const char *tag)
50 +static unsigned long bcm47xx_gpio_count;
51 +
52 +/* low level BCM47xx gpio api */
53 +u32 bcm47xx_gpio_in(u32 mask)
54 {
55 switch (bcm47xx_bus_type) {
56 #ifdef CONFIG_BCM47XX_SSB
57 case BCM47XX_BUS_TYPE_SSB:
58 - if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
59 - ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
60 - return -EINVAL;
61 -
62 - if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
63 - ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
64 - return -EINVAL;
65 -
66 - if (test_and_set_bit(gpio, gpio_in_use))
67 - return -EBUSY;
68 -
69 - return 0;
70 + return ssb_gpio_in(&bcm47xx_bus.ssb, mask);
71 #endif
72 #ifdef CONFIG_BCM47XX_BCMA
73 case BCM47XX_BUS_TYPE_BCMA:
74 - if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
75 - return -EINVAL;
76 -
77 - if (test_and_set_bit(gpio, gpio_in_use))
78 - return -EBUSY;
79 + return bcma_gpio_in(&bcm47xx_bus.bcma.bus, mask);
80 +#endif
81 + }
82 + return -EINVAL;
83 +}
84 +EXPORT_SYMBOL(bcm47xx_gpio_in);
85
86 - return 0;
87 +u32 bcm47xx_gpio_out(u32 mask, u32 value)
88 +{
89 + switch (bcm47xx_bus_type) {
90 +#ifdef CONFIG_BCM47XX_SSB
91 + case BCM47XX_BUS_TYPE_SSB:
92 + return ssb_gpio_out(&bcm47xx_bus.ssb, mask, value);
93 +#endif
94 +#ifdef CONFIG_BCM47XX_BCMA
95 + case BCM47XX_BUS_TYPE_BCMA:
96 + return bcma_gpio_out(&bcm47xx_bus.bcma.bus, mask, value);
97 #endif
98 }
99 return -EINVAL;
100 }
101 -EXPORT_SYMBOL(gpio_request);
102 +EXPORT_SYMBOL(bcm47xx_gpio_out);
103
104 -void gpio_free(unsigned gpio)
105 +u32 bcm47xx_gpio_outen(u32 mask, u32 value)
106 {
107 switch (bcm47xx_bus_type) {
108 #ifdef CONFIG_BCM47XX_SSB
109 case BCM47XX_BUS_TYPE_SSB:
110 - if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
111 - ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
112 - return;
113 + return ssb_gpio_outen(&bcm47xx_bus.ssb, mask, value);
114 +#endif
115 +#ifdef CONFIG_BCM47XX_BCMA
116 + case BCM47XX_BUS_TYPE_BCMA:
117 + return bcma_gpio_outen(&bcm47xx_bus.bcma.bus, mask, value);
118 +#endif
119 + }
120 + return -EINVAL;
121 +}
122 +EXPORT_SYMBOL(bcm47xx_gpio_outen);
123
124 - if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
125 - ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
126 - return;
127 +u32 bcm47xx_gpio_control(u32 mask, u32 value)
128 +{
129 + switch (bcm47xx_bus_type) {
130 +#ifdef CONFIG_BCM47XX_SSB
131 + case BCM47XX_BUS_TYPE_SSB:
132 + return ssb_gpio_control(&bcm47xx_bus.ssb, mask, value);
133 +#endif
134 +#ifdef CONFIG_BCM47XX_BCMA
135 + case BCM47XX_BUS_TYPE_BCMA:
136 + return bcma_gpio_control(&bcm47xx_bus.bcma.bus, mask, value);
137 +#endif
138 + }
139 + return -EINVAL;
140 +}
141 +EXPORT_SYMBOL(bcm47xx_gpio_control);
142
143 - clear_bit(gpio, gpio_in_use);
144 - return;
145 +u32 bcm47xx_gpio_intmask(u32 mask, u32 value)
146 +{
147 + switch (bcm47xx_bus_type) {
148 +#ifdef CONFIG_BCM47XX_SSB
149 + case BCM47XX_BUS_TYPE_SSB:
150 + return ssb_gpio_intmask(&bcm47xx_bus.ssb, mask, value);
151 #endif
152 #ifdef CONFIG_BCM47XX_BCMA
153 case BCM47XX_BUS_TYPE_BCMA:
154 - if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
155 - return;
156 + return bcma_gpio_intmask(&bcm47xx_bus.bcma.bus, mask, value);
157 +#endif
158 + }
159 + return -EINVAL;
160 +}
161 +EXPORT_SYMBOL(bcm47xx_gpio_intmask);
162
163 - clear_bit(gpio, gpio_in_use);
164 - return;
165 +u32 bcm47xx_gpio_polarity(u32 mask, u32 value)
166 +{
167 + switch (bcm47xx_bus_type) {
168 +#ifdef CONFIG_BCM47XX_SSB
169 + case BCM47XX_BUS_TYPE_SSB:
170 + return ssb_gpio_polarity(&bcm47xx_bus.ssb, mask, value);
171 +#endif
172 +#ifdef CONFIG_BCM47XX_BCMA
173 + case BCM47XX_BUS_TYPE_BCMA:
174 + return bcma_gpio_polarity(&bcm47xx_bus.bcma.bus, mask, value);
175 #endif
176 }
177 + return -EINVAL;
178 +}
179 +EXPORT_SYMBOL(bcm47xx_gpio_polarity);
180 +
181 +
182 +static int bcm47xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
183 +{
184 + return bcm47xx_gpio_in(1 << gpio);
185 +}
186 +
187 +static void bcm47xx_gpio_set_value(struct gpio_chip *chip,
188 + unsigned gpio, int value)
189 +{
190 + bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
191 +}
192 +
193 +static int bcm47xx_gpio_direction_input(struct gpio_chip *chip,
194 + unsigned gpio)
195 +{
196 + bcm47xx_gpio_outen(1 << gpio, 0);
197 + return 0;
198 +}
199 +
200 +static int bcm47xx_gpio_direction_output(struct gpio_chip *chip,
201 + unsigned gpio, int value)
202 +{
203 + /* first set the gpio out value */
204 + bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
205 + /* then set the gpio mode */
206 + bcm47xx_gpio_outen(1 << gpio, 1 << gpio);
207 + return 0;
208 }
209 -EXPORT_SYMBOL(gpio_free);
210
211 -int gpio_to_irq(unsigned gpio)
212 +static int bcm47xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
213 {
214 switch (bcm47xx_bus_type) {
215 #ifdef CONFIG_BCM47XX_SSB
216 @@ -99,4 +166,55 @@ int gpio_to_irq(unsigned gpio)
217 }
218 return -EINVAL;
219 }
220 -EXPORT_SYMBOL_GPL(gpio_to_irq);
221 +
222 +static struct gpio_chip bcm47xx_gpio_chip = {
223 + .label = "bcm47xx",
224 + .get = bcm47xx_gpio_get_value,
225 + .set = bcm47xx_gpio_set_value,
226 + .direction_input = bcm47xx_gpio_direction_input,
227 + .direction_output = bcm47xx_gpio_direction_output,
228 + .to_irq = bcm47xx_gpio_to_irq,
229 + .base = 0,
230 +};
231 +
232 +void __init bcm47xx_gpio_init(void)
233 +{
234 + int err;
235 +
236 + switch (bcm47xx_bus_type) {
237 +#ifdef CONFIG_BCM47XX_SSB
238 + case BCM47XX_BUS_TYPE_SSB:
239 + bcm47xx_gpio_count = ssb_gpio_count(&bcm47xx_bus.ssb);
240 + break;
241 +#endif
242 +#ifdef CONFIG_BCM47XX_BCMA
243 + case BCM47XX_BUS_TYPE_BCMA:
244 + bcm47xx_gpio_count = bcma_gpio_count(&bcm47xx_bus.bcma.bus);
245 + break;
246 +#endif
247 + }
248 +
249 + bcm47xx_gpio_chip.ngpio = bcm47xx_gpio_count;
250 +
251 + err = gpiochip_add(&bcm47xx_gpio_chip);
252 + if (err)
253 + panic("cannot add BCM47xx GPIO chip, error=%d", err);
254 +}
255 +
256 +int gpio_get_value(unsigned gpio)
257 +{
258 + if (gpio < bcm47xx_gpio_count)
259 + return bcm47xx_gpio_in(1 << gpio);
260 +
261 + return __gpio_get_value(gpio);
262 +}
263 +EXPORT_SYMBOL(gpio_get_value);
264 +
265 +void gpio_set_value(unsigned gpio, int value)
266 +{
267 + if (gpio < bcm47xx_gpio_count)
268 + bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
269 + else
270 + __gpio_set_value(gpio, value);
271 +}
272 +EXPORT_SYMBOL(gpio_set_value);
273 --- a/arch/mips/bcm47xx/setup.c
274 +++ b/arch/mips/bcm47xx/setup.c
275 @@ -345,6 +345,8 @@ void __init plat_mem_setup(void)
276 _machine_restart = bcm47xx_machine_restart;
277 _machine_halt = bcm47xx_machine_halt;
278 pm_power_off = bcm47xx_machine_halt;
279 +
280 + bcm47xx_gpio_init();
281 }
282
283 static int __init bcm47xx_register_bus_complete(void)
284 --- a/arch/mips/bcm47xx/wgt634u.c
285 +++ b/arch/mips/bcm47xx/wgt634u.c
286 @@ -133,6 +133,7 @@ static int __init wgt634u_init(void)
287 * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
288 */
289 u8 *et0mac;
290 + int err;
291
292 if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
293 return -ENODEV;
294 @@ -146,6 +147,12 @@ static int __init wgt634u_init(void)
295
296 printk(KERN_INFO "WGT634U machine detected.\n");
297
298 + err = gpio_request(WGT634U_GPIO_RESET, "reset-buton");
299 + if (err) {
300 + printk(KERN_INFO "Can not register gpio for reset button\n");
301 + return 0;
302 + }
303 +
304 if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
305 gpio_interrupt, IRQF_SHARED,
306 "WGT634U GPIO", ccore)) {
307 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
308 +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
309 @@ -56,4 +56,6 @@ void bcm47xx_fill_bcma_boardinfo(struct
310 const char *prefix);
311 #endif
312
313 +void bcm47xx_gpio_init(void);
314 +
315 #endif /* __ASM_BCM47XX_H */
316 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
317 +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
318 @@ -4,152 +4,42 @@
319 * for more details.
320 *
321 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
322 + * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
323 */
324
325 #ifndef __BCM47XX_GPIO_H
326 #define __BCM47XX_GPIO_H
327
328 -#include <linux/ssb/ssb_embedded.h>
329 -#include <linux/bcma/bcma.h>
330 -#include <asm/mach-bcm47xx/bcm47xx.h>
331 -
332 -#define BCM47XX_EXTIF_GPIO_LINES 5
333 -#define BCM47XX_CHIPCO_GPIO_LINES 16
334 -
335 -extern int gpio_request(unsigned gpio, const char *label);
336 -extern void gpio_free(unsigned gpio);
337 -extern int gpio_to_irq(unsigned gpio);
338 -
339 -static inline int gpio_get_value(unsigned gpio)
340 -{
341 - switch (bcm47xx_bus_type) {
342 -#ifdef CONFIG_BCM47XX_SSB
343 - case BCM47XX_BUS_TYPE_SSB:
344 - return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
345 -#endif
346 -#ifdef CONFIG_BCM47XX_BCMA
347 - case BCM47XX_BUS_TYPE_BCMA:
348 - return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
349 - 1 << gpio);
350 -#endif
351 - }
352 - return -EINVAL;
353 -}
354 -
355 -#define gpio_get_value_cansleep gpio_get_value
356 -
357 -static inline void gpio_set_value(unsigned gpio, int value)
358 -{
359 - switch (bcm47xx_bus_type) {
360 -#ifdef CONFIG_BCM47XX_SSB
361 - case BCM47XX_BUS_TYPE_SSB:
362 - ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
363 - value ? 1 << gpio : 0);
364 - return;
365 -#endif
366 -#ifdef CONFIG_BCM47XX_BCMA
367 - case BCM47XX_BUS_TYPE_BCMA:
368 - bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
369 - value ? 1 << gpio : 0);
370 - return;
371 -#endif
372 - }
373 -}
374 -
375 -#define gpio_set_value_cansleep gpio_set_value
376 -
377 -static inline int gpio_cansleep(unsigned gpio)
378 -{
379 - return 0;
380 -}
381 -
382 -static inline int gpio_is_valid(unsigned gpio)
383 -{
384 - return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
385 -}
386 +#define ARCH_NR_GPIOS 64
387 +#include <asm-generic/gpio.h>
388
389 +/* low level BCM47xx gpio api */
390 +u32 bcm47xx_gpio_in(u32 mask);
391 +u32 bcm47xx_gpio_out(u32 mask, u32 value);
392 +u32 bcm47xx_gpio_outen(u32 mask, u32 value);
393 +u32 bcm47xx_gpio_control(u32 mask, u32 value);
394 +u32 bcm47xx_gpio_intmask(u32 mask, u32 value);
395 +u32 bcm47xx_gpio_polarity(u32 mask, u32 value);
396
397 -static inline int gpio_direction_input(unsigned gpio)
398 -{
399 - switch (bcm47xx_bus_type) {
400 -#ifdef CONFIG_BCM47XX_SSB
401 - case BCM47XX_BUS_TYPE_SSB:
402 - ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
403 - return 0;
404 -#endif
405 -#ifdef CONFIG_BCM47XX_BCMA
406 - case BCM47XX_BUS_TYPE_BCMA:
407 - bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
408 - 0);
409 - return 0;
410 -#endif
411 - }
412 - return -EINVAL;
413 -}
414 +int gpio_get_value(unsigned gpio);
415 +void gpio_set_value(unsigned gpio, int value);
416
417 -static inline int gpio_direction_output(unsigned gpio, int value)
418 +static inline void gpio_intmask(unsigned gpio, int value)
419 {
420 - switch (bcm47xx_bus_type) {
421 -#ifdef CONFIG_BCM47XX_SSB
422 - case BCM47XX_BUS_TYPE_SSB:
423 - /* first set the gpio out value */
424 - ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
425 - value ? 1 << gpio : 0);
426 - /* then set the gpio mode */
427 - ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
428 - return 0;
429 -#endif
430 -#ifdef CONFIG_BCM47XX_BCMA
431 - case BCM47XX_BUS_TYPE_BCMA:
432 - /* first set the gpio out value */
433 - bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
434 - value ? 1 << gpio : 0);
435 - /* then set the gpio mode */
436 - bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
437 - 1 << gpio);
438 - return 0;
439 -#endif
440 - }
441 - return -EINVAL;
442 + bcm47xx_gpio_intmask(1 << gpio, value ? 1 << gpio : 0);
443 }
444
445 -static inline int gpio_intmask(unsigned gpio, int value)
446 +static inline void gpio_polarity(unsigned gpio, int value)
447 {
448 - switch (bcm47xx_bus_type) {
449 -#ifdef CONFIG_BCM47XX_SSB
450 - case BCM47XX_BUS_TYPE_SSB:
451 - ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
452 - value ? 1 << gpio : 0);
453 - return 0;
454 -#endif
455 -#ifdef CONFIG_BCM47XX_BCMA
456 - case BCM47XX_BUS_TYPE_BCMA:
457 - bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
458 - 1 << gpio, value ? 1 << gpio : 0);
459 - return 0;
460 -#endif
461 - }
462 - return -EINVAL;
463 + bcm47xx_gpio_polarity(1 << gpio, value ? 1 << gpio : 0);
464 }
465
466 -static inline int gpio_polarity(unsigned gpio, int value)
467 +static inline int irq_to_gpio(int gpio)
468 {
469 - switch (bcm47xx_bus_type) {
470 -#ifdef CONFIG_BCM47XX_SSB
471 - case BCM47XX_BUS_TYPE_SSB:
472 - ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
473 - value ? 1 << gpio : 0);
474 - return 0;
475 -#endif
476 -#ifdef CONFIG_BCM47XX_BCMA
477 - case BCM47XX_BUS_TYPE_BCMA:
478 - bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
479 - 1 << gpio, value ? 1 << gpio : 0);
480 - return 0;
481 -#endif
482 - }
483 return -EINVAL;
484 }
485
486 +#define gpio_cansleep __gpio_cansleep
487 +#define gpio_to_irq __gpio_to_irq
488
489 #endif /* __BCM47XX_GPIO_H */