clean up PCI bus topology
[openwrt/staging/mkresin.git] / target / linux / brcm47xx / patches-3.6 / 502-bcm47xx-rewrite-gpio-handling.patch
1 --- a/arch/mips/Kconfig
2 +++ b/arch/mips/Kconfig
3 @@ -101,6 +101,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 @@ -110,7 +111,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 */