aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/max8998-irq.c
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2013-06-24 08:39:52 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-06-30 17:29:44 -0400
commit443c6ae253e96db9a5800a28d7c61131e81c2dee (patch)
treec9df532a7f81a8799fe52f6845504b275803e58e /drivers/mfd/max8998-irq.c
parentb5c46787df1f28b0a24499e275491ba9a505c8ec (diff)
mfd: max8998: Add irq domain support
This patch adds irq domain support for max8998 interrupts. To keep both non-DT and DT worlds happy, simple domain is used, which is linear when no explicit IRQ base is specified and legacy, with static mapping, otherwise. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/max8998-irq.c')
-rw-r--r--drivers/mfd/max8998-irq.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c
index 5919710dc9ed..c469477eb778 100644
--- a/drivers/mfd/max8998-irq.c
+++ b/drivers/mfd/max8998-irq.c
@@ -14,6 +14,7 @@
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/irqdomain.h>
17#include <linux/mfd/max8998-private.h> 18#include <linux/mfd/max8998-private.h>
18 19
19struct max8998_irq_data { 20struct max8998_irq_data {
@@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = {
99static inline struct max8998_irq_data * 100static inline struct max8998_irq_data *
100irq_to_max8998_irq(struct max8998_dev *max8998, int irq) 101irq_to_max8998_irq(struct max8998_dev *max8998, int irq)
101{ 102{
102 return &max8998_irqs[irq - max8998->irq_base]; 103 struct irq_data *data = irq_get_irq_data(irq);
104 return &max8998_irqs[data->hwirq];
103} 105}
104 106
105static void max8998_irq_lock(struct irq_data *data) 107static void max8998_irq_lock(struct irq_data *data)
@@ -176,8 +178,14 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
176 178
177 /* Report */ 179 /* Report */
178 for (i = 0; i < MAX8998_IRQ_NR; i++) { 180 for (i = 0; i < MAX8998_IRQ_NR; i++) {
179 if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) 181 if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) {
180 handle_nested_irq(max8998->irq_base + i); 182 irq = irq_find_mapping(max8998->irq_domain, i);
183 if (WARN_ON(!irq)) {
184 disable_irq_nosync(max8998->irq);
185 return IRQ_NONE;
186 }
187 handle_nested_irq(irq);
188 }
181 } 189 }
182 190
183 return IRQ_HANDLED; 191 return IRQ_HANDLED;
@@ -185,27 +193,40 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
185 193
186int max8998_irq_resume(struct max8998_dev *max8998) 194int max8998_irq_resume(struct max8998_dev *max8998)
187{ 195{
188 if (max8998->irq && max8998->irq_base) 196 if (max8998->irq && max8998->irq_domain)
189 max8998_irq_thread(max8998->irq_base, max8998); 197 max8998_irq_thread(max8998->irq, max8998);
198 return 0;
199}
200
201static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq,
202 irq_hw_number_t hw)
203{
204 struct max8997_dev *max8998 = d->host_data;
205
206 irq_set_chip_data(irq, max8998);
207 irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq);
208 irq_set_nested_thread(irq, 1);
209#ifdef CONFIG_ARM
210 set_irq_flags(irq, IRQF_VALID);
211#else
212 irq_set_noprobe(irq);
213#endif
190 return 0; 214 return 0;
191} 215}
192 216
217static struct irq_domain_ops max8998_irq_domain_ops = {
218 .map = max8998_irq_domain_map,
219};
220
193int max8998_irq_init(struct max8998_dev *max8998) 221int max8998_irq_init(struct max8998_dev *max8998)
194{ 222{
195 int i; 223 int i;
196 int cur_irq;
197 int ret; 224 int ret;
225 struct irq_domain *domain;
198 226
199 if (!max8998->irq) { 227 if (!max8998->irq) {
200 dev_warn(max8998->dev, 228 dev_warn(max8998->dev,
201 "No interrupt specified, no interrupts\n"); 229 "No interrupt specified, no interrupts\n");
202 max8998->irq_base = 0;
203 return 0;
204 }
205
206 if (!max8998->irq_base) {
207 dev_err(max8998->dev,
208 "No interrupt base specified, no interrupts\n");
209 return 0; 230 return 0;
210 } 231 }
211 232
@@ -221,19 +242,13 @@ int max8998_irq_init(struct max8998_dev *max8998)
221 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff); 242 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff);
222 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff); 243 max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff);
223 244
224 /* register with genirq */ 245 domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR,
225 for (i = 0; i < MAX8998_IRQ_NR; i++) { 246 max8998->irq_base, &max8998_irq_domain_ops, max8998);
226 cur_irq = i + max8998->irq_base; 247 if (!domain) {
227 irq_set_chip_data(cur_irq, max8998); 248 dev_err(max8998->dev, "could not create irq domain\n");
228 irq_set_chip_and_handler(cur_irq, &max8998_irq_chip, 249 return -ENODEV;
229 handle_edge_irq);
230 irq_set_nested_thread(cur_irq, 1);
231#ifdef CONFIG_ARM
232 set_irq_flags(cur_irq, IRQF_VALID);
233#else
234 irq_set_noprobe(cur_irq);
235#endif
236 } 250 }
251 max8998->irq_domain = domain;
237 252
238 ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread, 253 ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread,
239 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 254 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,