gpio-rcar: Add support for IRQ_TYPE_EDGE_BOTH

As hardware support for this feature is not universal for all SoCs a flag,
has_both_edge_trigger, has been added to the platform data of the driver to
allow this feature to be enabled.

The motivation for this is to allow use of the gpio-keys driver on the
lager board which is based on the r8a7790 SoC. The V2 of this patch has been
fully exercised using that driver on that board.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
This commit is contained in:
Simon Horman 2013-05-24 18:47:24 +09:00
parent 36cb0066ff
commit 7e1092b5a2
2 changed files with 22 additions and 5 deletions

View File

@ -49,6 +49,7 @@ struct gpio_rcar_priv {
#define POSNEG 0x20
#define EDGLEVEL 0x24
#define FILONOFF 0x28
#define BOTHEDGE 0x4c
static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
{
@ -91,7 +92,8 @@ static void gpio_rcar_irq_enable(struct irq_data *d)
static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
unsigned int hwirq,
bool active_high_rising_edge,
bool level_trigger)
bool level_trigger,
bool both)
{
unsigned long flags;
@ -108,6 +110,10 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
/* Configure edge or level trigger in EDGLEVEL */
gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger);
/* Select one edge or both edges in BOTHEDGE */
if (p->config.has_both_edge_trigger)
gpio_rcar_modify_bit(p, BOTHEDGE, hwirq, both);
/* Select "Interrupt Input Mode" in IOINTSEL */
gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true);
@ -127,16 +133,26 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_LEVEL_HIGH:
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true);
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true,
false);
break;
case IRQ_TYPE_LEVEL_LOW:
gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true);
gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true,
false);
break;
case IRQ_TYPE_EDGE_RISING:
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false);
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
false);
break;
case IRQ_TYPE_EDGE_FALLING:
gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false);
gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false,
false);
break;
case IRQ_TYPE_EDGE_BOTH:
if (!p->config.has_both_edge_trigger)
return -EINVAL;
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
true);
break;
default:
return -EINVAL;

View File

@ -21,6 +21,7 @@ struct gpio_rcar_config {
unsigned int irq_base;
unsigned int number_of_pins;
const char *pctl_name;
unsigned has_both_edge_trigger:1;
};
#endif /* __GPIO_RCAR_H__ */