Gitweb: http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3c9a071d77e007464952a2d41b6686d98eb3f0b8 Commit: 3c9a071d77e007464952a2d41b6686d98eb3f0b8 Parent: 7ca722533979d47563e75a40c86c405153818b83 Author: Herbert Valerio Riedel <[EMAIL PROTECTED]> AuthorDate: Mon Nov 26 18:49:08 2007 +0100 Committer: Russell King <[EMAIL PROTECTED]> CommitDate: Sat Jan 26 14:37:31 2008 +0000
[ARM] 4670/1: ep93xx: implement IRQT_BOTHEDGE gpio irq sense type Having a both-edge sensitive irq trigger type is required for the generic gpio-keys input driver; alas the ep93xx does not support both-edge gpio triggers in hardware, so this patch implements them by switching edge polarity on each triggered interrupt. This is the same approach as taken by the Orion SoC both-edge gpio irq support implementation. Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]> Acked-by: Lennert Buytenhek <[EMAIL PROTECTED]> Signed-off-by: Russell King <[EMAIL PROTECTED]> --- arch/arm/mach-ep93xx/core.c | 64 +++++++++++++++++++++++++++++++++++------- 1 files changed, 53 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 58957d7..2788da0 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -3,6 +3,7 @@ * Core routines for Cirrus EP93xx chips. * * Copyright (C) 2006 Lennert Buytenhek <[EMAIL PROTECTED]> + * Copyright (C) 2007 Herbert Valerio Riedel <[EMAIL PROTECTED]> * * Thanks go to Michael Burian and Ray Lehtiniemi for their key * role in the ep93xx linux community. @@ -315,12 +316,29 @@ static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) desc_handle_irq(gpio_irq, irq_desc + gpio_irq); } +static void ep93xx_gpio_irq_ack(unsigned int irq) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + int port_mask = 1 << (line & 7); + + if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) { + gpio_int_type2[port] ^= port_mask; /* switch edge direction */ + update_gpio_int_params(port); + } + + __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +} + static void ep93xx_gpio_irq_mask_ack(unsigned int irq) { int line = irq_to_gpio(irq); int port = line >> 3; int port_mask = 1 << (line & 7); + if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) + gpio_int_type2[port] ^= port_mask; /* switch edge direction */ + gpio_int_unmasked[port] &= ~port_mask; update_gpio_int_params(port); @@ -353,31 +371,54 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq) */ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) { + struct irq_desc *desc = irq_desc + irq; const int gpio = irq_to_gpio(irq); const int port = gpio >> 3; const int port_mask = 1 << (gpio & 7); ep93xx_gpio_set_direction(gpio, GPIO_IN); - if (type & IRQT_RISING) { - gpio_int_enabled[port] |= port_mask; + switch (type) { + case IRQT_RISING: gpio_int_type1[port] |= port_mask; gpio_int_type2[port] |= port_mask; - } else if (type & IRQT_FALLING) { - gpio_int_enabled[port] |= port_mask; + desc->handle_irq = handle_edge_irq; + break; + case IRQT_FALLING: gpio_int_type1[port] |= port_mask; gpio_int_type2[port] &= ~port_mask; - } else if (type & IRQT_HIGH) { - gpio_int_enabled[port] |= port_mask; + desc->handle_irq = handle_edge_irq; + break; + case IRQT_HIGH: gpio_int_type1[port] &= ~port_mask; gpio_int_type2[port] |= port_mask; - } else if (type & IRQT_LOW) { - gpio_int_enabled[port] |= port_mask; + desc->handle_irq = handle_level_irq; + break; + case IRQT_LOW: gpio_int_type1[port] &= ~port_mask; gpio_int_type2[port] &= ~port_mask; - } else { - gpio_int_enabled[port] &= ~port_mask; + desc->handle_irq = handle_level_irq; + break; + case IRQT_BOTHEDGE: + gpio_int_type1[port] |= port_mask; + /* set initial polarity based on current input level */ + if (gpio_get_value(gpio)) + gpio_int_type2[port] &= ~port_mask; /* falling */ + else + gpio_int_type2[port] |= port_mask; /* rising */ + desc->handle_irq = handle_edge_irq; + break; + default: + pr_err("ep93xx: failed to set irq type %d for gpio %d\n", + type, gpio); + return -EINVAL; } + + gpio_int_enabled[port] |= port_mask; + + desc->status &= ~IRQ_TYPE_SENSE_MASK; + desc->status |= type & IRQ_TYPE_SENSE_MASK; + update_gpio_int_params(port); return 0; @@ -385,7 +426,8 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) static struct irq_chip ep93xx_gpio_irq_chip = { .name = "GPIO", - .ack = ep93xx_gpio_irq_mask_ack, + .ack = ep93xx_gpio_irq_ack, + .mask_ack = ep93xx_gpio_irq_mask_ack, .mask = ep93xx_gpio_irq_mask, .unmask = ep93xx_gpio_irq_unmask, .set_type = ep93xx_gpio_irq_type, - To unsubscribe from this list: send the line "unsubscribe git-commits-head" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html