diff options
Diffstat (limited to 'target/linux/adm5120/files-2.6.26/arch')
-rw-r--r-- | target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c | 365 |
1 files changed, 162 insertions, 203 deletions
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 aed0038752..8143d31f67 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 <juhosg@openwrt.org> * @@ -25,60 +25,69 @@ #include <asm/mach-adm5120/adm5120_info.h> #include <asm/mach-adm5120/adm5120_switch.h> -#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); + t = __raw_readl(reg); + if ((t & PIN_IM(offset)) != 0) + t &= PIN_IV(offset); + else + t &= PIN_OV(offset); - return 0; + return (t) ? 1 : 0; } +EXPORT_SYMBOL(__adm5120_gpio0_get_value); -static inline int pins_direction_output(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 &= ~(PIN_IM(pin) | PIN_OV(pin)); - t |= PIN_OE(pin); + t = __raw_readl(reg); + if (value == 0) + t &= ~(PIN_OV(offset)); + else + t |= PIN_OV(offset); - if (value) - t |= PIN_OV(pin); + __raw_writel(t, reg); +} +EXPORT_SYMBOL(__adm5120_gpio0_set_value); - GPIO_WRITE(t, reg); +static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __adm5120_gpio0_get_value(offset); +} - return 0; +static void adm5120_gpio0_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio0_set_value(offset, value); } -static inline int pins_get_value(unsigned pin) +static int adm5120_gpio0_direction_input(struct gpio_chip *chip, + unsigned offset) { 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); - else - t &= PIN_OV(pin); + t = __raw_readl(reg); + t &= ~(PIN_OE(offset)); + t |= PIN_IM(offset); + __raw_writel(t, reg); - return (t) ? 1 : 0; + return 0; } -static inline void pins_set_value(unsigned pin, 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 = GPIO_READ(reg); - if (value == 0) - t &= ~(PIN_OV(pin)); - else - t |= PIN_OV(pin); + t = __raw_readl(reg); + t &= ~(PIN_IM(offset) | PIN_OV(offset)); + t |= PIN_OE(offset); + + if (value) + t |= PIN_OV(offset); - GPIO_WRITE(t, reg); + __raw_writel(t, reg); + + return 0; } -/* - * Helpers for GPIO lines in PORTx_LED registers - */ -static inline int leds_direction_input(unsigned led) +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; + u32 t, m; - reg = led_table[led].reg; - t = GPIO_READ(reg); - t &= ~(LED_MODE_MASK << led_table[led].mode_shift); - GPIO_WRITE(t, reg); + reg = gpio1_table[offset].reg; - return 0; + 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); -static inline int leds_direction_output(unsigned led, int 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); - - return 0; -} - -static inline int leds_get_value(unsigned led) -{ - void __iomem **reg; - u32 t, m; - - 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); + __raw_writel(t, reg); } -EXPORT_SYMBOL(adm5120_gpio_direction_input); +EXPORT_SYMBOL(__adm5120_gpio1_set_value); -int adm5120_gpio_direction_output(unsigned gpio, int value) +static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset) { - 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); + return __adm5120_gpio1_get_value(offset); } -EXPORT_SYMBOL(adm5120_gpio_direction_output); -int adm5120_gpio_get_value(unsigned gpio) +static void adm5120_gpio1_set_value(struct gpio_chip *chip, + unsigned offset, int value) { - if (gpio < ADM5120_GPIO_P0L0) - return pins_get_value(gpio); - - gpio -= ADM5120_GPIO_P0L0; - return leds_get_value(gpio); + __adm5120_gpio1_set_value(offset, value); } -EXPORT_SYMBOL(adm5120_gpio_get_value); -void adm5120_gpio_set_value(unsigned gpio, int value) +static int adm5120_gpio1_direction_input(struct gpio_chip *chip, + unsigned offset) { - 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; + void __iomem **reg; + u32 t; - 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; -} -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; + __adm5120_gpio1_set_value(offset, value); + return 0; } -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); + } |