diff options
author | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-09-21 18:06:52 +0800 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-10-02 11:43:13 +0200 |
commit | 2e57d56747e601b3e0ff6697e524025d0504d161 (patch) | |
tree | 29a7c677878d39f64e90dfbdf7063a11c08d4c15 /drivers | |
parent | 837c8293ba24d08cd7438d82ad9bb8d2fb0f8a5b (diff) |
mfd: 88pm860x: Device tree support
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/touchscreen/88pm860x-ts.c | 46 | ||||
-rw-r--r-- | drivers/leds/leds-88pm860x.c | 33 | ||||
-rw-r--r-- | drivers/mfd/88pm860x-core.c | 62 | ||||
-rw-r--r-- | drivers/regulator/88pm8607.c | 35 | ||||
-rw-r--r-- | drivers/rtc/rtc-88pm860x.c | 43 | ||||
-rw-r--r-- | drivers/video/backlight/88pm860x_bl.c | 39 |
6 files changed, 219 insertions, 39 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 05f30b73c3c..4f81e6eb74b 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/input.h> @@ -113,14 +114,31 @@ static void pm860x_touch_close(struct input_dev *dev) pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); } +#ifdef CONFIG_OF +static int __devinit pm860x_touch_dt_init(struct platform_device *pdev, + int *res_x) +{ + struct device_node *np = pdev->dev.parent->of_node; + if (!np) + return -ENODEV; + np = of_find_node_by_name(np, "touch"); + if (!np) { + dev_err(&pdev->dev, "Can't find touch node\n"); + return -EINVAL; + } + of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x); + return 0; +} +#else +#define pm860x_touch_dt_init(x, y) (-1) +#endif + static int __devinit pm860x_touch_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_platform_data *pm860x_pdata = \ - pdev->dev.parent->platform_data; - struct pm860x_touch_pdata *pdata = NULL; + struct pm860x_touch_pdata *pdata = pdev->dev.platform_data; struct pm860x_touch *touch; - int irq, ret; + int irq, ret, res_x = 0; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -128,15 +146,13 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev) return -EINVAL; } - if (!pm860x_pdata) { - dev_err(&pdev->dev, "platform data is missing\n"); - return -EINVAL; - } - - pdata = pm860x_pdata->touch; - if (!pdata) { - dev_err(&pdev->dev, "touchscreen data is missing\n"); - return -EINVAL; + if (pm860x_touch_dt_init(pdev, &res_x)) { + if (pdata) + res_x = pdata->res_x; + else { + dev_err(&pdev->dev, "failed to get platform data\n"); + return -EINVAL; + } } touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); @@ -159,8 +175,8 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev) touch->idev->close = pm860x_touch_close; touch->chip = chip; touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; - touch->irq = irq + chip->irq_base; - touch->res_x = pdata->res_x; + touch->irq = irq; + touch->res_x = res_x; input_set_drvdata(touch->idev, touch); ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 70232b1756f..b7e8cc0957f 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/leds.h> @@ -123,6 +124,33 @@ static void pm860x_led_set(struct led_classdev *cdev, schedule_work(&data->work); } +#ifdef CONFIG_OF +static int pm860x_led_dt_init(struct platform_device *pdev, + struct pm860x_led *data) +{ + struct device_node *nproot = pdev->dev.parent->of_node, *np; + int iset = 0; + if (!nproot) + return -ENODEV; + nproot = of_find_node_by_name(nproot, "leds"); + if (!nproot) { + dev_err(&pdev->dev, "failed to find leds node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) { + if (!of_node_cmp(np->name, data->name)) { + of_property_read_u32(np, "marvell,88pm860x-iset", + &iset); + data->iset = PM8606_LED_CURRENT(iset); + break; + } + } + return 0; +} +#else +#define pm860x_led_dt_init(x, y) (-1) +#endif + static int pm860x_led_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -179,8 +207,9 @@ static int pm860x_led_probe(struct platform_device *pdev) data->chip = chip; data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; data->port = pdev->id; - if (pdata && pdata->iset) - data->iset = pdata->iset; + if (pm860x_led_dt_init(pdev, data)) + if (pdata) + data->iset = pdata->iset; data->current_brightness = 0; data->cdev.name = data->name; diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 5b56fe8250b..fdaf6861ce9 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -16,6 +16,8 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -1112,12 +1114,6 @@ static void __devexit pm860x_device_exit(struct pm860x_chip *chip) mfd_remove_devices(chip->dev); } -static const struct i2c_device_id pm860x_id_table[] = { - { "88PM860x", 0 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, pm860x_id_table); - static int verify_addr(struct i2c_client *i2c) { unsigned short addr_8607[] = {0x30, 0x34}; @@ -1144,21 +1140,52 @@ static struct regmap_config pm860x_regmap_config = { .val_bits = 8, }; +static int __devinit pm860x_dt_init(struct device_node *np, + struct device *dev, + struct pm860x_platform_data *pdata) +{ + int ret; + + if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL)) + pdata->irq_mode = 1; + ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr", + &pdata->companion_addr); + if (ret) { + dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" " + "property\n"); + pdata->companion_addr = 0; + } + return 0; +} + static int __devinit pm860x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct pm860x_platform_data *pdata = client->dev.platform_data; + struct device_node *node = client->dev.of_node; struct pm860x_chip *chip; int ret; - if (!pdata) { + if (node && !pdata) { + /* parse DT to get platform data */ + pdata = devm_kzalloc(&client->dev, + sizeof(struct pm860x_platform_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + ret = pm860x_dt_init(node, &client->dev, pdata); + if (ret) + goto err; + } else if (!pdata) { pr_info("No platform data in %s!\n", __func__); return -EINVAL; } chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; + if (chip == NULL) { + ret = -ENOMEM; + goto err; + } chip->id = verify_addr(client); chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config); @@ -1198,6 +1225,10 @@ static int __devinit pm860x_probe(struct i2c_client *client, pm860x_device_init(chip, pdata); return 0; +err: + if (node) + devm_kfree(&client->dev, pdata); + return ret; } static int __devexit pm860x_remove(struct i2c_client *client) @@ -1238,11 +1269,24 @@ static int pm860x_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume); +static const struct i2c_device_id pm860x_id_table[] = { + { "88PM860x", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pm860x_id_table); + +static const struct of_device_id pm860x_dt_ids[] = { + { .compatible = "marvell,88pm860x", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pm860x_dt_ids); + static struct i2c_driver pm860x_driver = { .driver = { .name = "88PM860x", .owner = THIS_MODULE, .pm = &pm860x_pm_ops, + .of_match_table = of_match_ptr(pm860x_dt_ids), }, .probe = pm860x_probe, .remove = __devexit_p(pm860x_remove), diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index f96fbe38ff6..1c5ab0172ea 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -12,6 +12,8 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/i2c.h> +#include <linux/of.h> +#include <linux/regulator/of_regulator.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> @@ -364,6 +366,34 @@ static struct pm8607_regulator_info pm8606_regulator_info[] = { PM8606_PREG(PREREGULATORB, 5), }; +#ifdef CONFIG_OF +static int pm8607_regulator_dt_init(struct platform_device *pdev, + struct pm8607_regulator_info *info, + struct regulator_config *config) +{ + struct device_node *nproot, *np; + nproot = pdev->dev.parent->of_node; + if (!nproot) + return -ENODEV; + nproot = of_find_node_by_name(nproot, "regulators"); + if (!nproot) { + dev_err(&pdev->dev, "failed to find regulators node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) { + if (!of_node_cmp(np->name, info->desc.name)) { + config->init_data = + of_get_regulator_init_data(&pdev->dev, np); + config->of_node = np; + break; + } + } + return 0; +} +#else +#define pm8607_regulator_dt_init(x, y, z) (-1) +#endif + static int __devinit pm8607_regulator_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -402,9 +432,12 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) info->slope_double = 1; config.dev = &pdev->dev; - config.init_data = pdata; config.driver_data = info; + if (pm8607_regulator_dt_init(pdev, info, &config)) + if (pdata) + config.init_data = pdata; + if (chip->id == CHIP_PM8607) config.regmap = chip->regmap; else diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index feddefc4210..de9e854b326 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/mutex.h> @@ -284,6 +285,28 @@ out: } #endif +#ifdef CONFIG_OF +static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev, + struct pm860x_rtc_info *info) +{ + struct device_node *np = pdev->dev.parent->of_node; + int ret; + if (!np) + return -ENODEV; + np = of_find_node_by_name(np, "rtc"); + if (!np) { + dev_err(&pdev->dev, "failed to find rtc node\n"); + return -ENODEV; + } + ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc); + if (ret) + info->vrtc = 0; + return 0; +} +#else +#define pm860x_rtc_dt_init(x, y) (-1) +#endif + static int __devinit pm860x_rtc_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -294,8 +317,6 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev) int ret; pdata = pdev->dev.platform_data; - if (pdata == NULL) - dev_warn(&pdev->dev, "No platform data!\n"); info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL); if (!info) @@ -345,9 +366,11 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev) } } rtc_tm_to_time(&tm, &ticks); - if (pdata && pdata->sync) { - pdata->sync(ticks); - info->sync = pdata->sync; + if (pm860x_rtc_dt_init(pdev, info)) { + if (pdata && pdata->sync) { + pdata->sync(ticks); + info->sync = pdata->sync; + } } info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev, @@ -366,10 +389,12 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev) #ifdef VRTC_CALIBRATION /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */ - if (pdata && pdata->vrtc) - info->vrtc = pdata->vrtc & 0x3; - else - info->vrtc = 1; + if (pm860x_rtc_dt_init(pdev, info)) { + if (pdata && pdata->vrtc) + info->vrtc = pdata->vrtc & 0x3; + else + info->vrtc = 1; + } pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC); /* calibrate VRTC */ diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 965161cacef..b7ec34c57f4 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/fb.h> @@ -159,6 +160,36 @@ static const struct backlight_ops pm860x_backlight_ops = { .get_brightness = pm860x_backlight_get_brightness, }; +#ifdef CONFIG_OF +static int pm860x_backlight_dt_init(struct platform_device *pdev, + struct pm860x_backlight_data *data, + char *name) +{ + struct device_node *nproot = pdev->dev.parent->of_node, *np; + int iset = 0; + if (!nproot) + return -ENODEV; + nproot = of_find_node_by_name(nproot, "backlights"); + if (!nproot) { + dev_err(&pdev->dev, "failed to find backlights node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) { + if (!of_node_cmp(np->name, name)) { + of_property_read_u32(np, "marvell,88pm860x-iset", + &iset); + data->iset = PM8606_WLED_CURRENT(iset); + of_property_read_u32(np, "marvell,88pm860x-pwm", + &data->pwm); + break; + } + } + return 0; +} +#else +#define pm860x_backlight_dt_init(x, y, z) (-1) +#endif + static int pm860x_backlight_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -203,9 +234,11 @@ static int pm860x_backlight_probe(struct platform_device *pdev) data->i2c = (chip->id == CHIP_PM8606) ? chip->client \ : chip->companion; data->current_brightness = MAX_BRIGHTNESS; - if (pdata) { - data->pwm = pdata->pwm; - data->iset = pdata->iset; + if (pm860x_backlight_dt_init(pdev, data, name)) { + if (pdata) { + data->pwm = pdata->pwm; + data->iset = pdata->iset; + } } memset(&props, 0, sizeof(struct backlight_properties)); |