1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-12-01 03:17:11 +02:00
openwrt-xburst/target/linux/brcm47xx/patches-3.3/502-bcm47xx-rewrite-gpio-handling.patch
hauke b7397011b8 [brcm47xx] make brcm47xx build only with bcma or only with ssb support.
There are some ifdefs missing so when only ssb or only bcma was
selected in the kernel config it did not build.


git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33209 3c298f89-4303-0410-b956-a3cf2f4a3e73
2012-08-18 14:08:35 +00:00

490 lines
12 KiB
Diff

--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -92,6 +92,7 @@ config ATH79
config BCM47XX
bool "Broadcom BCM47XX based boards"
+ select ARCH_REQUIRE_GPIOLIB
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
@@ -100,7 +101,6 @@ config BCM47XX
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_GPIO
select CFE
help
Support for BCM47XX based boards
--- a/arch/mips/bcm47xx/gpio.c
+++ b/arch/mips/bcm47xx/gpio.c
@@ -4,83 +4,150 @@
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Parts of this file are based on Atheros AR71XX/AR724X/AR913X GPIO
*/
#include <linux/export.h>
+#include <linux/gpio.h>
#include <linux/ssb/ssb.h>
-#include <linux/ssb/ssb_driver_chipcommon.h>
-#include <linux/ssb/ssb_driver_extif.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
-#include <asm/mach-bcm47xx/gpio.h>
+#include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_driver_gpio.h>
+
+#include <bcm47xx.h>
-#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
-#else
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
-#endif
-int gpio_request(unsigned gpio, const char *tag)
+static unsigned long bcm47xx_gpio_count;
+
+/* low level BCM47xx gpio api */
+u32 bcm47xx_gpio_in(u32 mask)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
- if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return -EINVAL;
-
- if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
- return -EINVAL;
-
- if (test_and_set_bit(gpio, gpio_in_use))
- return -EBUSY;
-
- return 0;
+ return ssb_gpio_in(&bcm47xx_bus.ssb, mask);
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
- if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
- return -EINVAL;
-
- if (test_and_set_bit(gpio, gpio_in_use))
- return -EBUSY;
+ return bcma_gpio_in(&bcm47xx_bus.bcma.bus, mask);
+#endif
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(bcm47xx_gpio_in);
- return 0;
+u32 bcm47xx_gpio_out(u32 mask, u32 value)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_out(&bcm47xx_bus.ssb, mask, value);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_gpio_out(&bcm47xx_bus.bcma.bus, mask, value);
#endif
}
return -EINVAL;
}
-EXPORT_SYMBOL(gpio_request);
+EXPORT_SYMBOL(bcm47xx_gpio_out);
-void gpio_free(unsigned gpio)
+u32 bcm47xx_gpio_outen(u32 mask, u32 value)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
- if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return;
+ return ssb_gpio_outen(&bcm47xx_bus.ssb, mask, value);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_gpio_outen(&bcm47xx_bus.bcma.bus, mask, value);
+#endif
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(bcm47xx_gpio_outen);
- if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
- return;
+u32 bcm47xx_gpio_control(u32 mask, u32 value)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_control(&bcm47xx_bus.ssb, mask, value);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_gpio_control(&bcm47xx_bus.bcma.bus, mask, value);
+#endif
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(bcm47xx_gpio_control);
- clear_bit(gpio, gpio_in_use);
- return;
+u32 bcm47xx_gpio_intmask(u32 mask, u32 value)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_intmask(&bcm47xx_bus.ssb, mask, value);
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
- if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
- return;
+ return bcma_gpio_intmask(&bcm47xx_bus.bcma.bus, mask, value);
+#endif
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(bcm47xx_gpio_intmask);
- clear_bit(gpio, gpio_in_use);
- return;
+u32 bcm47xx_gpio_polarity(u32 mask, u32 value)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_polarity(&bcm47xx_bus.ssb, mask, value);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_gpio_polarity(&bcm47xx_bus.bcma.bus, mask, value);
#endif
}
+ return -EINVAL;
+}
+EXPORT_SYMBOL(bcm47xx_gpio_polarity);
+
+
+static int bcm47xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ return bcm47xx_gpio_in(1 << gpio);
+}
+
+static void bcm47xx_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int bcm47xx_gpio_direction_input(struct gpio_chip *chip,
+ unsigned gpio)
+{
+ bcm47xx_gpio_outen(1 << gpio, 0);
+ return 0;
+}
+
+static int bcm47xx_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ /* first set the gpio out value */
+ bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
+ /* then set the gpio mode */
+ bcm47xx_gpio_outen(1 << gpio, 1 << gpio);
+ return 0;
}
-EXPORT_SYMBOL(gpio_free);
-int gpio_to_irq(unsigned gpio)
+static int bcm47xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
@@ -99,4 +166,55 @@ int gpio_to_irq(unsigned gpio)
}
return -EINVAL;
}
-EXPORT_SYMBOL_GPL(gpio_to_irq);
+
+static struct gpio_chip bcm47xx_gpio_chip = {
+ .label = "bcm47xx",
+ .get = bcm47xx_gpio_get_value,
+ .set = bcm47xx_gpio_set_value,
+ .direction_input = bcm47xx_gpio_direction_input,
+ .direction_output = bcm47xx_gpio_direction_output,
+ .to_irq = bcm47xx_gpio_to_irq,
+ .base = 0,
+};
+
+void __init bcm47xx_gpio_init(void)
+{
+ int err;
+
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ bcm47xx_gpio_count = ssb_gpio_count(&bcm47xx_bus.ssb);
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcm47xx_gpio_count = bcma_gpio_count(&bcm47xx_bus.bcma.bus);
+ break;
+#endif
+ }
+
+ bcm47xx_gpio_chip.ngpio = bcm47xx_gpio_count;
+
+ err = gpiochip_add(&bcm47xx_gpio_chip);
+ if (err)
+ panic("cannot add BCM47xx GPIO chip, error=%d", err);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ if (gpio < bcm47xx_gpio_count)
+ return bcm47xx_gpio_in(1 << gpio);
+
+ return __gpio_get_value(gpio);
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ if (gpio < bcm47xx_gpio_count)
+ bcm47xx_gpio_out(1 << gpio, value ? 1 << gpio : 0);
+ else
+ __gpio_set_value(gpio, value);
+}
+EXPORT_SYMBOL(gpio_set_value);
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -345,6 +345,8 @@ void __init plat_mem_setup(void)
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
+
+ bcm47xx_gpio_init();
}
static int __init bcm47xx_register_bus_complete(void)
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -133,6 +133,7 @@ static int __init wgt634u_init(void)
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
*/
u8 *et0mac;
+ int err;
if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
return -ENODEV;
@@ -146,6 +147,12 @@ static int __init wgt634u_init(void)
printk(KERN_INFO "WGT634U machine detected.\n");
+ err = gpio_request(WGT634U_GPIO_RESET, "reset-buton");
+ if (err) {
+ printk(KERN_INFO "Can not register gpio for reset button\n");
+ return 0;
+ }
+
if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
gpio_interrupt, IRQF_SHARED,
"WGT634U GPIO", ccore)) {
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -56,4 +56,6 @@ void bcm47xx_fill_bcma_boardinfo(struct
const char *prefix);
#endif
+void bcm47xx_gpio_init(void);
+
#endif /* __ASM_BCM47XX_H */
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -4,152 +4,42 @@
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
*/
#ifndef __BCM47XX_GPIO_H
#define __BCM47XX_GPIO_H
-#include <linux/ssb/ssb_embedded.h>
-#include <linux/bcma/bcma.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
-
-#define BCM47XX_EXTIF_GPIO_LINES 5
-#define BCM47XX_CHIPCO_GPIO_LINES 16
-
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_to_irq(unsigned gpio);
-
-static inline int gpio_get_value(unsigned gpio)
-{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
- 1 << gpio);
-#endif
- }
- return -EINVAL;
-}
-
-#define gpio_get_value_cansleep gpio_get_value
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
- value ? 1 << gpio : 0);
- return;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
- value ? 1 << gpio : 0);
- return;
-#endif
- }
-}
-
-#define gpio_set_value_cansleep gpio_set_value
-
-static inline int gpio_cansleep(unsigned gpio)
-{
- return 0;
-}
-
-static inline int gpio_is_valid(unsigned gpio)
-{
- return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
-}
+#define ARCH_NR_GPIOS 64
+#include <asm-generic/gpio.h>
+/* low level BCM47xx gpio api */
+u32 bcm47xx_gpio_in(u32 mask);
+u32 bcm47xx_gpio_out(u32 mask, u32 value);
+u32 bcm47xx_gpio_outen(u32 mask, u32 value);
+u32 bcm47xx_gpio_control(u32 mask, u32 value);
+u32 bcm47xx_gpio_intmask(u32 mask, u32 value);
+u32 bcm47xx_gpio_polarity(u32 mask, u32 value);
-static inline int gpio_direction_input(unsigned gpio)
-{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
- return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
- 0);
- return 0;
-#endif
- }
- return -EINVAL;
-}
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
-static inline int gpio_direction_output(unsigned gpio, int value)
+static inline void gpio_intmask(unsigned gpio, int value)
{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- /* first set the gpio out value */
- ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
- value ? 1 << gpio : 0);
- /* then set the gpio mode */
- ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
- return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- /* first set the gpio out value */
- bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
- value ? 1 << gpio : 0);
- /* then set the gpio mode */
- bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
- 1 << gpio);
- return 0;
-#endif
- }
- return -EINVAL;
+ bcm47xx_gpio_intmask(1 << gpio, value ? 1 << gpio : 0);
}
-static inline int gpio_intmask(unsigned gpio, int value)
+static inline void gpio_polarity(unsigned gpio, int value)
{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
- 1 << gpio, value ? 1 << gpio : 0);
- return 0;
-#endif
- }
- return -EINVAL;
+ bcm47xx_gpio_polarity(1 << gpio, value ? 1 << gpio : 0);
}
-static inline int gpio_polarity(unsigned gpio, int value)
+static inline int irq_to_gpio(int gpio)
{
- switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
- ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
- bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
- 1 << gpio, value ? 1 << gpio : 0);
- return 0;
-#endif
- }
return -EINVAL;
}
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
#endif /* __BCM47XX_GPIO_H */