diff options
author | Rajanikanth H.V <rajanikanth.hv@stericsson.com> | 2012-11-18 21:45:41 -0500 |
---|---|---|
committer | Anton Vorontsov <anton.vorontsov@linaro.org> | 2012-11-18 22:37:04 -0500 |
commit | e0f1abeba5c2d8a2183566717d99294fd1a29c2e (patch) | |
tree | bf4b3582791d3e4baa298f4268cf2bbad8169b74 /drivers/power/ab8500_fg.c | |
parent | e9f14c18b83ccf3ab291b83a1d6c640113ecf545 (diff) |
ab8500: Add devicetree support for fuelgauge
- This patch adds device tree support for fuelgauge driver
- optimize bm devices platform_data usage and of_probe(...)
Note: of_probe() routine for battery managed devices is made
common across all bm drivers.
- test status:
- interrupt numbers assigned differs between legacy and FDT mode.
Signed-off-by: Rajanikanth H.V <rajanikanth.hv@stericsson.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power/ab8500_fg.c')
-rw-r--r-- | drivers/power/ab8500_fg.c | 82 |
1 files changed, 42 insertions, 40 deletions
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 2db8cc254399..ed62ef788eb5 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c | |||
@@ -22,15 +22,16 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
24 | #include <linux/kobject.h> | 24 | #include <linux/kobject.h> |
25 | #include <linux/mfd/abx500/ab8500.h> | ||
26 | #include <linux/mfd/abx500.h> | ||
27 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
28 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
29 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
30 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
31 | #include <linux/mfd/abx500.h> | ||
32 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/of.h> | ||
33 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
30 | #include <linux/mfd/core.h> | ||
31 | #include <linux/mfd/abx500.h> | ||
32 | #include <linux/mfd/abx500/ab8500.h> | ||
33 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
34 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
34 | 35 | ||
35 | #define MILLI_TO_MICRO 1000 | 36 | #define MILLI_TO_MICRO 1000 |
36 | #define FG_LSB_IN_MA 1627 | 37 | #define FG_LSB_IN_MA 1627 |
@@ -172,7 +173,6 @@ struct inst_curr_result_list { | |||
172 | * @avg_cap: Average capacity filter | 173 | * @avg_cap: Average capacity filter |
173 | * @parent: Pointer to the struct ab8500 | 174 | * @parent: Pointer to the struct ab8500 |
174 | * @gpadc: Pointer to the struct gpadc | 175 | * @gpadc: Pointer to the struct gpadc |
175 | * @pdata: Pointer to the abx500_fg platform data | ||
176 | * @bat: Pointer to the abx500_bm platform data | 176 | * @bat: Pointer to the abx500_bm platform data |
177 | * @fg_psy: Structure that holds the FG specific battery properties | 177 | * @fg_psy: Structure that holds the FG specific battery properties |
178 | * @fg_wq: Work queue for running the FG algorithm | 178 | * @fg_wq: Work queue for running the FG algorithm |
@@ -212,7 +212,6 @@ struct ab8500_fg { | |||
212 | struct ab8500_fg_avg_cap avg_cap; | 212 | struct ab8500_fg_avg_cap avg_cap; |
213 | struct ab8500 *parent; | 213 | struct ab8500 *parent; |
214 | struct ab8500_gpadc *gpadc; | 214 | struct ab8500_gpadc *gpadc; |
215 | struct abx500_fg_platform_data *pdata; | ||
216 | struct abx500_bm_data *bat; | 215 | struct abx500_bm_data *bat; |
217 | struct power_supply fg_psy; | 216 | struct power_supply fg_psy; |
218 | struct workqueue_struct *fg_wq; | 217 | struct workqueue_struct *fg_wq; |
@@ -2429,7 +2428,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev) | |||
2429 | flush_scheduled_work(); | 2428 | flush_scheduled_work(); |
2430 | power_supply_unregister(&di->fg_psy); | 2429 | power_supply_unregister(&di->fg_psy); |
2431 | platform_set_drvdata(pdev, NULL); | 2430 | platform_set_drvdata(pdev, NULL); |
2432 | kfree(di); | ||
2433 | return ret; | 2431 | return ret; |
2434 | } | 2432 | } |
2435 | 2433 | ||
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { | |||
2442 | {"CCEOC", ab8500_fg_cc_data_end_handler}, | 2440 | {"CCEOC", ab8500_fg_cc_data_end_handler}, |
2443 | }; | 2441 | }; |
2444 | 2442 | ||
2443 | static char *supply_interface[] = { | ||
2444 | "ab8500_chargalg", | ||
2445 | "ab8500_usb", | ||
2446 | }; | ||
2447 | |||
2445 | static int __devinit ab8500_fg_probe(struct platform_device *pdev) | 2448 | static int __devinit ab8500_fg_probe(struct platform_device *pdev) |
2446 | { | 2449 | { |
2450 | struct device_node *np = pdev->dev.of_node; | ||
2451 | struct ab8500_fg *di; | ||
2447 | int i, irq; | 2452 | int i, irq; |
2448 | int ret = 0; | 2453 | int ret = 0; |
2449 | struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; | ||
2450 | struct ab8500_fg *di; | ||
2451 | |||
2452 | if (!plat_data) { | ||
2453 | dev_err(&pdev->dev, "No platform data\n"); | ||
2454 | return -EINVAL; | ||
2455 | } | ||
2456 | 2454 | ||
2457 | di = kzalloc(sizeof(*di), GFP_KERNEL); | 2455 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
2458 | if (!di) | 2456 | if (!di) { |
2457 | dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); | ||
2459 | return -ENOMEM; | 2458 | return -ENOMEM; |
2459 | } | ||
2460 | di->bat = pdev->mfd_cell->platform_data; | ||
2461 | if (!di->bat) { | ||
2462 | if (np) { | ||
2463 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
2464 | if (ret) { | ||
2465 | dev_err(&pdev->dev, | ||
2466 | "failed to get battery information\n"); | ||
2467 | return ret; | ||
2468 | } | ||
2469 | } else { | ||
2470 | dev_err(&pdev->dev, "missing dt node for ab8500_fg\n"); | ||
2471 | return -EINVAL; | ||
2472 | } | ||
2473 | } else { | ||
2474 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2475 | } | ||
2460 | 2476 | ||
2461 | mutex_init(&di->cc_lock); | 2477 | mutex_init(&di->cc_lock); |
2462 | 2478 | ||
@@ -2465,29 +2481,13 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) | |||
2465 | di->parent = dev_get_drvdata(pdev->dev.parent); | 2481 | di->parent = dev_get_drvdata(pdev->dev.parent); |
2466 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2482 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
2467 | 2483 | ||
2468 | /* get fg specific platform data */ | ||
2469 | di->pdata = plat_data->fg; | ||
2470 | if (!di->pdata) { | ||
2471 | dev_err(di->dev, "no fg platform data supplied\n"); | ||
2472 | ret = -EINVAL; | ||
2473 | goto free_device_info; | ||
2474 | } | ||
2475 | |||
2476 | /* get battery specific platform data */ | ||
2477 | di->bat = plat_data->battery; | ||
2478 | if (!di->bat) { | ||
2479 | dev_err(di->dev, "no battery platform data supplied\n"); | ||
2480 | ret = -EINVAL; | ||
2481 | goto free_device_info; | ||
2482 | } | ||
2483 | |||
2484 | di->fg_psy.name = "ab8500_fg"; | 2484 | di->fg_psy.name = "ab8500_fg"; |
2485 | di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; | 2485 | di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; |
2486 | di->fg_psy.properties = ab8500_fg_props; | 2486 | di->fg_psy.properties = ab8500_fg_props; |
2487 | di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); | 2487 | di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); |
2488 | di->fg_psy.get_property = ab8500_fg_get_property; | 2488 | di->fg_psy.get_property = ab8500_fg_get_property; |
2489 | di->fg_psy.supplied_to = di->pdata->supplied_to; | 2489 | di->fg_psy.supplied_to = supply_interface; |
2490 | di->fg_psy.num_supplicants = di->pdata->num_supplicants; | 2490 | di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface), |
2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; | 2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; |
2492 | 2492 | ||
2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * | 2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * |
@@ -2506,8 +2506,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) | |||
2506 | di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); | 2506 | di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); |
2507 | if (di->fg_wq == NULL) { | 2507 | if (di->fg_wq == NULL) { |
2508 | dev_err(di->dev, "failed to create work queue\n"); | 2508 | dev_err(di->dev, "failed to create work queue\n"); |
2509 | ret = -ENOMEM; | 2509 | return -ENOMEM; |
2510 | goto free_device_info; | ||
2511 | } | 2510 | } |
2512 | 2511 | ||
2513 | /* Init work for running the fg algorithm instantly */ | 2512 | /* Init work for running the fg algorithm instantly */ |
@@ -2606,12 +2605,14 @@ free_irq: | |||
2606 | } | 2605 | } |
2607 | free_inst_curr_wq: | 2606 | free_inst_curr_wq: |
2608 | destroy_workqueue(di->fg_wq); | 2607 | destroy_workqueue(di->fg_wq); |
2609 | free_device_info: | ||
2610 | kfree(di); | ||
2611 | |||
2612 | return ret; | 2608 | return ret; |
2613 | } | 2609 | } |
2614 | 2610 | ||
2611 | static const struct of_device_id ab8500_fg_match[] = { | ||
2612 | { .compatible = "stericsson,ab8500-fg", }, | ||
2613 | { }, | ||
2614 | }; | ||
2615 | |||
2615 | static struct platform_driver ab8500_fg_driver = { | 2616 | static struct platform_driver ab8500_fg_driver = { |
2616 | .probe = ab8500_fg_probe, | 2617 | .probe = ab8500_fg_probe, |
2617 | .remove = __devexit_p(ab8500_fg_remove), | 2618 | .remove = __devexit_p(ab8500_fg_remove), |
@@ -2620,6 +2621,7 @@ static struct platform_driver ab8500_fg_driver = { | |||
2620 | .driver = { | 2621 | .driver = { |
2621 | .name = "ab8500-fg", | 2622 | .name = "ab8500-fg", |
2622 | .owner = THIS_MODULE, | 2623 | .owner = THIS_MODULE, |
2624 | .of_match_table = ab8500_fg_match, | ||
2623 | }, | 2625 | }, |
2624 | }; | 2626 | }; |
2625 | 2627 | ||