Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ab8500: Add devicetree support for charger

This patch adds device tree support for ab8500-charger driver

Signed-off-by: Rajanikanth H.V <rajanikanth.hv@stericsson.com>
Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>

authored by

Rajanikanth H.V and committed by
Anton Vorontsov
4aef72db bd9e8ab2

+95 -29
+14
Documentation/devicetree/bindings/mfd/ab8500.txt
··· 36 36 : BTEMP_LOW_MEDIUM : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C 37 37 : BTEMP_MEDIUM_HIGH : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp 38 38 : BTEMP_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp 39 + ab8500-charger : : vddadc : Charger interface 40 + : MAIN_CH_UNPLUG_DET : : main charger unplug detection management (not in 8505) 41 + : MAIN_CHARGE_PLUG_DET : : main charger plug detection management (not in 8505) 42 + : MAIN_EXT_CH_NOT_OK : : main charger not OK 43 + : MAIN_CH_TH_PROT_R : : Die temp is above main charger 44 + : MAIN_CH_TH_PROT_F : : Die temp is below main charger 45 + : VBUS_DET_F : : VBUS falling detected 46 + : VBUS_DET_R : : VBUS rising detected 47 + : USB_LINK_STATUS : : USB link status has changed 48 + : USB_CH_TH_PROT_R : : Die temp is above usb charger 49 + : USB_CH_TH_PROT_F : : Die temp is below usb charger 50 + : USB_CHARGER_NOT_OKR : : allowed USB charger not ok detection 51 + : VBUS_OVV : : Overvoltage on Vbus ball detected (USB charge is stopped) 52 + : CH_WD_EXP : : Charger watchdog detected 39 53 ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter 40 54 SW_CONV_END : : 41 55 ab8500-gpio : : : GPIO Controller
+25
Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
··· 1 + === AB8500 Charger Driver === 2 + 3 + Required Properties: 4 + - compatible = Shall be "stericsson,ab8500-charger" 5 + - battery = Shall be battery specific information 6 + Example: 7 + ab8500_charger { 8 + compatible = "stericsson,ab8500-charger"; 9 + battery = <&ab8500_battery>; 10 + }; 11 + 12 + - vddadc-supply: Supply for USB and Main charger 13 + Example: 14 + ab8500-charger { 15 + vddadc-supply = <&ab8500_ldo_tvout_reg>; 16 + } 17 + - autopower_cfg: 18 + Boolean value depicting the presence of 'automatic poweron after powerloss' 19 + Example: 20 + ab8500-charger { 21 + autopower_cfg; 22 + }; 23 + 24 + For information on battery specific node, Ref: 25 + Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
+6
arch/arm/boot/dts/dbx5x0.dtsi
··· 367 367 battery = <&ab8500_battery>; 368 368 }; 369 369 370 + ab8500_charger { 371 + compatible = "stericsson,ab8500-charger"; 372 + battery = <&ab8500_battery>; 373 + vddadc-supply = <&ab8500_ldo_tvout_reg>; 374 + }; 375 + 370 376 ab8500_usb { 371 377 compatible = "stericsson,ab8500-usb"; 372 378 interrupts = < 90 0x4
+5
drivers/mfd/ab8500-core.c
··· 1041 1041 static struct mfd_cell __devinitdata ab8500_bm_devs[] = { 1042 1042 { 1043 1043 .name = "ab8500-charger", 1044 + .of_compatible = "stericsson,ab8500-charger", 1044 1045 .num_resources = ARRAY_SIZE(ab8500_charger_resources), 1045 1046 .resources = ab8500_charger_resources, 1047 + #ifndef CONFIG_OF 1048 + .platform_data = &ab8500_bm_data, 1049 + .pdata_size = sizeof(ab8500_bm_data), 1050 + #endif 1046 1051 }, 1047 1052 { 1048 1053 .name = "ab8500-btemp",
+45 -29
drivers/power/ab8500_charger.c
··· 23 23 #include <linux/err.h> 24 24 #include <linux/workqueue.h> 25 25 #include <linux/kobject.h> 26 + #include <linux/of.h> 27 + #include <linux/mfd/core.h> 26 28 #include <linux/mfd/abx500/ab8500.h> 27 29 #include <linux/mfd/abx500.h> 28 30 #include <linux/mfd/abx500/ab8500-bm.h> ··· 183 181 * @vbat Battery voltage 184 182 * @old_vbat Previously measured battery voltage 185 183 * @autopower Indicate if we should have automatic pwron after pwrloss 184 + * @autopower_cfg platform specific power config support for "pwron after pwrloss" 186 185 * @parent: Pointer to the struct ab8500 187 186 * @gpadc: Pointer to the struct gpadc 188 - * @pdata: Pointer to the abx500_charger platform data 189 187 * @bat: Pointer to the abx500_bm platform data 190 188 * @flags: Structure for information about events triggered 191 189 * @usb_state: Structure for usb stack information ··· 220 218 int vbat; 221 219 int old_vbat; 222 220 bool autopower; 221 + bool autopower_cfg; 223 222 struct ab8500 *parent; 224 223 struct ab8500_gpadc *gpadc; 225 - struct abx500_bmdevs_plat_data *pdata; 226 224 struct abx500_bm_data *bat; 227 225 struct ab8500_charger_event_flags flags; 228 226 struct ab8500_charger_usb_state usb_state; ··· 324 322 static void ab8500_power_supply_changed(struct ab8500_charger *di, 325 323 struct power_supply *psy) 326 324 { 327 - if (di->pdata->autopower_cfg) { 325 + if (di->autopower_cfg) { 328 326 if (!di->usb.charger_connected && 329 327 !di->ac.charger_connected && 330 328 di->autopower) { ··· 2528 2526 power_supply_unregister(&di->usb_chg.psy); 2529 2527 power_supply_unregister(&di->ac_chg.psy); 2530 2528 platform_set_drvdata(pdev, NULL); 2531 - kfree(di); 2532 2529 2533 2530 return 0; 2534 2531 } 2535 2532 2533 + static char *supply_interface[] = { 2534 + "ab8500_chargalg", 2535 + "ab8500_fg", 2536 + "ab8500_btemp", 2537 + }; 2538 + 2536 2539 static int __devinit ab8500_charger_probe(struct platform_device *pdev) 2537 2540 { 2538 - struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data; 2541 + struct device_node *np = pdev->dev.of_node; 2539 2542 struct ab8500_charger *di; 2540 2543 int irq, i, charger_status, ret = 0; 2541 2544 2542 - if (!plat_data) { 2543 - dev_err(&pdev->dev, "No platform data\n"); 2544 - return -EINVAL; 2545 - } 2546 - 2547 - di = kzalloc(sizeof(*di), GFP_KERNEL); 2548 - if (!di) 2545 + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); 2546 + if (!di) { 2547 + dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); 2549 2548 return -ENOMEM; 2549 + } 2550 + di->bat = pdev->mfd_cell->platform_data; 2551 + if (!di->bat) { 2552 + if (np) { 2553 + ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); 2554 + if (ret) { 2555 + dev_err(&pdev->dev, 2556 + "failed to get battery information\n"); 2557 + return ret; 2558 + } 2559 + di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); 2560 + } else { 2561 + dev_err(&pdev->dev, "missing dt node for ab8500_charger\n"); 2562 + return -EINVAL; 2563 + } 2564 + } else { 2565 + dev_info(&pdev->dev, "falling back to legacy platform data\n"); 2566 + di->autopower_cfg = false; 2567 + } 2550 2568 2551 2569 /* get parent data */ 2552 2570 di->dev = &pdev->dev; ··· 2575 2553 2576 2554 /* initialize lock */ 2577 2555 spin_lock_init(&di->usb_state.usb_lock); 2578 - 2579 - /* get charger specific platform data */ 2580 - di->pdata = plat_data; 2581 - if (!di->pdata) { 2582 - dev_err(di->dev, "no charger platform data supplied\n"); 2583 - ret = -EINVAL; 2584 - goto free_device_info; 2585 - } 2586 2556 2587 2557 di->autopower = false; 2588 2558 ··· 2585 2571 di->ac_chg.psy.properties = ab8500_charger_ac_props; 2586 2572 di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); 2587 2573 di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; 2588 - di->ac_chg.psy.supplied_to = di->pdata->supplied_to; 2589 - di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants; 2574 + di->ac_chg.psy.supplied_to = supply_interface; 2575 + di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), 2590 2576 /* ux500_charger sub-class */ 2591 2577 di->ac_chg.ops.enable = &ab8500_charger_ac_en; 2592 2578 di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; ··· 2603 2589 di->usb_chg.psy.properties = ab8500_charger_usb_props; 2604 2590 di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); 2605 2591 di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; 2606 - di->usb_chg.psy.supplied_to = di->pdata->supplied_to; 2607 - di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; 2592 + di->usb_chg.psy.supplied_to = supply_interface; 2593 + di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), 2608 2594 /* ux500_charger sub-class */ 2609 2595 di->usb_chg.ops.enable = &ab8500_charger_usb_en; 2610 2596 di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; ··· 2620 2606 create_singlethread_workqueue("ab8500_charger_wq"); 2621 2607 if (di->charger_wq == NULL) { 2622 2608 dev_err(di->dev, "failed to create work queue\n"); 2623 - ret = -ENOMEM; 2624 - goto free_device_info; 2609 + return -ENOMEM; 2625 2610 } 2626 2611 2627 2612 /* Init work for HW failure check */ ··· 2762 2749 regulator_put(di->regu); 2763 2750 free_charger_wq: 2764 2751 destroy_workqueue(di->charger_wq); 2765 - free_device_info: 2766 - kfree(di); 2767 - 2768 2752 return ret; 2769 2753 } 2754 + 2755 + static const struct of_device_id ab8500_charger_match[] = { 2756 + { .compatible = "stericsson,ab8500-charger", }, 2757 + { }, 2758 + }; 2770 2759 2771 2760 static struct platform_driver ab8500_charger_driver = { 2772 2761 .probe = ab8500_charger_probe, ··· 2778 2763 .driver = { 2779 2764 .name = "ab8500-charger", 2780 2765 .owner = THIS_MODULE, 2766 + .of_match_table = ab8500_charger_match, 2781 2767 }, 2782 2768 }; 2783 2769