Make max8925 to support both platform data and device tree. So a translation
between device tree and platform data is added.

Signed-off-by: Haojian Zhuang <haojian.zhu...@marvell.com>
---
 drivers/mfd/max8925-i2c.c |  159 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 0219115..fb74554 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -10,6 +10,9 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_regulator.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/mfd/max8925.h>
@@ -135,6 +138,154 @@ static const struct i2c_device_id max8925_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, max8925_id_table);
 
+#ifdef CONFIG_OF
+static int __devinit max8925_parse_irq(struct i2c_client *i2c,
+                                       struct max8925_platform_data *pdata)
+{
+       struct device_node *of_node = i2c->dev.of_node;
+
+       pdata->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0);
+       irq_domain_add_simple(of_node, pdata->irq_base);
+       return 0;
+}
+
+static void __devinit max8925_parse_backlight(struct device_node *np,
+                                       struct max8925_platform_data *pdata)
+{
+       struct max8925_backlight_pdata *bk;
+       const __be32 *p;
+
+       bk = kzalloc(sizeof(struct max8925_backlight_pdata), GFP_KERNEL);
+       if (bk == NULL)
+               return;
+       pdata->backlight = bk;
+       p = of_get_property(np, "lxw-scl", NULL);
+       if (p)
+               bk->lxw_scl = be32_to_cpu(*p);
+       p = of_get_property(np, "lxw-freq", NULL);
+       if (p)
+               bk->lxw_freq = be32_to_cpu(*p);
+       p = of_get_property(np, "dual-string", NULL);
+       if (p)
+               bk->dual_string = be32_to_cpu(*p);
+}
+
+static void __devinit max8925_parse_touch(struct device_node *np,
+                                       struct max8925_platform_data *pdata)
+{
+       struct max8925_touch_pdata *touch;
+       const __be32 *p;
+
+       touch = kzalloc(sizeof(struct max8925_touch_pdata), GFP_KERNEL);
+       if (touch == NULL)
+               return;
+       pdata->touch = touch;
+       p = of_get_property(np, "flags", NULL);
+       if (p)
+               touch->flags = be32_to_cpu(*p);
+       p = of_get_property(np, "interrupts", NULL);
+       if (p)
+               pdata->tsc_irq = irq_of_parse_and_map(np, 0);
+}
+
+static void __devinit max8925_parse_power(struct device_node *np,
+                                       struct max8925_platform_data *pdata)
+{
+       struct max8925_power_pdata *power;
+       const __be32 *p;
+
+       power = kzalloc(sizeof(struct max8925_power_pdata), GFP_KERNEL);
+       if (power == NULL)
+               return;
+       pdata->power = power;
+       p = of_get_property(np, "battery-detect", NULL);
+       if (p)
+               power->batt_detect = be32_to_cpu(*p) ? 1 : 0;
+       p = of_get_property(np, "topoff-threshold", NULL);
+       if (p)
+               power->topoff_threshold = be32_to_cpu(*p) & 0x3;
+       p = of_get_property(np, "fast-charge", NULL);
+       if (p)
+               power->fast_charge = be32_to_cpu(*p) & 0x7;
+}
+
+static void __devinit max8925_parse_regulator(struct device_node *np,
+                                       struct max8925_platform_data *pdata)
+{
+       const char *name[MAX8925_MAX_REGULATOR] = {
+                       "SD1", "SD2", "SD3", "LDO1", "LDO2", "LDO3", "LDO4",
+                       "LDO5", "LDO6", "LDO7", "LDO8", "LDO9", "LDO10",
+                       "LDO11", "LDO12", "LDO13", "LDO14", "LDO15", "LDO16",
+                       "LDO17", "LDO18", "LDO19", "LDO20"};
+       const char *cp;
+       int i;
+
+       cp = of_get_property(np, "compatible", NULL);
+       if (cp == NULL)
+               return;
+       for (i = 0; i < MAX8925_MAX_REGULATOR; i++) {
+               if (strncmp(cp, name[i], strlen(name[i])))
+                       continue;
+               of_regulator_init_data(np, pdata->regulator[i]);
+               break;
+       }
+}
+
+static struct max8925_platform_data __devinit
+*max8925_get_alt_pdata(struct i2c_client *client)
+{
+       struct max8925_platform_data *pdata;
+       struct device_node *of_node = client->dev.of_node;
+       struct device_node *np, *pp = NULL;
+       const char *cp;
+       int ret, i;
+
+       pdata = kzalloc(sizeof(struct max8925_platform_data), GFP_KERNEL);
+       if (pdata == NULL)
+               return NULL;
+       pdata->regulator[0] = kzalloc(sizeof(struct regulator_init_data)
+                       * MAX8925_MAX_REGULATOR, GFP_KERNEL);
+       if (pdata->regulator[0] == NULL) {
+               kfree(pdata);
+               return NULL;
+       }
+       for (i = 1; i < MAX8925_MAX_REGULATOR; i++)
+               pdata->regulator[i] = pdata->regulator[i - 1] + 1;
+
+       ret = max8925_parse_irq(client, pdata);
+       if (ret < 0)
+               goto out;
+
+       for (; (np = of_get_next_child(of_node, pp)) != NULL; pp = np) {
+               cp = of_get_property(np, "compatible", NULL);
+               if (cp == NULL)
+                       continue;
+               if (!strncmp(cp, "backlight", strlen("backlight")))
+                       max8925_parse_backlight(np, pdata);
+               if (!strncmp(cp, "power", strlen("power")))
+                       max8925_parse_power(np, pdata);
+               if (!strncmp(cp, "touch", strlen("touch")))
+                       max8925_parse_touch(np, pdata);
+               cp = of_get_property(np, "device_type", NULL);
+               if (cp == NULL)
+                       continue;
+               if (!strncmp(cp, "regulator", strlen("regulator")))
+                       max8925_parse_regulator(np, pdata);
+       }
+       return pdata;
+out:
+       kfree(pdata->regulator[0]);
+       kfree(pdata);
+       return NULL;
+}
+#else
+static struct max8925_platform_data __devinit
+*max8925_get_alt_pdata(struct i2c_client *client)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit max8925_probe(struct i2c_client *client,
                                   const struct i2c_device_id *id)
 {
@@ -142,8 +293,12 @@ static int __devinit max8925_probe(struct i2c_client 
*client,
        static struct max8925_chip *chip;
 
        if (!pdata) {
-               pr_info("%s: platform data is missing\n", __func__);
-               return -EINVAL;
+               pdata = max8925_get_alt_pdata(client);
+               if (!pdata) {
+                       pr_info("%s: platform data is missing\n", __func__);
+                       return -EINVAL;
+               }
+               client->dev.platform_data = pdata;
        }
 
        chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
-- 
1.5.6.5

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to