diff options
author | Tomasz Figa <t.figa@samsung.com> | 2013-06-24 08:39:52 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-30 17:29:44 -0400 |
commit | 443c6ae253e96db9a5800a28d7c61131e81c2dee (patch) | |
tree | c9df532a7f81a8799fe52f6845504b275803e58e /drivers/mfd/max8998-irq.c | |
parent | b5c46787df1f28b0a24499e275491ba9a505c8ec (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.c | 65 |
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 | ||
19 | struct max8998_irq_data { | 20 | struct max8998_irq_data { |
@@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = { | |||
99 | static inline struct max8998_irq_data * | 100 | static inline struct max8998_irq_data * |
100 | irq_to_max8998_irq(struct max8998_dev *max8998, int irq) | 101 | irq_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 | ||
105 | static void max8998_irq_lock(struct irq_data *data) | 107 | static 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 | ||
186 | int max8998_irq_resume(struct max8998_dev *max8998) | 194 | int 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 | |||
201 | static 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 | ||
217 | static struct irq_domain_ops max8998_irq_domain_ops = { | ||
218 | .map = max8998_irq_domain_map, | ||
219 | }; | ||
220 | |||
193 | int max8998_irq_init(struct max8998_dev *max8998) | 221 | int 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, |