mfd: max8925: Add irqdomain for dt
authorQing Xu <qingx@marvell.com>
Mon, 4 Feb 2013 15:40:42 +0000 (23:40 +0800)
committerSamuel Ortiz <sameo@linux.intel.com>
Wed, 13 Feb 2013 23:23:00 +0000 (00:23 +0100)
Add irqdomains for max8925's main irq, wrap irq register operations
into irqdomain's map func. it is necessary for dt support.

Also, add dt support for max8925 driver.

Signed-off-by: Qing Xu <qingx@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
drivers/mfd/max8925-core.c
drivers/mfd/max8925-i2c.c
include/linux/mfd/max8925.h

index e32466e865b92134b0d2355c7ff721198945bb0b..0ad8d9a7c15ae1532a9ab0c4f4e234a611a44c6c 100644 (file)
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 static struct resource bk_resources[] = {
        { 0x84, 0x84, "mode control", IORESOURCE_REG, },
@@ -639,17 +642,33 @@ static struct irq_chip max8925_irq_chip = {
        .irq_disable    = max8925_irq_disable,
 };
 
+static int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq,
+                                irq_hw_number_t hw)
+{
+       irq_set_chip_data(virq, d->host_data);
+       irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq);
+       irq_set_nested_thread(virq, 1);
+#ifdef CONFIG_ARM
+       set_irq_flags(virq, IRQF_VALID);
+#else
+       irq_set_noprobe(virq);
+#endif
+       return 0;
+}
+
+static struct irq_domain_ops max8925_irq_domain_ops = {
+       .map    = max8925_irq_domain_map,
+       .xlate  = irq_domain_xlate_onetwocell,
+};
+
+
 static int max8925_irq_init(struct max8925_chip *chip, int irq,
                            struct max8925_platform_data *pdata)
 {
        unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-       int i, ret;
-       int __irq;
+       int ret;
+       struct device_node *node = chip->dev->of_node;
 
-       if (!pdata || !pdata->irq_base) {
-               dev_warn(chip->dev, "No interrupt support on IRQ base\n");
-               return -EINVAL;
-       }
        /* clear all interrupts */
        max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
        max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
@@ -667,35 +686,30 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
        max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
 
        mutex_init(&chip->irq_lock);
-       chip->core_irq = irq;
-       chip->irq_base = pdata->irq_base;
-
-       /* register with genirq */
-       for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
-               __irq = i + chip->irq_base;
-               irq_set_chip_data(__irq, chip);
-               irq_set_chip_and_handler(__irq, &max8925_irq_chip,
-                                        handle_edge_irq);
-               irq_set_nested_thread(__irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(__irq, IRQF_VALID);
-#else
-               irq_set_noprobe(__irq);
-#endif
-       }
-       if (!irq) {
-               dev_warn(chip->dev, "No interrupt support on core IRQ\n");
-               goto tsc_irq;
+       chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0);
+       if (chip->irq_base < 0) {
+               dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n",
+                       chip->irq_base);
+               return -EBUSY;
        }
 
+       irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0,
+                             &max8925_irq_domain_ops, chip);
+
+       /* request irq handler for pmic main irq*/
+       chip->core_irq = irq;
+       if (!chip->core_irq)
+               return -EBUSY;
        ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT,
                                   "max8925", chip);
        if (ret) {
                dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
                chip->core_irq = 0;
+               return -EBUSY;
        }
 
-tsc_irq:
+       /* request irq handler for pmic tsc irq*/
+
        /* mask TSC interrupt */
        max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f);
 
@@ -704,7 +718,6 @@ tsc_irq:
                return 0;
        }
        chip->tsc_irq = pdata->tsc_irq;
-
        ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
                                   flags | IRQF_ONESHOT, "max8925-tsc", chip);
        if (ret) {
@@ -875,11 +888,11 @@ int max8925_device_init(struct max8925_chip *chip,
 
        if (pdata && pdata->power) {
                ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
-                                       ARRAY_SIZE(power_devs),
+                                     ARRAY_SIZE(power_devs),
                                      &power_supply_resources[0], 0, NULL);
                if (ret < 0) {
-                       dev_err(chip->dev, "Failed to add power supply "
-                               "subdev\n");
+                       dev_err(chip->dev,
+                               "Failed to add power supply subdev\n");
                        goto out_dev;
                }
        }
index 00b5b456063df380fe88eb97144adb8d1282bfb9..92bbebd31598815659e667d890a846249b37db8b 100644 (file)
@@ -135,13 +135,37 @@ static const struct i2c_device_id max8925_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, max8925_id_table);
 
+static int max8925_dt_init(struct device_node *np, struct device *dev,
+                          struct max8925_platform_data *pdata)
+{
+       int ret;
+
+       ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq);
+       if (ret) {
+               dev_err(dev, "Not found maxim,tsc-irq property\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int max8925_probe(struct i2c_client *client,
                                   const struct i2c_device_id *id)
 {
        struct max8925_platform_data *pdata = client->dev.platform_data;
        static struct max8925_chip *chip;
-
-       if (!pdata) {
+       struct device_node *node = client->dev.of_node;
+
+       if (node && !pdata) {
+               /* parse DT to get platform data */
+               pdata = devm_kzalloc(&client->dev,
+                                    sizeof(struct max8925_platform_data),
+                                    GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+
+               if (max8925_dt_init(node, &client->dev, pdata))
+                       return -EINVAL;
+       } else if (!pdata) {
                pr_info("%s: platform data is missing\n", __func__);
                return -EINVAL;
        }
@@ -203,11 +227,18 @@ static int max8925_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume);
 
+static const struct of_device_id max8925_dt_ids[] = {
+       { .compatible = "maxim,max8925", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, max8925_dt_ids);
+
 static struct i2c_driver max8925_driver = {
        .driver = {
                .name   = "max8925",
                .owner  = THIS_MODULE,
                .pm     = &max8925_pm_ops,
+               .of_match_table = of_match_ptr(max8925_dt_ids),
        },
        .probe          = max8925_probe,
        .remove         = max8925_remove,
@@ -217,7 +248,6 @@ static struct i2c_driver max8925_driver = {
 static int __init max8925_i2c_init(void)
 {
        int ret;
-
        ret = i2c_add_driver(&max8925_driver);
        if (ret != 0)
                pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
index 74d8e2969630de5689957cff6ec0b5fc1e459ffd..ce8502e9e7dcba93f90f90334ceeaeceb1885bc9 100644 (file)
@@ -190,6 +190,8 @@ enum {
        MAX8925_NR_IRQS,
 };
 
+
+
 struct max8925_chip {
        struct device           *dev;
        struct i2c_client       *i2c;
@@ -201,7 +203,6 @@ struct max8925_chip {
        int                     irq_base;
        int                     core_irq;
        int                     tsc_irq;
-
        unsigned int            wakeup_flag;
 };