Root/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 */
494

Archive Download this file



interactive