diff options
Diffstat (limited to 'arch/mips/jz4740/gpio.c')
-rw-r--r-- | arch/mips/jz4740/gpio.c | 140 |
1 files changed, 38 insertions, 102 deletions
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 4397972949f..e1ddb95c05e 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -17,8 +17,6 @@ #include <linux/module.h> #include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/delay.h> @@ -30,6 +28,8 @@ #include <asm/mach-jz4740/base.h> +#include "irq.h" + #define JZ4740_GPIO_BASE_A (32*0) #define JZ4740_GPIO_BASE_B (32*1) #define JZ4740_GPIO_BASE_C (32*2) @@ -77,14 +77,10 @@ struct jz_gpio_chip { unsigned int irq; unsigned int irq_base; - uint32_t wakeup; - uint32_t suspend_mask; uint32_t edge_trigger_both; void __iomem *base; - spinlock_t lock; - struct gpio_chip gpio_chip; }; @@ -102,7 +98,8 @@ static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *g static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data) { - return irq_data_get_irq_chip_data(data); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + return gc->private; } static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) @@ -304,21 +301,15 @@ static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) { uint32_t flag; unsigned int gpio_irq; - unsigned int gpio_bank; struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc); - gpio_bank = JZ4740_IRQ_GPIO0 - irq; - flag = readl(chip->base + JZ_REG_GPIO_FLAG); - if (!flag) return; - gpio_irq = __fls(flag); + gpio_irq = chip->irq_base + __fls(flag); - jz_gpio_check_trigger_both(chip, irq); - - gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0); + jz_gpio_check_trigger_both(chip, gpio_irq); generic_handle_irq(gpio_irq); }; @@ -329,18 +320,12 @@ static inline void jz_gpio_set_irq_bit(struct irq_data *data, unsigned int reg) writel(IRQ_TO_BIT(data->irq), chip->base + reg); } -static void jz_gpio_irq_mask(struct irq_data *data) -{ - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET); -}; - static void jz_gpio_irq_unmask(struct irq_data *data) { struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); jz_gpio_check_trigger_both(chip, data->irq); - - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR); + irq_gc_unmask_enable_reg(data); }; /* TODO: Check if function is gpio */ @@ -353,18 +338,13 @@ static unsigned int jz_gpio_irq_startup(struct irq_data *data) static void jz_gpio_irq_shutdown(struct irq_data *data) { - jz_gpio_irq_mask(data); + irq_gc_mask_disable_reg(data); /* Set direction to input */ jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR); } -static void jz_gpio_irq_ack(struct irq_data *data) -{ - jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR); -}; - static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) { struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); @@ -408,35 +388,13 @@ static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) { struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); - spin_lock(&chip->lock); - if (on) - chip->wakeup |= IRQ_TO_BIT(data->irq); - else - chip->wakeup &= ~IRQ_TO_BIT(data->irq); - spin_unlock(&chip->lock); + irq_gc_set_wake(data, on); irq_set_irq_wake(chip->irq, on); + return 0; } -static struct irq_chip jz_gpio_irq_chip = { - .name = "GPIO", - .irq_mask = jz_gpio_irq_mask, - .irq_unmask = jz_gpio_irq_unmask, - .irq_ack = jz_gpio_irq_ack, - .irq_startup = jz_gpio_irq_startup, - .irq_shutdown = jz_gpio_irq_shutdown, - .irq_set_type = jz_gpio_irq_set_type, - .irq_set_wake = jz_gpio_irq_set_wake, - .flags = IRQCHIP_SET_TYPE_MASKED, -}; - -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - #define JZ4740_GPIO_CHIP(_bank) { \ .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ .gpio_chip = { \ @@ -458,64 +416,44 @@ static struct jz_gpio_chip jz4740_gpio_chips[] = { JZ4740_GPIO_CHIP(D), }; -static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip) -{ - chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); - writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); - writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); -} - -static int jz4740_gpio_suspend(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++) - jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]); - - return 0; -} - -static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip) +static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) { - uint32_t mask = chip->suspend_mask; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; - writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); - writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); -} + chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); -static void jz4740_gpio_resume(void) -{ - int i; + chip->irq = JZ4740_IRQ_INTC_GPIO(id); + irq_set_handler_data(chip->irq, chip); + irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler); - for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--) - jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]); -} + gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base, + chip->base, handle_level_irq); -static struct syscore_ops jz4740_gpio_syscore_ops = { - .suspend = jz4740_gpio_suspend, - .resume = jz4740_gpio_resume, -}; + gc->wake_enabled = IRQ_MSK(chip->gpio_chip.ngpio); + gc->private = chip; -static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) -{ - int irq; + ct = gc->chip_types; + ct->regs.enable = JZ_REG_GPIO_MASK_CLEAR; + ct->regs.disable = JZ_REG_GPIO_MASK_SET; + ct->regs.ack = JZ_REG_GPIO_FLAG_CLEAR; - spin_lock_init(&chip->lock); + ct->chip.name = "GPIO"; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = jz_gpio_irq_unmask; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_suspend = jz4740_irq_suspend; + ct->chip.irq_resume = jz4740_irq_resume; + ct->chip.irq_startup = jz_gpio_irq_startup; + ct->chip.irq_shutdown = jz_gpio_irq_shutdown; + ct->chip.irq_set_type = jz_gpio_irq_set_type; + ct->chip.irq_set_wake = jz_gpio_irq_set_wake; + ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; - chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); + irq_setup_generic_chip(gc, IRQ_MSK(chip->gpio_chip.ngpio), + IRQ_GC_INIT_NESTED_LOCK, 0, IRQ_NOPROBE | IRQ_LEVEL); gpiochip_add(&chip->gpio_chip); - - chip->irq = JZ4740_IRQ_INTC_GPIO(id); - irq_set_handler_data(chip->irq, chip); - irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler); - - for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_data(irq, chip); - irq_set_chip_and_handler(irq, &jz_gpio_irq_chip, - handle_level_irq); - } } static int __init jz4740_gpio_init(void) @@ -525,8 +463,6 @@ static int __init jz4740_gpio_init(void) for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); - register_syscore_ops(&jz4740_gpio_syscore_ops); - printk(KERN_INFO "JZ4740 GPIO initialized\n"); return 0; |