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