diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 26 |
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 | ||
53 | static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) | 54 | static 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) | |||
91 | static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, | 92 | static 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; |