aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-rcar.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 0f3d6473bf89..d173d56dbb8c 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -49,6 +49,7 @@ struct gpio_rcar_priv {
49#define POSNEG 0x20 49#define POSNEG 0x20
50#define EDGLEVEL 0x24 50#define EDGLEVEL 0x24
51#define FILONOFF 0x28 51#define FILONOFF 0x28
52#define BOTHEDGE 0x4c
52 53
53static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) 54static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
54{ 55{
@@ -91,7 +92,8 @@ static void gpio_rcar_irq_enable(struct irq_data *d)
91static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, 92static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
92 unsigned int hwirq, 93 unsigned int hwirq,
93 bool active_high_rising_edge, 94 bool active_high_rising_edge,
94 bool level_trigger) 95 bool level_trigger,
96 bool both)
95{ 97{
96 unsigned long flags; 98 unsigned long flags;
97 99
@@ -108,6 +110,10 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
108 /* Configure edge or level trigger in EDGLEVEL */ 110 /* Configure edge or level trigger in EDGLEVEL */
109 gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger); 111 gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger);
110 112
113 /* Select one edge or both edges in BOTHEDGE */
114 if (p->config.has_both_edge_trigger)
115 gpio_rcar_modify_bit(p, BOTHEDGE, hwirq, both);
116
111 /* Select "Interrupt Input Mode" in IOINTSEL */ 117 /* Select "Interrupt Input Mode" in IOINTSEL */
112 gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true); 118 gpio_rcar_modify_bit(p, IOINTSEL, hwirq, true);
113 119
@@ -127,16 +133,26 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
127 133
128 switch (type & IRQ_TYPE_SENSE_MASK) { 134 switch (type & IRQ_TYPE_SENSE_MASK) {
129 case IRQ_TYPE_LEVEL_HIGH: 135 case IRQ_TYPE_LEVEL_HIGH:
130 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true); 136 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, true,
137 false);
131 break; 138 break;
132 case IRQ_TYPE_LEVEL_LOW: 139 case IRQ_TYPE_LEVEL_LOW:
133 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true); 140 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, true,
141 false);
134 break; 142 break;
135 case IRQ_TYPE_EDGE_RISING: 143 case IRQ_TYPE_EDGE_RISING:
136 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false); 144 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
145 false);
137 break; 146 break;
138 case IRQ_TYPE_EDGE_FALLING: 147 case IRQ_TYPE_EDGE_FALLING:
139 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false); 148 gpio_rcar_config_interrupt_input_mode(p, hwirq, false, false,
149 false);
150 break;
151 case IRQ_TYPE_EDGE_BOTH:
152 if (!p->config.has_both_edge_trigger)
153 return -EINVAL;
154 gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
155 true);
140 break; 156 break;
141 default: 157 default:
142 return -EINVAL; 158 return -EINVAL;