diff --git a/target/linux/atheros/config-2.6.37 b/target/linux/atheros/config-2.6.37 index eee22085ecd..aaac19646e5 100644 --- a/target/linux/atheros/config-2.6.37 +++ b/target/linux/atheros/config-2.6.37 @@ -52,7 +52,9 @@ CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GPIOLIB=y CONFIG_GPIO_DEVICE=y +CONFIG_GPIO_SYSFS=y # CONFIG_HAMRADIO is not set # CONFIG_HARDLOCKUP_DETECTOR is not set CONFIG_HARDWARE_WATCHPOINTS=y diff --git a/target/linux/atheros/patches-2.6.37/300-sysfs_for_gpio.patch b/target/linux/atheros/patches-2.6.37/300-sysfs_for_gpio.patch new file mode 100644 index 00000000000..0cf2a8f7d4d --- /dev/null +++ b/target/linux/atheros/patches-2.6.37/300-sysfs_for_gpio.patch @@ -0,0 +1,534 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -111,7 +111,7 @@ config ATHEROS_AR231X + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_32BIT_KERNEL +- select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB + select SYS_HAS_EARLY_PRINTK + help + Support for AR231x and AR531x based boards +--- a/arch/mips/ar231x/Kconfig ++++ b/arch/mips/ar231x/Kconfig +@@ -13,7 +13,6 @@ config ATHEROS_AR2315 + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN +- select GENERIC_GPIO + default y + + config ATHEROS_AR2315_PCI +--- a/arch/mips/ar231x/ar2315.c ++++ b/arch/mips/ar231x/ar2315.c +@@ -23,12 +23,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include +-#include + + #include + #include +@@ -312,17 +312,6 @@ ar2315_irq_init(void) + setup_irq(AR2315_IRQ_MISC_INTRS, &cascade); + } + +-const struct ar231x_gpiodev ar2315_gpiodev; +- +-static u32 +-ar2315_gpio_get_output(void) +-{ +- u32 reg; +- reg = ar231x_read_reg(AR2315_GPIO_CR); +- reg &= ar2315_gpiodev.valid_mask; +- return reg; +-} +- + static u32 + ar2315_gpio_set_output(u32 mask, u32 val) + { +@@ -336,11 +325,11 @@ ar2315_gpio_set_output(u32 mask, u32 val + } + + static u32 +-ar2315_gpio_get(void) ++ar2315_gpio_get(u32 valid_mask) + { + u32 reg; + reg = ar231x_read_reg(AR2315_GPIO_DI); +- reg &= ar2315_gpiodev.valid_mask; ++ reg &= valid_mask; + return reg; + } + +@@ -355,14 +344,75 @@ ar2315_gpio_set(u32 mask, u32 value) + return reg; + } + +-const struct ar231x_gpiodev ar2315_gpiodev = { ++/* ++ * gpiolib implementation. Original legacy mask based methods ++ * preserved for now. ++ */ ++static int ++ar2315_gpio_get_value(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ u32 rett; ++ if (!(gpch->valid_mask & mask)) ++ return 0; ++ rett = ar2315_gpio_get(gpch->valid_mask); // legacy code ++ return !!(rett & mask); ++} ++ ++static void ++ar2315_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return; ++ ar2315_gpio_set(mask, (!!value) * mask); // legacy ++} ++ ++static int ++ar2315_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return -ENXIO; ++ ar2315_gpio_set_output(mask, 0); // legacy ++ return 0; ++} ++ ++static int ++ar2315_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return -ENXIO; ++ ar2315_gpio_set_output(mask, mask); // both legacy ++ ar2315_gpio_set(mask, (!!value) * mask); ++ return 0; ++} ++ ++static struct ar231x_gpio_chip ar2315_gpio_chip = { + .valid_mask = (1 << 22) - 1, +- .get_output = ar2315_gpio_get_output, +- .set_output = ar2315_gpio_set_output, +- .get = ar2315_gpio_get, +- .set = ar2315_gpio_set, ++ .chip = { ++ .label = "ar2315-gpio", ++ .direction_input = ar2315_gpio_direction_input, ++ .direction_output = ar2315_gpio_direction_output, ++ .set = ar2315_gpio_set_value, ++ .get = ar2315_gpio_get_value, ++ .base = 0, ++ .ngpio = AR531X_GPIO_IRQ_COUNT, // 22 ++ } + }; + ++// end of gpiolib ++ ++ + static struct ar231x_eth ar2315_eth_data = { + .reset_base = AR2315_RESET, + .reset_mac = AR2315_RESET_ENET0, +@@ -496,7 +546,7 @@ static struct platform_device ar2315_gpi + }; + + static void __init +-ar2315_init_gpio(void) ++ar2315_init_gpio_leds(void) + { + static char led_names[6][6]; + int i, led = 0; +@@ -522,7 +572,7 @@ ar2315_init_gpio(void) + platform_device_register(&ar2315_gpio_leds); + } + #else +-static inline void ar2315_init_gpio(void) ++static inline void ar2315_init_gpio_leds(void) + { + } + #endif +@@ -537,7 +587,7 @@ ar2315_init_devices(void) + ar231x_find_config(ar2315_flash_limit()); + ar2315_eth_data.macaddr = ar231x_board.config->enet0_mac; + +- ar2315_init_gpio(); ++ ar2315_init_gpio_leds(); + platform_device_register(&ar2315_wdt); + platform_device_register(&ar2315_spiflash); + ar231x_add_ethernet(0, KSEG1ADDR(AR2315_ENET0), AR2315_IRQ_ENET0_INTRS, +@@ -633,6 +683,25 @@ ar2315_time_init(void) + mips_hpt_frequency = ar2315_cpu_frequency() / 2; + } + ++int __init ++ar2315_gpio_init(void) ++{ ++ int ret; ++ struct ar231x_gpio_chip *gpch; ++ gpch = &ar2315_gpio_chip; ++ ret = gpiochip_add(&gpch->chip); ++ if (ret) { ++ printk(KERN_ERR "%s: failed to add gpiochip\n", ++ gpch->chip.label); ++ return ret; ++ } ++ printk(KERN_INFO "%s: registered %d GPIOs\n", ++ gpch->chip.label, gpch->chip.ngpio); ++ return ret; ++} ++ ++ ++ + void __init + ar2315_prom_init(void) + { +@@ -659,7 +728,7 @@ ar2315_prom_init(void) + ar231x_devtype = DEV_TYPE_AR2315; + break; + } +- ar231x_gpiodev = &ar2315_gpiodev; ++ ar2315_gpio_init(); + ar231x_board.devid = devid; + } + +--- a/arch/mips/ar231x/ar5312.c ++++ b/arch/mips/ar231x/ar5312.c +@@ -23,12 +23,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include +-#include + + #include + #include +@@ -160,17 +160,6 @@ void __init ar5312_irq_init(void) + setup_irq(AR5312_IRQ_MISC_INTRS, &cascade); + } + +-const struct ar231x_gpiodev ar5312_gpiodev; +- +-static u32 +-ar5312_gpio_get_output(void) +-{ +- u32 reg; +- reg = ~(ar231x_read_reg(AR531X_GPIO_CR)); +- reg &= ar5312_gpiodev.valid_mask; +- return reg; +-} +- + static u32 + ar5312_gpio_set_output(u32 mask, u32 val) + { +@@ -184,11 +173,11 @@ ar5312_gpio_set_output(u32 mask, u32 val + } + + static u32 +-ar5312_gpio_get(void) ++ar5312_gpio_get(u32 valid_mask) + { + u32 reg; + reg = ar231x_read_reg(AR531X_GPIO_DI); +- reg &= ar5312_gpiodev.valid_mask; ++ reg &= valid_mask; + return reg; + } + +@@ -203,14 +192,72 @@ ar5312_gpio_set(u32 mask, u32 value) + return reg; + } + +-const struct ar231x_gpiodev ar5312_gpiodev = { +- .valid_mask = (1 << 8) - 1, +- .get_output = ar5312_gpio_get_output, +- .set_output = ar5312_gpio_set_output, +- .get = ar5312_gpio_get, +- .set = ar5312_gpio_set, ++/* ++ * gpiolib implementations. Original mask based methods preserved ++ */ ++static int ++ar5312_gpio_get_value(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ u32 rett; ++ if (!(gpch->valid_mask & mask)) ++ return 0; ++ rett = ar5312_gpio_get(gpch->valid_mask); ++ return !!(rett & mask); ++} ++ ++static void ++ar5312_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return; ++ ar5312_gpio_set(mask, (!!value) * mask); ++} ++ ++static int ++ar5312_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return -ENXIO; ++ ar5312_gpio_set_output(mask, 0); ++ return 0; ++} ++static int ++ar5312_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) ++{ ++ struct ar231x_gpio_chip *gpch = ++ container_of(chip, struct ar231x_gpio_chip, chip); ++ u32 mask = 1 << gpio; ++ if (!(gpch->valid_mask & mask)) ++ return -ENXIO; ++ ar5312_gpio_set_output(mask, mask); ++ ar5312_gpio_set(mask, (!!value) * mask); ++ return 0; ++} ++ ++static struct ar231x_gpio_chip ar5312_gpio_chip = { ++ .valid_mask = (1 << 22) - 1, ++ .chip = { ++ .label = "ar5312-gpio", ++ .direction_input = ar5312_gpio_direction_input, ++ .direction_output = ar5312_gpio_direction_output, ++ .set = ar5312_gpio_set_value, ++ .get = ar5312_gpio_get_value, ++ .base = 0, ++ .ngpio = AR531X_GPIO_IRQ_COUNT, // 22 ++ } + }; + ++// end of gpiolib ++ + static struct physmap_flash_data ar5312_flash_data = { + .width = 2, + }; +@@ -486,6 +533,22 @@ ar5312_time_init(void) + mips_hpt_frequency = ar5312_cpu_frequency() / 2; + } + ++int __init ++ar5312_gpio_init(void) ++{ ++ int ret; ++ struct ar231x_gpio_chip *gpch; ++ gpch = &ar5312_gpio_chip; ++ ret = gpiochip_add(&gpch->chip); ++ if (ret) { ++ printk(KERN_ERR "%s: failed to add gpiochip\n", ++ gpch->chip.label); ++ return ret; ++ } ++ printk(KERN_INFO "%s: registered %d GPIOs\n", ++ gpch->chip.label, gpch->chip.ngpio); ++ return ret; ++} + + void __init + ar5312_prom_init(void) +@@ -509,7 +572,7 @@ ar5312_prom_init(void) + devid >>= AR531X_REV_WMAC_MIN_S; + devid &= AR531X_REV_CHIP; + ar231x_board.devid = (u16) devid; +- ar231x_gpiodev = &ar5312_gpiodev; ++ ar5312_gpio_init(); + } + + void __init +--- a/arch/mips/ar231x/devices.c ++++ b/arch/mips/ar231x/devices.c +@@ -12,8 +12,6 @@ + + struct ar231x_board_config ar231x_board; + int ar231x_devtype = DEV_TYPE_UNKNOWN; +-const struct ar231x_gpiodev *ar231x_gpiodev; +-EXPORT_SYMBOL(ar231x_gpiodev); + + static struct resource ar231x_eth0_res[] = { + { +--- a/arch/mips/ar231x/devices.h ++++ b/arch/mips/ar231x/devices.h +@@ -1,5 +1,6 @@ + #ifndef __AR231X_DEVICES_H + #define __AR231X_DEVICES_H ++#include + + enum { + /* handled by ar5312.c */ +@@ -34,4 +35,8 @@ static inline bool is_5312(void) + return !is_2315(); + } + ++struct ar231x_gpio_chip { ++ u32 valid_mask; ++ struct gpio_chip chip; ++}; + #endif +--- a/arch/mips/ar231x/reset.c ++++ b/arch/mips/ar231x/reset.c +@@ -6,11 +6,11 @@ + #include + #include + #include ++#include + #include + #include + #include + #include +-#include + #include "devices.h" + + #define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ(ar231x_board.config->resetConfigGpio)) +@@ -85,13 +85,12 @@ static void + reset_button_poll(unsigned long unused) + { + struct event_t *event; +- int gpio = ~0; ++ int gpio = 0; + + if(!no_release_workaround) + return; + +- gpio = ar231x_gpiodev->get(); +- gpio &= (1 << (AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE)); ++ gpio = gpio_get_value(AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE); + if(gpio) { + rst_button_timer.expires = jiffies + (HZ / 4); + add_timer(&rst_button_timer); +@@ -113,7 +112,7 @@ button_handler(int irq, void *dev_id) + { + static int pressed = 0; + struct event_t *event; +- u32 gpio = ~0; ++ u32 gpio = 0; + + event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); + if (!event) +@@ -121,7 +120,7 @@ button_handler(int irq, void *dev_id) + + pressed = !pressed; + +- gpio = ar231x_gpiodev->get() & (1 << (irq - AR531X_GPIO_IRQ_BASE)); ++ gpio = gpio_get_value(irq - AR531X_GPIO_IRQ_BASE); + + event->set = gpio; + if(!event->set) +--- a/arch/mips/include/asm/mach-ar231x/gpio.h ++++ b/arch/mips/include/asm/mach-ar231x/gpio.h +@@ -3,66 +3,15 @@ + + #include + +-struct ar231x_gpiodev { +- u32 valid_mask; +- u32 (*get_output)(void); +- u32 (*set_output)(u32 mask, u32 val); +- u32 (*get)(void); +- u32 (*set)(u32 mask, u32 val); +-}; +- +-extern const struct ar231x_gpiodev *ar231x_gpiodev; ++#define gpio_get_value __gpio_get_value ++#define gpio_set_value __gpio_set_value ++#define gpio_cansleep __gpio_cansleep + + /* + * Wrappers for the generic GPIO layer + */ + +-static inline int gpio_direction_input(unsigned gpio) { +- u32 mask = 1 << gpio; +- +- if (!(ar231x_gpiodev->valid_mask & mask)) +- return -ENXIO; +- +- ar231x_gpiodev->set_output(mask, 0); +- return 0; +-} +- +-static inline void gpio_set_value(unsigned gpio, int value) { +- u32 mask = 1 << gpio; +- +- if (!(ar231x_gpiodev->valid_mask & mask)) +- return; +- +- ar231x_gpiodev->set(mask, (!!value) * mask); +-} +- +-static inline int gpio_direction_output(unsigned gpio, int value) { +- u32 mask = 1 << gpio; +- +- if (!(ar231x_gpiodev->valid_mask & mask)) +- return -ENXIO; +- +- ar231x_gpiodev->set_output(mask, mask); +- ar231x_gpiodev->set(mask, (!!value) * mask); +- return 0; +-} +- +-/* Reads the gpio pin. Unchecked function */ +-static inline int gpio_get_value(unsigned gpio) { +- u32 mask = 1 << gpio; +- +- if (!(ar231x_gpiodev->valid_mask & mask)) +- return 0; +- +- return !!(ar231x_gpiodev->get() & mask); +-} +- +-static inline int gpio_request(unsigned gpio, const char *label) { +- return 0; +-} +- +-static inline void gpio_free(unsigned gpio) { +-} ++/* not sure if these are used? */ + + /* Returns IRQ to attach for gpio. Unchecked function */ + static inline int gpio_to_irq(unsigned gpio) { +@@ -74,11 +23,6 @@ static inline int irq_to_gpio(unsigned i + return (irq - (AR531X_GPIO_IRQ(0))); + } + +-static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) +-{ +- return -ENOSYS; +-} +- + #include /* cansleep wrappers */ + + #endif