diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c index aed003875..8143d31f6 100644 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c +++ b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c @@ -1,5 +1,5 @@ /* - * ADM5120 generic GPIO API support + * ADM5120 generic GPIO API support via GPIOLIB * * Copyright (C) 2007-2008 Gabor Juhos * @@ -25,60 +25,69 @@ #include #include -#define GPIO_READ(r) __raw_readl((r)) -#define GPIO_WRITE(v, r) __raw_writel((v), (r)) -#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+r) +#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r) -struct adm5120_gpio_line { - u32 flags; - const char *label; - int irq; +struct gpio1_desc { + void __iomem *reg; /* register address */ + u8 iv_shift; /* shift amount for input bit */ + u8 mode_shift; /* shift amount for mode bits */ }; -#define GPIO_FLAG_VALID 0x01 -#define GPIO_FLAG_USED 0x02 - -struct led_desc { - void __iomem *reg; /* LED register address */ - u8 iv_shift; /* shift amount for input bit */ - u8 mode_shift; /* shift amount for mode bits */ -}; - -#define LED_DESC(p, l) { \ - .reg = GPIO_REG(SWITCH_REG_PORT0_LED+((p) * 4)), \ - .iv_shift = LED0_IV_SHIFT + (l), \ - .mode_shift = (l) * 4 \ +#define GPIO1_DESC(p, l) { \ + .reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \ + .iv_shift = LED0_IV_SHIFT + (l), \ + .mode_shift = (l) * 4 \ } -static struct led_desc led_table[15] = { - LED_DESC(0, 0), LED_DESC(0, 1), LED_DESC(0, 2), - LED_DESC(1, 0), LED_DESC(1, 1), LED_DESC(1, 2), - LED_DESC(2, 0), LED_DESC(2, 1), LED_DESC(2, 2), - LED_DESC(3, 0), LED_DESC(3, 1), LED_DESC(3, 2), - LED_DESC(4, 0), LED_DESC(4, 1), LED_DESC(4, 2) +static struct gpio1_desc gpio1_table[15] = { + GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2), + GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2), + GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2), + GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2), + GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2) }; -static struct adm5120_gpio_line adm5120_gpio_map[ADM5120_GPIO_COUNT]; - static u32 gpio_conf2; -/*-------------------------------------------------------------------------*/ - -static inline int gpio_is_invalid(unsigned gpio) +int adm5120_gpio_to_irq(unsigned gpio) { - if ((gpio > ADM5120_GPIO_MAX) || - (adm5120_gpio_map[gpio].flags & GPIO_FLAG_VALID) == 0) - return 1; + int ret; - return 0; + switch (gpio) { + case ADM5120_GPIO_PIN2: + ret = ADM5120_IRQ_GPIO2; + break; + case ADM5120_GPIO_PIN4: + ret = ADM5120_IRQ_GPIO4; + break; + default: + ret = -EINVAL; + break; + } + + return ret; } +EXPORT_SYMBOL(adm5120_gpio_to_irq); -static inline int gpio_is_used(unsigned gpio) +int adm5120_irq_to_gpio(unsigned irq) { - return ((adm5120_gpio_map[gpio].flags & GPIO_FLAG_USED) != 0); -} + int ret; -/*-------------------------------------------------------------------------*/ + switch (irq) { + case ADM5120_IRQ_GPIO2: + ret = ADM5120_GPIO_PIN2; + break; + case ADM5120_IRQ_GPIO4: + ret = ADM5120_GPIO_PIN4; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL(adm5120_irq_to_gpio); /* * Helpers for GPIO lines in GPIO_CONF0 register @@ -88,97 +97,125 @@ static inline int gpio_is_used(unsigned gpio) #define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p) #define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p) -static inline int pins_direction_input(unsigned pin) +int __adm5120_gpio0_get_value(unsigned offset) { void __iomem **reg; u32 t; reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - t = GPIO_READ(reg); - t &= ~(PIN_OE(pin)); - t |= PIN_IM(pin); - GPIO_WRITE(t, reg); - - return 0; -} - -static inline int pins_direction_output(unsigned pin, int value) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = GPIO_READ(reg); - t &= ~(PIN_IM(pin) | PIN_OV(pin)); - t |= PIN_OE(pin); - - if (value) - t |= PIN_OV(pin); - - GPIO_WRITE(t, reg); - - return 0; -} - -static inline int pins_get_value(unsigned pin) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = GPIO_READ(reg); - if ((t & PIN_IM(pin)) != 0) - t &= PIN_IV(pin); + t = __raw_readl(reg); + if ((t & PIN_IM(offset)) != 0) + t &= PIN_IV(offset); else - t &= PIN_OV(pin); + t &= PIN_OV(offset); return (t) ? 1 : 0; } +EXPORT_SYMBOL(__adm5120_gpio0_get_value); -static inline void pins_set_value(unsigned pin, int value) +void __adm5120_gpio0_set_value(unsigned offset, int value) { void __iomem **reg; u32 t; reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - t = GPIO_READ(reg); + t = __raw_readl(reg); if (value == 0) - t &= ~(PIN_OV(pin)); + t &= ~(PIN_OV(offset)); else - t |= PIN_OV(pin); + t |= PIN_OV(offset); - GPIO_WRITE(t, reg); + __raw_writel(t, reg); +} +EXPORT_SYMBOL(__adm5120_gpio0_set_value); + +static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __adm5120_gpio0_get_value(offset); } -/* - * Helpers for GPIO lines in PORTx_LED registers - */ -static inline int leds_direction_input(unsigned led) +static void adm5120_gpio0_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio0_set_value(offset, value); +} + +static int adm5120_gpio0_direction_input(struct gpio_chip *chip, + unsigned offset) { void __iomem **reg; u32 t; - reg = led_table[led].reg; - t = GPIO_READ(reg); - t &= ~(LED_MODE_MASK << led_table[led].mode_shift); - GPIO_WRITE(t, reg); + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + t &= ~(PIN_OE(offset)); + t |= PIN_IM(offset); + __raw_writel(t, reg); return 0; } -static inline int leds_direction_output(unsigned led, int value) +static int adm5120_gpio0_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem **reg; + u32 t; + + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + t &= ~(PIN_IM(offset) | PIN_OV(offset)); + t |= PIN_OE(offset); + + if (value) + t |= PIN_OV(offset); + + __raw_writel(t, reg); + + return 0; +} + +static struct gpio_chip adm5120_gpio0_chip = { + .label = "adm5120 gpio0", + .get = adm5120_gpio0_get_value, + .set = adm5120_gpio0_set_value, + .direction_input = adm5120_gpio0_direction_input, + .direction_output = adm5120_gpio0_direction_output, + .base = ADM5120_GPIO_PIN0, + .ngpio = ADM5120_GPIO_PIN7 - ADM5120_GPIO_PIN0 + 1, +}; + +int __adm5120_gpio1_get_value(unsigned offset) +{ + void __iomem **reg; + u32 t, m; + + reg = gpio1_table[offset].reg; + + t = __raw_readl(reg); + m = (t >> gpio1_table[offset].mode_shift) & LED_MODE_MASK; + if (m == LED_MODE_INPUT) + return (t >> gpio1_table[offset].iv_shift) & 1; + + if (m == LED_MODE_OUT_LOW) + return 0; + + return 1; +} +EXPORT_SYMBOL(__adm5120_gpio1_get_value); + +void __adm5120_gpio1_set_value(unsigned offset, int value) { void __iomem **reg; u32 t, s; - reg = led_table[led].reg; - s = led_table[led].mode_shift; + reg = gpio1_table[offset].reg; + s = gpio1_table[offset].mode_shift; - t = GPIO_READ(reg); + t = __raw_readl(reg); t &= ~(LED_MODE_MASK << s); switch (value) { @@ -202,137 +239,58 @@ static inline int leds_direction_output(unsigned led, int value) break; } - GPIO_WRITE(t, reg); + __raw_writel(t, reg); +} +EXPORT_SYMBOL(__adm5120_gpio1_set_value); - return 0; +static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __adm5120_gpio1_get_value(offset); } -static inline int leds_get_value(unsigned led) +static void adm5120_gpio1_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio1_set_value(offset, value); +} + +static int adm5120_gpio1_direction_input(struct gpio_chip *chip, + unsigned offset) { void __iomem **reg; - u32 t, m; + u32 t; - reg = led_table[led].reg; - - t = GPIO_READ(reg); - m = (t >> led_table[led].mode_shift) & LED_MODE_MASK; - if (m == LED_MODE_INPUT) - return (t >> led_table[led].iv_shift) & 1; - - if (m == LED_MODE_OUT_LOW) - return 0; - - return 1; -} - -/*-------------------------------------------------------------------------*/ - -/* - * Main GPIO support routines - */ -int adm5120_gpio_direction_input(unsigned gpio) -{ - if (gpio_is_invalid(gpio)) - return -EINVAL; - - if (gpio < ADM5120_GPIO_P0L0) - return pins_direction_input(gpio); - - gpio -= ADM5120_GPIO_P0L0; - return leds_direction_input(gpio); -} -EXPORT_SYMBOL(adm5120_gpio_direction_input); - -int adm5120_gpio_direction_output(unsigned gpio, int value) -{ - if (gpio_is_invalid(gpio)) - return -EINVAL; - - if (gpio < ADM5120_GPIO_P0L0) - return pins_direction_output(gpio, value); - - gpio -= ADM5120_GPIO_P0L0; - return leds_direction_output(gpio, value); -} -EXPORT_SYMBOL(adm5120_gpio_direction_output); - -int adm5120_gpio_get_value(unsigned gpio) -{ - if (gpio < ADM5120_GPIO_P0L0) - return pins_get_value(gpio); - - gpio -= ADM5120_GPIO_P0L0; - return leds_get_value(gpio); -} -EXPORT_SYMBOL(adm5120_gpio_get_value); - -void adm5120_gpio_set_value(unsigned gpio, int value) -{ - if (gpio < ADM5120_GPIO_P0L0) { - pins_set_value(gpio, value); - return; - } - - gpio -= ADM5120_GPIO_P0L0; - leds_direction_output(gpio, value); -} -EXPORT_SYMBOL(adm5120_gpio_set_value); - -int adm5120_gpio_request(unsigned gpio, const char *label) -{ - if (gpio_is_invalid(gpio)) - return -EINVAL; - - if (gpio_is_used(gpio)) - return -EBUSY; - - adm5120_gpio_map[gpio].flags |= GPIO_FLAG_USED; - adm5120_gpio_map[gpio].label = label; + reg = gpio1_table[offset].reg; + t = __raw_readl(reg); + t &= ~(LED_MODE_MASK << gpio1_table[offset].mode_shift); + __raw_writel(t, reg); return 0; } -EXPORT_SYMBOL(adm5120_gpio_request); -void adm5120_gpio_free(unsigned gpio) +static int adm5120_gpio1_direction_output(struct gpio_chip *chip, + unsigned offset, int value) { - if (gpio_is_invalid(gpio)) - return; - - adm5120_gpio_map[gpio].flags &= ~GPIO_FLAG_USED; - adm5120_gpio_map[gpio].label = NULL; + __adm5120_gpio1_set_value(offset, value); + return 0; } -EXPORT_SYMBOL(adm5120_gpio_free); -int adm5120_gpio_to_irq(unsigned gpio) -{ - if (gpio > ADM5120_GPIO_MAX) - return -EINVAL; - - return adm5120_gpio_map[gpio].irq; -} -EXPORT_SYMBOL(adm5120_gpio_to_irq); - -int adm5120_irq_to_gpio(unsigned irq) -{ - int i; - - for (i = 0; i < ADM5120_GPIO_COUNT; i++) - if (adm5120_gpio_map[i].irq == irq) - return i; - - return -EINVAL; -} -EXPORT_SYMBOL(adm5120_irq_to_gpio); - -/*-------------------------------------------------------------------------*/ +static struct gpio_chip adm5120_gpio1_chip = { + .label = "adm5120 gpio1", + .get = adm5120_gpio1_get_value, + .set = adm5120_gpio1_set_value, + .direction_input = adm5120_gpio1_direction_input, + .direction_output = adm5120_gpio1_direction_output, + .base = ADM5120_GPIO_P0L0, + .ngpio = ADM5120_GPIO_P4L2 - ADM5120_GPIO_P0L0 + 1, +}; void __init adm5120_gpio_csx0_enable(void) { gpio_conf2 |= GPIO_CONF2_CSX0; SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - adm5120_gpio_map[ADM5120_GPIO_PIN1].flags &= ~GPIO_FLAG_VALID; - adm5120_gpio_map[ADM5120_GPIO_PIN2].irq = ADM5120_IRQ_GPIO2; + gpio_request(ADM5120_GPIO_PIN1, "CSX0"); } void __init adm5120_gpio_csx1_enable(void) @@ -340,9 +298,7 @@ void __init adm5120_gpio_csx1_enable(void) gpio_conf2 |= GPIO_CONF2_CSX1; SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - adm5120_gpio_map[ADM5120_GPIO_PIN3].flags &= ~GPIO_FLAG_VALID; - if (adm5120_package_bga()) - adm5120_gpio_map[ADM5120_GPIO_PIN4].irq = ADM5120_IRQ_GPIO4; + gpio_request(ADM5120_GPIO_PIN3, "CSX1"); } void __init adm5120_gpio_ew_enable(void) @@ -350,23 +306,26 @@ void __init adm5120_gpio_ew_enable(void) gpio_conf2 |= GPIO_CONF2_EW; SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - adm5120_gpio_map[ADM5120_GPIO_PIN0].flags &= ~GPIO_FLAG_VALID; + gpio_request(ADM5120_GPIO_PIN0, "EW"); } void __init adm5120_gpio_init(void) { - int i; + int err; - gpio_conf2 = 0; SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - for (i = 0; i < ADM5120_GPIO_COUNT; i++) - adm5120_gpio_map[i].flags = GPIO_FLAG_VALID; - if (adm5120_package_pqfp()) { - adm5120_gpio_map[ADM5120_GPIO_PIN4].flags &= ~GPIO_FLAG_VALID; - adm5120_gpio_map[ADM5120_GPIO_PIN5].flags &= ~GPIO_FLAG_VALID; - adm5120_gpio_map[ADM5120_GPIO_PIN6].flags &= ~GPIO_FLAG_VALID; - adm5120_gpio_map[ADM5120_GPIO_PIN7].flags &= ~GPIO_FLAG_VALID; + gpiochip_reserve(ADM5120_GPIO_PIN4, 4); + adm5120_gpio0_chip.ngpio = 4; } + + err = gpiochip_add(&adm5120_gpio0_chip); + if (err) + panic("cannot add ADM5120 GPIO0 chip, error=%d", err); + + err = gpiochip_add(&adm5120_gpio1_chip); + if (err) + panic("cannot add ADM5120 GPIO1 chip, error=%d", err); + } diff --git a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/gpio.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/gpio.h index 6007693d7..7ba7efca1 100644 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/gpio.h +++ b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/gpio.h @@ -9,8 +9,12 @@ * */ -#ifndef _ASM_MACH_ADM5120_GPIO_H -#define _ASM_MACH_ADM5120_GPIO_H +#ifndef _ASM_MIPS_MACH_ADM5120_GPIO_H +#define _ASM_MIPS_MACH_ADM5120_GPIO_H + +#define ARCH_NR_GPIOS 64 + +#include #include @@ -55,46 +59,45 @@ #define ADM5120_GPIO_10M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_10M_ACT) #define ADM5120_GPIO_100M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_100M_ACT) -extern int adm5120_gpio_direction_input(unsigned gpio); -extern int adm5120_gpio_direction_output(unsigned gpio, int value); -extern int adm5120_gpio_get_value(unsigned gpio); -extern void adm5120_gpio_set_value(unsigned gpio, int value); -extern int adm5120_gpio_request(unsigned gpio, const char *label); -extern void adm5120_gpio_free(unsigned gpio); -extern int adm5120_gpio_to_irq(unsigned gpio); -extern int adm5120_irq_to_gpio(unsigned irq); - -/* - * Wrappers for the generic GPIO layer - */ -static inline int gpio_direction_input(unsigned gpio) -{ - return adm5120_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return adm5120_gpio_direction_output(gpio,value); -} +extern int __adm5120_gpio0_get_value(unsigned gpio); +extern void __adm5120_gpio0_set_value(unsigned gpio, int value); +extern int __adm5120_gpio1_get_value(unsigned gpio); +extern void __adm5120_gpio1_set_value(unsigned gpio, int value); +extern int adm5120_gpio_to_irq(unsigned gpio); +extern int adm5120_irq_to_gpio(unsigned irq); static inline int gpio_get_value(unsigned gpio) { - return adm5120_gpio_get_value(gpio); + int ret; + + switch (gpio) { + case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: + ret = __adm5120_gpio0_get_value(gpio); + break; + case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: + ret = __adm5120_gpio1_get_value(gpio - ADM5120_GPIO_P0L0); + break; + default: + ret = __gpio_get_value(gpio); + break; + } + + return ret; } static inline void gpio_set_value(unsigned gpio, int value) { - adm5120_gpio_set_value(gpio, value); -} - -static inline int gpio_request(unsigned gpio, const char *label) -{ - return adm5120_gpio_request(gpio, label); -} - -static inline void gpio_free(unsigned gpio) -{ - adm5120_gpio_free(gpio); + switch (gpio) { + case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: + __adm5120_gpio0_set_value(gpio, value); + break; + case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: + __adm5120_gpio1_set_value(gpio - ADM5120_GPIO_P0L0, value); + break; + default: + __gpio_set_value(gpio, value); + break; + } } static inline int gpio_to_irq(unsigned gpio) @@ -107,6 +110,6 @@ static inline int irq_to_gpio(unsigned irq) return adm5120_irq_to_gpio(irq); } -#include /* cansleep wrappers */ +#define gpio_cansleep __gpio_cansleep -#endif /* _ASM_MACH_ADM5120_GPIO_H */ +#endif /* _ASM_MIPS_MACH_ADM5120_GPIO_H */ diff --git a/target/linux/adm5120/patches-2.6.26/001-adm5120.patch b/target/linux/adm5120/patches-2.6.26/001-adm5120.patch index 334362c21..52c8c812f 100644 --- a/target/linux/adm5120/patches-2.6.26/001-adm5120.patch +++ b/target/linux/adm5120/patches-2.6.26/001-adm5120.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -18,6 +18,20 @@ +@@ -18,6 +18,21 @@ prompt "System type" default SGI_IP22 @@ -16,6 +16,7 @@ + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_32BIT_KERNEL + select GENERIC_GPIO ++ select HAVE_GPIO_LIB + select SWAP_IO_SPACE if CPU_BIG_ENDIAN + config MACH_ALCHEMY diff --git a/target/linux/adm5120/router_be/config-2.6.26 b/target/linux/adm5120/router_be/config-2.6.26 index 4e05db860..bc07fbb2f 100644 --- a/target/linux/adm5120/router_be/config-2.6.26 +++ b/target/linux/adm5120/router_be/config-2.6.26 @@ -83,10 +83,13 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_GPIO=y # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +# CONFIG_GPIO_MCP23S08 is not set +CONFIG_GPIO_SYSFS=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y # CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_GPIO_LIB=y CONFIG_HAVE_IDE=y # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set diff --git a/target/linux/adm5120/router_le/config-2.6.26 b/target/linux/adm5120/router_le/config-2.6.26 index 742f9ba5a..c340a678a 100644 --- a/target/linux/adm5120/router_le/config-2.6.26 +++ b/target/linux/adm5120/router_le/config-2.6.26 @@ -104,10 +104,13 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_GPIO=y # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +# CONFIG_GPIO_MCP23S08 is not set +CONFIG_GPIO_SYSFS=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y # CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_GPIO_LIB=y CONFIG_HAVE_IDE=y # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set