aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/max8998-irq.c65
-rw-r--r--drivers/rtc/rtc-max8998.c12
3 files changed, 52 insertions, 26 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3bb2932eafb1..aecd6ddcbbbf 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -363,6 +363,7 @@ config MFD_MAX8998
363 bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" 363 bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
364 depends on I2C=y && GENERIC_HARDIRQS 364 depends on I2C=y && GENERIC_HARDIRQS
365 select MFD_CORE 365 select MFD_CORE
366 select IRQ_DOMAIN
366 help 367 help
367 Say yes here to support for Maxim Semiconductor MAX8998 and 368 Say yes here to support for Maxim Semiconductor MAX8998 and
368 National Semiconductor LP3974. This is a Power Management IC. 369 National Semiconductor LP3974. This is a Power Management IC.
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,
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index d5af7baa48b5..46f23014759b 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -16,6 +16,7 @@
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/bcd.h> 18#include <linux/bcd.h>
19#include <linux/irqdomain.h>
19#include <linux/rtc.h> 20#include <linux/rtc.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/mfd/max8998.h> 22#include <linux/mfd/max8998.h>
@@ -264,7 +265,6 @@ static int max8998_rtc_probe(struct platform_device *pdev)
264 info->dev = &pdev->dev; 265 info->dev = &pdev->dev;
265 info->max8998 = max8998; 266 info->max8998 = max8998;
266 info->rtc = max8998->rtc; 267 info->rtc = max8998->rtc;
267 info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0;
268 268
269 platform_set_drvdata(pdev, info); 269 platform_set_drvdata(pdev, info);
270 270
@@ -277,6 +277,15 @@ static int max8998_rtc_probe(struct platform_device *pdev)
277 goto out_rtc; 277 goto out_rtc;
278 } 278 }
279 279
280 if (!max8998->irq_domain)
281 goto no_irq;
282
283 info->irq = irq_create_mapping(max8998->irq_domain, MAX8998_IRQ_ALARM0);
284 if (!info->irq) {
285 dev_warn(&pdev->dev, "Failed to map alarm IRQ\n");
286 goto no_irq;
287 }
288
280 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 289 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
281 max8998_rtc_alarm_irq, 0, "rtc-alarm0", info); 290 max8998_rtc_alarm_irq, 0, "rtc-alarm0", info);
282 291
@@ -284,6 +293,7 @@ static int max8998_rtc_probe(struct platform_device *pdev)
284 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 293 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
285 info->irq, ret); 294 info->irq, ret);
286 295
296no_irq:
287 dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); 297 dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
288 if (pdata && pdata->rtc_delay) { 298 if (pdata && pdata->rtc_delay) {
289 info->lp3974_bug_workaround = true; 299 info->lp3974_bug_workaround = true;