[PATCH] mfd: convert devicetree to platform on 88pm860x
Haojian Zhuang
haojian.zhuang at marvell.com
Fri Jul 8 06:20:27 EDT 2011
Make 88pm860x 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.zhuang at marvell.com>
---
drivers/mfd/88pm860x-i2c.c | 191 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 189 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index e017dc8..b017e4a 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -10,6 +10,8 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_regulator.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/mfd/88pm860x.h>
@@ -236,6 +238,187 @@ static const struct i2c_device_id pm860x_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
+#ifdef CONFIG_OF
+static int __devinit pm860x_parse_irq(struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ struct device_node *of_node = i2c->dev.of_node;
+
+ pdata->irq_base = irq_alloc_descs(-1, 0, 24, 0);
+ irq_domain_add_simple(of_node, pdata->irq_base);
+ return 0;
+}
+
+static void __devinit pm860x_parse_backlight(struct device_node *np,
+ struct pm860x_platform_data *pdata)
+{
+ const __be32 *idx, *iset, *pwm;
+ int i;
+
+ idx = of_get_property(np, "cell-index", NULL);
+ if (idx == NULL)
+ return;
+ iset = of_get_property(np, "iset", NULL);
+ if (iset == NULL)
+ return;
+ pwm = of_get_property(np, "pwm", NULL);
+
+ i = be32_to_cpu(*idx);
+ pdata->backlight[i].iset = be32_to_cpu(*iset);
+ pdata->backlight[i].flags = i;
+ if (pwm)
+ pdata->backlight[i].pwm = be32_to_cpu(*pwm);
+ pdata->num_backlights++;
+}
+
+static void __devinit pm860x_parse_led(struct device_node *np,
+ struct pm860x_platform_data *pdata)
+{
+ const __be32 *idx, *iset;
+ int i;
+
+ idx = of_get_property(np, "cell-index", NULL);
+ if (idx == NULL)
+ return;
+ iset = of_get_property(np, "iset", NULL);
+ if (iset == NULL)
+ return;
+
+ i = be32_to_cpu(*idx);
+ pdata->led[i].iset = be32_to_cpu(*iset);
+ pdata->led[i].flags = i;
+ pdata->num_leds++;
+}
+
+static void __devinit pm860x_parse_touch(struct device_node *np,
+ struct pm860x_platform_data *pdata)
+{
+ struct pm860x_touch_pdata *touch;
+ const __be32 *prebias, *slot, *res, *prechg;
+
+ prebias = of_get_property(np, "prebias", NULL);
+ if (prebias == NULL)
+ return;
+ slot = of_get_property(np, "slot-cycle", NULL);
+ if (slot == NULL)
+ return;
+ res = of_get_property(np, "resistor-xplate", NULL);
+ if (res == NULL)
+ return;
+ prechg = of_get_property(np, "pen-prechg", NULL);
+ if (prechg == NULL)
+ return;
+ touch = kzalloc(sizeof(struct pm860x_touch_pdata), GFP_KERNEL);
+ if (touch == NULL)
+ return;
+ touch->gpadc_prebias = be32_to_cpu(*prebias++);
+ touch->tsi_prebias = be32_to_cpu(*prebias++);
+ touch->pen_prebias = be32_to_cpu(*prebias);
+ touch->slot_cycle = be32_to_cpu(*slot);
+ touch->pen_prechg = be32_to_cpu(*prechg);
+ pdata->touch = touch;
+}
+
+static int data[PM8607_ID_RG_MAX];
+
+static void __devinit pm860x_parse_regulator(struct device_node *np,
+ struct pm860x_platform_data *pdata)
+{
+ const char *name[PM8607_ID_RG_MAX] = {
+ "BUCK1", "BUCK2", "BUCK3", "LDO1", "LDO2", "LDO3", "LOD4",
+ "LDO5", "LDO6", "LDO7", "LDO8", "LDO9", "LDO10", "LDO11",
+ "LDO12", "LDO13", "LDO14", "LDO15"};
+ const char *cp;
+ int i;
+
+ cp = of_get_property(np, "compatible", NULL);
+ if (cp == NULL)
+ return;
+ for (i = 0; i < PM8607_ID_RG_MAX; i++) {
+ if (strncmp(cp, name[i], strlen(name[i])))
+ continue;
+ of_regulator_init_data(np, &pdata->regulator[i]);
+ data[i] = i;
+ pdata->regulator[i].driver_data = &data[i];
+ pdata->num_regulators++;
+ break;
+ }
+}
+
+static struct pm860x_platform_data __devinit
+*pm860x_get_alt_pdata(struct i2c_client *i2c)
+{
+ struct pm860x_platform_data *pdata;
+ struct device_node *of_node = i2c->dev.of_node;
+ struct device_node *np, *pp = NULL;
+ const char *cp;
+ const __be32 *p;
+ int ret;
+
+ pdata = kzalloc(sizeof(struct pm860x_platform_data), GFP_KERNEL);
+ if (pdata == NULL)
+ return NULL;
+ pdata->regulator = kzalloc(sizeof(struct regulator_init_data)
+ * PM8607_ID_RG_MAX, GFP_KERNEL);
+ if (pdata->regulator == NULL)
+ goto out_reg;
+ pdata->led = kzalloc(sizeof(struct pm860x_led_pdata) * 3,
+ GFP_KERNEL);
+ if (pdata->led == NULL)
+ goto out_led;
+ pdata->backlight = kzalloc(sizeof(struct pm860x_backlight_pdata)
+ * 3, GFP_KERNEL);
+ if (pdata->backlight == NULL)
+ goto out_backlight;
+ p = of_get_property(of_node, "i2c-port", NULL);
+ if (p)
+ pdata->i2c_port = be32_to_cpu(*p);
+ p = of_get_property(of_node, "companion-addr", NULL);
+ if (p)
+ pdata->companion_addr = be32_to_cpu(*p);
+ p = of_get_property(of_node, "irq-mode", NULL);
+ if (p)
+ pdata->irq_mode = be32_to_cpu(*p);
+
+ ret = pm860x_parse_irq(i2c, 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")))
+ pm860x_parse_backlight(np, pdata);
+ if (!strncmp(cp, "led", strlen("led")))
+ pm860x_parse_led(np, pdata);
+ if (!strncmp(cp, "touch", strlen("touch")))
+ pm860x_parse_touch(np, pdata);
+ cp = of_get_property(np, "device_type", NULL);
+ if (cp == NULL)
+ continue;
+ if (!strncmp(cp, "regulator", strlen("regulator")))
+ pm860x_parse_regulator(np, pdata);
+ }
+ return pdata;
+out:
+ kfree(pdata->backlight);
+out_backlight:
+ kfree(pdata->led);
+out_led:
+ kfree(pdata->regulator);
+out_reg:
+ kfree(pdata);
+ return NULL;
+}
+#else
+static struct pm860x_platform_data __devinit
+*pm860x_get_alt_pdata(struct i2c_client *i2c)
+{
+ return NULL;
+}
+#endif
+
static int verify_addr(struct i2c_client *i2c)
{
unsigned short addr_8607[] = {0x30, 0x34};
@@ -264,8 +447,12 @@ static int __devinit pm860x_probe(struct i2c_client *client,
struct pm860x_chip *chip;
if (!pdata) {
- pr_info("No platform data in %s!\n", __func__);
- return -EINVAL;
+ pdata = pm860x_get_alt_pdata(client);
+ if (!pdata) {
+ pr_info("No platform data in %s!\n", __func__);
+ return -EINVAL;
+ }
+ client->dev.platform_data = pdata;
}
chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
--
1.5.6.5
More information about the linux-arm-kernel
mailing list