diff options
Diffstat (limited to 'arch/blackfin/mach-common/ints-priority-sc.c')
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-sc.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index 147f0731087..dec42acb5de 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -313,6 +313,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; + static void bfin_gpio_ack_irq(unsigned int irq) { u16 gpionr = irq - IRQ_PF0; @@ -352,9 +353,11 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) { unsigned int ret; u16 gpionr = irq - IRQ_PF0; + char buf[8]; if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, "IRQ"); + snprintf(buf, sizeof buf, "IRQ %d", irq); + ret = gpio_request(gpionr, buf); if (ret) return ret; } @@ -376,6 +379,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { unsigned int ret; + char buf[8]; u16 gpionr = irq - IRQ_PF0; if (type == IRQ_TYPE_PROBE) { @@ -388,7 +392,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, "IRQ"); + snprintf(buf, sizeof buf, "IRQ %d", irq); + ret = gpio_request(gpionr, buf); if (ret) return ret; } @@ -478,6 +483,10 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, static unsigned char irq2pint_lut[NR_PINTS]; static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; +static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS]; +static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; + + struct pin_int_t { unsigned int mask_set; unsigned int mask_clear; @@ -544,13 +553,20 @@ void init_pint_lut(void) } -static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; - static void bfin_gpio_ack_irq(unsigned int irq) { u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u8 bank = PINT_2_BANK(pint_val); + + if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { + if (pint[bank]->invert_set & pintbit) + pint[bank]->invert_clear = pintbit; + else + pint[bank]->invert_set = pintbit; + } + pint[bank]->request = pintbit; - pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val); SSYNC(); } @@ -560,6 +576,13 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq) u32 pintbit = PINT_BIT(pint_val); u8 bank = PINT_2_BANK(pint_val); + if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { + if (pint[bank]->invert_set & pintbit) + pint[bank]->invert_clear = pintbit; + else + pint[bank]->invert_set = pintbit; + } + pint[bank]->request = pintbit; pint[bank]->mask_clear = pintbit; SSYNC(); @@ -587,7 +610,8 @@ static void bfin_gpio_unmask_irq(unsigned int irq) static unsigned int bfin_gpio_irq_startup(unsigned int irq) { unsigned int ret; - u16 gpionr = irq - IRQ_PA0; + char buf[8]; + u16 gpionr = irq_to_gpio(irq); u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; if (pint_val == IRQ_NOT_AVAIL) { @@ -598,7 +622,8 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) } if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, "IRQ"); + snprintf(buf, sizeof buf, "IRQ %d", irq); + ret = gpio_request(gpionr, buf); if (ret) return ret; } @@ -611,16 +636,19 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq) { + u16 gpionr = irq_to_gpio(irq); + bfin_gpio_mask_irq(irq); - gpio_free(irq - IRQ_PA0); - gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0); + gpio_free(gpionr); + gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); } static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) { unsigned int ret; - u16 gpionr = irq - IRQ_PA0; + char buf[8]; + u16 gpionr = irq_to_gpio(irq); u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; u32 pintbit = PINT_BIT(pint_val); u8 bank = PINT_2_BANK(pint_val); @@ -638,7 +666,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { - ret = gpio_request(gpionr, "IRQ"); + snprintf(buf, sizeof buf, "IRQ %d", irq); + ret = gpio_request(gpionr, buf); if (ret) return ret; } @@ -651,28 +680,33 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) gpio_direction_input(gpionr); - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - pint[bank]->edge_set = pintbit; - } else { - pint[bank]->edge_clear = pintbit; - } - if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ else - pint[bank]->invert_set = pintbit; /* high or rising edge denoted by zero */ + pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */ - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) - pint[bank]->invert_set = pintbit; - else - pint[bank]->invert_set = pintbit; + if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - SSYNC(); + gpio_both_edge_triggered[bank] |= pintbit; - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + if (gpio_get_value(gpionr)) + pint[bank]->invert_set = pintbit; + else + pint[bank]->invert_clear = pintbit; + } else { + gpio_both_edge_triggered[bank] &= ~pintbit; + } + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + pint[bank]->edge_set = pintbit; set_irq_handler(irq, handle_edge_irq); - else + } else { + pint[bank]->edge_clear = pintbit; set_irq_handler(irq, handle_level_irq); + } + + SSYNC(); return 0; } |