345aa415ab82a20ff9d1902d6d9baa35eb373267
[lede.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 */