mirror of https://gitee.com/openkylin/linux.git
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:
parent
36cb0066ff
commit
7e1092b5a2
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue