From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch-set adds device tree binding for ab8500 battery-managed devices. Removes the redundant platform structure maintained across bm devices and implements common DT probe routine across all the modules.
Test status: a) Tested across 'legacy platform data' and DT binding support a.1) ab8500_charger driver fails to get regulator in the legacy platform mode. b) Interrupt numbers assigned differs between legacy and FDT mode. (a) Legacy platform_data Mode: root@ME:/ cat /proc/interrupts CPU0 CPU1 483: 0 0 ab8500 ab8500-ponkey-dbf 484: 0 0 ab8500 ab8500-ponkey-dbr 485: 0 0 ab8500 BATT_OVV 494: 0 1 ab8500 495: 0 0 ab8500 ab8500-rtc 501: 0 13 ab8500 NCONV_ACCU 503: 7 22 ab8500 CCEOC 504: 0 1 ab8500 CC_INT_CALIB 505: 0 0 ab8500 LOW_BAT_F 516: 0 34 ab8500 ab8500-gpadc 556: 0 0 ab8500 usb-link-status
(b) FDT Mode: root@ME:/ cat /proc/interrupts CPU0 CPU1 6: 0 0 ab8500 ab8500-ponkey-dbf 7: 0 0 ab8500 ab8500-ponkey-dbr 8: 0 0 ab8500 BATT_OVV 162: 0 7 ab8500 ab8500-gpadc 163: 0 1 ab8500 164: 0 0 ab8500 ab8500-rtc 484: 0 0 ab8500 usb-link-status 499: 0 4 ab8500 NCONV_ACCU 500: 0 0 ab8500 LOW_BAT_F 502: 0 1 ab8500 CC_INT_CALIB 503: 0 6 ab8500 CCEOC
c) Event handlers across bm-modules have been verified only during 'battery discharge process' as 'battery charging process' depends on ab8500-usb code
Rajanikanth H.V (4): mfd: ab8500: add devicetree support for fuelgauge mfd: ab8500: add devicetree support for btemp mfd: ab8500: add devicetree support for charger mfd: ab8500: add devicetree support for chargalg
Documentation/devicetree/bindings/mfd/ab8500.txt | 27 +- .../bindings/power_supply/ab8500/btemp.txt | 16 + .../bindings/power_supply/ab8500/chargalg.txt | 16 + .../bindings/power_supply/ab8500/charger.txt | 25 + .../devicetree/bindings/power_supply/ab8500/fg.txt | 58 +++ arch/arm/boot/dts/dbx5x0.dtsi | 28 +- drivers/mfd/ab8500-core.c | 20 + drivers/power/Kconfig | 6 - drivers/power/Makefile | 2 +- drivers/power/ab8500_bmdata.c | 513 ++++++++++++++++++++ drivers/power/ab8500_btemp.c | 76 +-- drivers/power/ab8500_charger.c | 82 ++-- drivers/power/ab8500_fg.c | 80 +-- drivers/power/abx500_chargalg.c | 56 ++- include/linux/mfd/abx500.h | 34 +- 15 files changed, 876 insertions(+), 163 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/charger.txt create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt create mode 100644 drivers/power/ab8500_bmdata.c
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
- 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 --- Documentation/devicetree/bindings/mfd/ab8500.txt | 7 +- .../devicetree/bindings/power_supply/ab8500/fg.txt | 58 +++ arch/arm/boot/dts/dbx5x0.dtsi | 12 +- drivers/mfd/ab8500-core.c | 5 + drivers/power/Makefile | 2 +- drivers/power/ab8500_bmdata.c | 513 ++++++++++++++++++++ drivers/power/ab8500_btemp.c | 16 +- drivers/power/ab8500_charger.c | 16 +- drivers/power/ab8500_fg.c | 80 +-- drivers/power/abx500_chargalg.c | 8 +- include/linux/mfd/abx500.h | 36 +- 11 files changed, 659 insertions(+), 94 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt create mode 100644 drivers/power/ab8500_bmdata.c
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index ce83c8d..6ca8d81 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -24,7 +24,12 @@ ab8500-bm : : : Battery Manager ab8500-btemp : : : Battery Temperature ab8500-charger : : : Battery Charger ab8500-codec : : : Audio Codec -ab8500-fg : : : Fuel Gauge +ab8500-fg : : vddadc : Fuel Gauge + : NCONV_ACCU : : Accumulate N Sample Conversion + : BATT_OVV : : Battery Over Voltage + : LOW_BAT_F : : LOW threshold battery voltage + : CC_INT_CALIB : : Coulomb Counter Internal Calibration + : CCEOC : : Coulomb Counter End of Conversion ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter SW_CONV_END : : ab8500-gpio : : : GPIO Controller diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt new file mode 100644 index 0000000..28eaf35 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt @@ -0,0 +1,58 @@ +=== AB8500 Fuel Gauge Driver === + +AB8500 is a mixed signal multimedia and power management +device comprising: power and energy-management-module, +wall-charger, usb-charger, audio codec, general purpose adc, +tvout, clock management and sim card interface. + +Fuelgauge support is part of energy-management-modules, other +components of this module are: +main-charger, usb-combo-charger and battery-temperature-monitoring. + +The properties below describes the node for fuelgauge driver. + +Required Properties: +- compatible = This shall be: "stericsson,ab8500-fg" +- battery = Shall be battery specific information + Example: + ab8500_fg { + compatible = "stericsson,ab8500-fg"; + battery = <&ab8500_battery>; + }; + +dependent node: + ab8500_battery: ab8500_battery { + }; + This node will provide information on 'thermistor interface' and + 'battery technology type' used. + +Properties of this node are: +thermistor-on-batctrl: + A boolean value indicating thermistor interface to battery + + Note: + 'btemp' and 'batctrl' are the pins interfaced for battery temperature + measurement, 'btemp' signal is used when NTC(negative temperature + coefficient) resister is interfaced external to battery whereas + 'batctrl' pin is used when NTC resister is internal to battery. + + Example: + ab8500_battery: ab8500_battery { + thermistor-on-batctrl; + }; + indiactes: NTC resister is internal to battery, 'batctrl' is used + for thermal measurement. + + The absence of property 'thermal-on-batctrl' indicates + NTC resister is external to battery and 'btemp' signal is used + for thermal measurement. + +battery-type: + This shall be the battery manufacturing technology type, + allowed types are: + "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn" + Example: + ab8500_battery: ab8500_battery { + stericsson,battery-type = "LIPO"; + } + diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 748ba7a..68317f5 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -352,7 +352,17 @@ vddadc-supply = <&ab8500_ldo_tvout_reg>; };
- ab8500-usb { + ab8500_battery: ab8500_battery { + stericsson,battery-type = "LIPO"; + thermistor-on-batctrl; + }; + + ab8500_fg { + compatible = "stericsson,ab8500-fg"; + battery = <&ab8500_battery>; + }; + + ab8500_usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4 96 0x4 diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 1667c77..7c3017b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1051,8 +1051,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { }, { .name = "ab8500-fg", + .of_compatible = "stericsson,ab8500-fg", .num_resources = ARRAY_SIZE(ab8500_fg_resources), .resources = ab8500_fg_resources, +#ifndef CONFIG_OF + .platform_data = &ab8500_bm_data, + .pdata_size = sizeof(ab8500_bm_data), +#endif }, { .name = "ab8500-chargalg", diff --git a/drivers/power/Makefile b/drivers/power/Makefile index ee58afb..2c58d4e 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o -obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o +obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c new file mode 100644 index 0000000..393ac2b --- /dev/null +++ b/drivers/power/ab8500_bmdata.c @@ -0,0 +1,513 @@ +#include <linux/export.h> +#include <linux/power_supply.h> +#include <linux/of.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-bm.h> + +/* + * These are the defined batteries that uses a NTC and ID resistor placed + * inside of the battery pack. + * Note that the res_to_temp table must be strictly sorted by falling resistance + * values to work. + */ +static struct abx500_res_to_temp temp_tbl_A_thermistor[] = { + {-5, 53407}, + { 0, 48594}, + { 5, 43804}, + {10, 39188}, + {15, 34870}, + {20, 30933}, + {25, 27422}, + {30, 24347}, + {35, 21694}, + {40, 19431}, + {45, 17517}, + {50, 15908}, + {55, 14561}, + {60, 13437}, + {65, 12500}, +}; +static struct abx500_res_to_temp temp_tbl_B_thermistor[] = { + {-5, 165418}, + { 0, 159024}, + { 5, 151921}, + {10, 144300}, + {15, 136424}, + {20, 128565}, + {25, 120978}, + {30, 113875}, + {35, 107397}, + {40, 101629}, + {45, 96592}, + {50, 92253}, + {55, 88569}, + {60, 85461}, + {65, 82869}, +}; +static struct abx500_v_to_cap cap_tbl_A_thermistor[] = { + {4171, 100}, + {4114, 95}, + {4009, 83}, + {3947, 74}, + {3907, 67}, + {3863, 59}, + {3830, 56}, + {3813, 53}, + {3791, 46}, + {3771, 33}, + {3754, 25}, + {3735, 20}, + {3717, 17}, + {3681, 13}, + {3664, 8}, + {3651, 6}, + {3635, 5}, + {3560, 3}, + {3408, 1}, + {3247, 0}, +}; +static struct abx500_v_to_cap cap_tbl_B_thermistor[] = { + {4161, 100}, + {4124, 98}, + {4044, 90}, + {4003, 85}, + {3966, 80}, + {3933, 75}, + {3888, 67}, + {3849, 60}, + {3813, 55}, + {3787, 47}, + {3772, 30}, + {3751, 25}, + {3718, 20}, + {3681, 16}, + {3660, 14}, + {3589, 10}, + {3546, 7}, + {3495, 4}, + {3404, 2}, + {3250, 0}, +}; + +static struct abx500_v_to_cap cap_tbl[] = { + {4186, 100}, + {4163, 99}, + {4114, 95}, + {4068, 90}, + {3990, 80}, + {3926, 70}, + {3898, 65}, + {3866, 60}, + {3833, 55}, + {3812, 50}, + {3787, 40}, + {3768, 30}, + {3747, 25}, + {3730, 20}, + {3705, 15}, + {3699, 14}, + {3684, 12}, + {3672, 9}, + {3657, 7}, + {3638, 6}, + {3556, 4}, + {3424, 2}, + {3317, 1}, + {3094, 0}, +}; + +/* + * Note that the res_to_temp table must be strictly sorted by falling + * resistance values to work. + */ +static struct abx500_res_to_temp temp_tbl[] = { + {-5, 214834}, + { 0, 162943}, + { 5, 124820}, + {10, 96520}, + {15, 75306}, + {20, 59254}, + {25, 47000}, + {30, 37566}, + {35, 30245}, + {40, 24520}, + {45, 20010}, + {50, 16432}, + {55, 13576}, + {60, 11280}, + {65, 9425}, +}; + +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +struct batres_vs_temp temp_to_batres_tbl_thermistor[] = { + { 40, 120}, + { 30, 135}, + { 20, 165}, + { 10, 230}, + { 00, 325}, + {-10, 445}, + {-20, 595}, +}; + +/* + * Note that the batres_vs_temp table must be strictly sorted by falling + * temperature values to work. + */ +struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = { + { 60, 300}, + { 30, 300}, + { 20, 300}, + { 10, 300}, + { 00, 300}, + {-10, 300}, + {-20, 300}, +}; + +/* battery resistance table for LI ION 9100 battery */ +struct batres_vs_temp temp_to_batres_tbl_9100[] = { + { 60, 180}, + { 30, 180}, + { 20, 180}, + { 10, 180}, + { 00, 180}, + {-10, 180}, + {-20, 180}, +}; + +struct abx500_battery_type bat_type_thermistor[] = { +[BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, + .charge_full_design = 612, + .nominal_voltage = 3700, + .termination_vol = 4050, + .termination_curr = 200, + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4000, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +{ + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 53407, + .resis_low = 12500, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor), + .r_to_t_tbl = temp_tbl_A_thermistor, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor), + .v_to_cap_tbl = cap_tbl_A_thermistor, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, + +}, +{ + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 165418, + .resis_low = 82869, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3600, + .termination_vol = 4150, + .termination_curr = 80, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor), + .r_to_t_tbl = temp_tbl_B_thermistor, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor), + .v_to_cap_tbl = cap_tbl_B_thermistor, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +}; + +struct abx500_battery_type bat_type_ext_thermistor[] = { +[BATTERY_UNKNOWN] = { + /* First element always represent the UNKNOWN battery */ + .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, + .resis_high = 0, + .resis_low = 0, + .battery_resistance = 300, + .charge_full_design = 612, + .nominal_voltage = 3700, + .termination_vol = 4050, + .termination_curr = 200, + .recharge_vol = 3990, + .normal_cur_lvl = 400, + .normal_vol_lvl = 4100, + .maint_a_cur_lvl = 400, + .maint_a_vol_lvl = 4050, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 400, + .maint_b_vol_lvl = 4000, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +/* + * These are the batteries that doesn't have an internal NTC resistor to measure + * its temperature. The temperature in this case is measure with a NTC placed + * near the battery but on the PCB. + */ +{ + .name = POWER_SUPPLY_TECHNOLOGY_LIPO, + .resis_high = 76000, + .resis_low = 53000, + .battery_resistance = 300, + .charge_full_design = 900, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +{ + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 30000, + .resis_low = 10000, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +{ + .name = POWER_SUPPLY_TECHNOLOGY_LION, + .resis_high = 95000, + .resis_low = 76001, + .battery_resistance = 300, + .charge_full_design = 950, + .nominal_voltage = 3700, + .termination_vol = 4150, + .termination_curr = 100, + .recharge_vol = 4130, + .normal_cur_lvl = 700, + .normal_vol_lvl = 4200, + .maint_a_cur_lvl = 600, + .maint_a_vol_lvl = 4150, + .maint_a_chg_timer_h = 60, + .maint_b_cur_lvl = 600, + .maint_b_vol_lvl = 4100, + .maint_b_chg_timer_h = 200, + .low_high_cur_lvl = 300, + .low_high_vol_lvl = 4000, + .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), + .r_to_t_tbl = temp_tbl, + .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), + .v_to_cap_tbl = cap_tbl, + .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), + .batres_tbl = temp_to_batres_tbl_thermistor, +}, +}; + +static const struct abx500_bm_capacity_levels cap_levels = { + .critical = 2, + .low = 10, + .normal = 70, + .high = 95, + .full = 100, +}; + +static const struct abx500_fg_parameters fg = { + .recovery_sleep_timer = 10, + .recovery_total_time = 100, + .init_timer = 1, + .init_discard_time = 5, + .init_total_time = 40, + .high_curr_time = 60, + .accu_charging = 30, + .accu_high_curr = 30, + .high_curr_threshold = 50, + .lowbat_threshold = 3100, + .battok_falling_th_sel0 = 2860, + .battok_raising_th_sel1 = 2860, + .user_cap_limit = 15, + .maint_thres = 97, +}; + +static const struct abx500_maxim_parameters maxi_params = { + .ena_maxi = true, + .chg_curr = 910, + .wait_cycles = 10, + .charger_curr_step = 100, +}; + +static const struct abx500_bm_charger_parameters chg = { + .usb_volt_max = 5500, + .usb_curr_max = 1500, + .ac_volt_max = 7500, + .ac_curr_max = 1500, +}; + +struct abx500_bm_data ab8500_bm_data = { + .temp_under = 3, + .temp_low = 8, + .temp_high = 43, + .temp_over = 48, + .main_safety_tmr_h = 4, + .temp_interval_chg = 20, + .temp_interval_nochg = 120, + .usb_safety_tmr_h = 4, + .bkup_bat_v = BUP_VCH_SEL_2P6V, + .bkup_bat_i = BUP_ICH_SEL_150UA, + .no_maintenance = false, + .adc_therm = ABx500_ADC_THERM_BATCTRL, + .chg_unknown_bat = false, + .enable_overshoot = false, + .fg_res = 100, + .cap_levels = &cap_levels, + .bat_type = bat_type_thermistor, + .n_btypes = 3, + .batt_id = 0, + .interval_charging = 5, + .interval_not_charging = 120, + .temp_hysteresis = 3, + .gnd_lift_resistance = 34, + .maxi = &maxi_params, + .chg_params = &chg, + .fg_params = &fg, +}; + +int __devinit +bmdevs_of_probe(struct device *dev, + struct device_node *np, + struct abx500_bm_data **battery) +{ + struct abx500_battery_type *btype; + struct device_node *np_bat_supply; + struct abx500_bm_data *bat; + const char *bat_tech; + int i, thermistor; + + *battery = &ab8500_bm_data; + + /* get phandle to 'battery-info' node */ + np_bat_supply = of_parse_phandle(np, "battery", 0); + if (!np_bat_supply) { + dev_err(dev, "missing property battery\n"); + return -EINVAL; + } + if (of_property_read_bool(np_bat_supply, + "thermistor-on-batctrl")) + thermistor = NTC_INTERNAL; + else + thermistor = NTC_EXTERNAL; + + bat = *battery; + if (thermistor == NTC_EXTERNAL) { + bat->n_btypes = 4; + bat->bat_type = bat_type_ext_thermistor; + bat->adc_therm = ABx500_ADC_THERM_BATTEMP; + } + bat_tech = of_get_property(np_bat_supply, + "stericsson,battery-type", NULL); + if (!bat_tech) + dev_warn(dev, "missing property battery-name/type\n"); + + if (strncmp(bat_tech, "LION", 4) == 0) { + bat->no_maintenance = true; + bat->chg_unknown_bat = true; + bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; + bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; + bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130; + bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; + bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; + } + /* select the battery resolution table */ + for (i = 0; i < bat->n_btypes; ++i) { + btype = (bat->bat_type + i); + if (thermistor == NTC_EXTERNAL) { + btype->batres_tbl = + temp_to_batres_tbl_ext_thermistor; + } else if (strncmp(bat_tech, "LION", 4) == 0) { + btype->batres_tbl = + temp_to_batres_tbl_9100; + } else { + btype->batres_tbl = + temp_to_batres_tbl_thermistor; + } + } + of_node_put(np_bat_supply); + return 0; +} diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index bba3cca..803870e 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -93,7 +93,7 @@ struct ab8500_btemp { struct ab8500 *parent; struct ab8500_gpadc *gpadc; struct ab8500_fg *fg; - struct abx500_btemp_platform_data *pdata; + struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct power_supply btemp_psy; struct ab8500_btemp_events events; @@ -962,10 +962,10 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { + struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data; + struct ab8500_btemp *di; int irq, i, ret = 0; u8 val; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; - struct ab8500_btemp *di;
if (!plat_data) { dev_err(&pdev->dev, "No platform data\n"); @@ -982,21 +982,13 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
/* get btemp specific platform data */ - di->pdata = plat_data->btemp; + di->pdata = plat_data; if (!di->pdata) { dev_err(di->dev, "no btemp platform data supplied\n"); ret = -EINVAL; goto free_device_info; }
- /* get battery specific platform data */ - di->bat = plat_data->battery; - if (!di->bat) { - dev_err(di->dev, "no battery platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - /* BTEMP supply */ di->btemp_psy.name = "ab8500_btemp"; di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index d4f0c98..78a730c 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -220,7 +220,7 @@ struct ab8500_charger { bool autopower; struct ab8500 *parent; struct ab8500_gpadc *gpadc; - struct abx500_charger_platform_data *pdata; + struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct ab8500_charger_event_flags flags; struct ab8500_charger_usb_state usb_state; @@ -2533,9 +2533,9 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
static int __devinit ab8500_charger_probe(struct platform_device *pdev) { - int irq, i, charger_status, ret = 0; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; + struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data; struct ab8500_charger *di; + int irq, i, charger_status, ret = 0;
if (!plat_data) { dev_err(&pdev->dev, "No platform data\n"); @@ -2555,21 +2555,13 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) spin_lock_init(&di->usb_state.usb_lock);
/* get charger specific platform data */ - di->pdata = plat_data->charger; + di->pdata = plat_data; if (!di->pdata) { dev_err(di->dev, "no charger platform data supplied\n"); ret = -EINVAL; goto free_device_info; }
- /* get battery specific platform data */ - di->bat = plat_data->battery; - if (!di->bat) { - dev_err(di->dev, "no battery platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - di->autopower = false;
/* AC supply */ diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index bf02225..e117920 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -22,15 +22,16 @@ #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/kobject.h> -#include <linux/mfd/abx500/ab8500.h> -#include <linux/mfd/abx500.h> #include <linux/slab.h> -#include <linux/mfd/abx500/ab8500-bm.h> #include <linux/delay.h> -#include <linux/mfd/abx500/ab8500-gpadc.h> -#include <linux/mfd/abx500.h> #include <linux/time.h> +#include <linux/of.h> #include <linux/completion.h> +#include <linux/mfd/core.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-bm.h> +#include <linux/mfd/abx500/ab8500-gpadc.h>
#define MILLI_TO_MICRO 1000 #define FG_LSB_IN_MA 1627 @@ -212,7 +213,6 @@ struct ab8500_fg { struct ab8500_fg_avg_cap avg_cap; struct ab8500 *parent; struct ab8500_gpadc *gpadc; - struct abx500_fg_platform_data *pdata; struct abx500_bm_data *bat; struct power_supply fg_psy; struct workqueue_struct *fg_wq; @@ -2429,7 +2429,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev) flush_scheduled_work(); power_supply_unregister(&di->fg_psy); platform_set_drvdata(pdev, NULL); - kfree(di); return ret; }
@@ -2442,21 +2441,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"CCEOC", ab8500_fg_cc_data_end_handler}, };
+static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_usb", +}; + static int __devinit ab8500_fg_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; + struct ab8500_fg *di; int i, irq; int ret = 0; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; - struct ab8500_fg *di; - - if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - }
- di = kzalloc(sizeof(*di), GFP_KERNEL); - if (!di) + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); + if (!di) { + dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); return -ENOMEM; + } + di->bat = pdev->mfd_cell->platform_data; + if (!di->bat) { + if (np) { + ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); + if (ret) { + dev_err(&pdev->dev, + "failed to get battery information\n"); + return ret; + } + } else { + dev_err(&pdev->dev, "missing dt node for ab8500_fg\n"); + return -EINVAL; + } + } else { + dev_info(&pdev->dev, "falling back to legacy platform data\n"); + }
mutex_init(&di->cc_lock);
@@ -2465,29 +2482,13 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) di->parent = dev_get_drvdata(pdev->dev.parent); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- /* get fg specific platform data */ - di->pdata = plat_data->fg; - if (!di->pdata) { - dev_err(di->dev, "no fg platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - - /* get battery specific platform data */ - di->bat = plat_data->battery; - if (!di->bat) { - dev_err(di->dev, "no battery platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - di->fg_psy.name = "ab8500_fg"; di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; di->fg_psy.properties = ab8500_fg_props; di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); di->fg_psy.get_property = ab8500_fg_get_property; - di->fg_psy.supplied_to = di->pdata->supplied_to; - di->fg_psy.num_supplicants = di->pdata->num_supplicants; + di->fg_psy.supplied_to = supply_interface; + di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface), di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
di->bat_cap.max_mah_design = MILLI_TO_MICRO * @@ -2506,7 +2507,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); if (di->fg_wq == NULL) { dev_err(di->dev, "failed to create work queue\n"); - goto free_device_info; + return -ENOMEM; }
/* Init work for running the fg algorithm instantly */ @@ -2605,12 +2606,14 @@ free_irq: } free_inst_curr_wq: destroy_workqueue(di->fg_wq); -free_device_info: - kfree(di); - return ret; }
+static const struct of_device_id ab8500_fg_match[] = { + { .compatible = "stericsson,ab8500-fg", }, + { }, +}; + static struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = __devexit_p(ab8500_fg_remove), @@ -2619,6 +2622,7 @@ static struct platform_driver ab8500_fg_driver = { .driver = { .name = "ab8500-fg", .owner = THIS_MODULE, + .of_match_table = ab8500_fg_match, }, };
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 804b88c..88b5cc1 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -231,7 +231,7 @@ struct abx500_chargalg { struct abx500_chargalg_charger_info chg_info; struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_suspension_status susp_status; - struct abx500_chargalg_platform_data *pdata; + struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct power_supply chargalg_psy; struct ux500_charger *ac_chg; @@ -1802,7 +1802,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
static int __devinit abx500_chargalg_probe(struct platform_device *pdev) { - struct abx500_bm_plat_data *plat_data; + struct abx500_bmdevs_plat_data *plat_data; int ret = 0;
struct abx500_chargalg *di = @@ -1812,10 +1812,8 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
/* get device struct */ di->dev = &pdev->dev; - plat_data = pdev->dev.platform_data; - di->pdata = plat_data->chargalg; - di->bat = plat_data->battery; + di->pdata = plat_data;
/* chargalg supply */ di->chargalg_psy.name = "abx500_chargalg"; diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 1318ca6..bbf3ad6 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -382,39 +382,27 @@ struct abx500_bm_data { int gnd_lift_resistance; const struct abx500_maxim_parameters *maxi; const struct abx500_bm_capacity_levels *cap_levels; - const struct abx500_battery_type *bat_type; + struct abx500_battery_type *bat_type; const struct abx500_bm_charger_parameters *chg_params; const struct abx500_fg_parameters *fg_params; };
-struct abx500_chargalg_platform_data { - char **supplied_to; - size_t num_supplicants; -}; - -struct abx500_charger_platform_data { - char **supplied_to; - size_t num_supplicants; - bool autopower_cfg; -}; +extern struct abx500_bm_data ab8500_bm_data;
-struct abx500_btemp_platform_data { - char **supplied_to; - size_t num_supplicants; +struct abx500_bmdevs_plat_data { + char **supplied_to; + size_t num_supplicants; + bool autopower_cfg; };
-struct abx500_fg_platform_data { - char **supplied_to; - size_t num_supplicants; +enum { + NTC_EXTERNAL = 0, + NTC_INTERNAL, };
-struct abx500_bm_plat_data { - struct abx500_bm_data *battery; - struct abx500_charger_platform_data *charger; - struct abx500_btemp_platform_data *btemp; - struct abx500_fg_platform_data *fg; - struct abx500_chargalg_platform_data *chargalg; -}; +int bmdevs_of_probe(struct device *dev, + struct device_node *np, + struct abx500_bm_data **battery);
int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, u8 value);
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
- 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
[...]
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt new file mode 100644 index 0000000..28eaf35 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt @@ -0,0 +1,58 @@ +=== AB8500 Fuel Gauge Driver ===
+AB8500 is a mixed signal multimedia and power management +device comprising: power and energy-management-module, +wall-charger, usb-charger, audio codec, general purpose adc, +tvout, clock management and sim card interface.
+Fuelgauge support is part of energy-management-modules, other +components of this module are: +main-charger, usb-combo-charger and battery-temperature-monitoring.
+The properties below describes the node for fuelgauge driver.
+Required Properties: +- compatible = This shall be: "stericsson,ab8500-fg" +- battery = Shall be battery specific information
- Example:
- ab8500_fg {
compatible = "stericsson,ab8500-fg";
battery = <&ab8500_battery>;
- };
+dependent node:
- ab8500_battery: ab8500_battery {
- };
- This node will provide information on 'thermistor interface' and
- 'battery technology type' used.
+Properties of this node are: +thermistor-on-batctrl:
- A boolean value indicating thermistor interface to battery
- Note:
- 'btemp' and 'batctrl' are the pins interfaced for battery temperature
- measurement, 'btemp' signal is used when NTC(negative temperature
- coefficient) resister is interfaced external to battery whereas
- 'batctrl' pin is used when NTC resister is internal to battery.
- Example:
- ab8500_battery: ab8500_battery {
thermistor-on-batctrl;
- };
- indiactes: NTC resister is internal to battery, 'batctrl' is used
s/indiactes/indicates
[...]
+int __devinit +bmdevs_of_probe(struct device *dev,
struct device_node *np,
struct abx500_bm_data **battery)
+{
- struct abx500_battery_type *btype;
- struct device_node *np_bat_supply;
- struct abx500_bm_data *bat;
- const char *bat_tech;
- int i, thermistor;
- *battery = &ab8500_bm_data;
- /* get phandle to 'battery-info' node */
- np_bat_supply = of_parse_phandle(np, "battery", 0);
- if (!np_bat_supply) {
dev_err(dev, "missing property battery\n");
return -EINVAL;
- }
- if (of_property_read_bool(np_bat_supply,
"thermistor-on-batctrl"))
thermistor = NTC_INTERNAL;
- else
thermistor = NTC_EXTERNAL;
- bat = *battery;
- if (thermistor == NTC_EXTERNAL) {
bat->n_btypes = 4;
bat->bat_type = bat_type_ext_thermistor;
bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
- }
- bat_tech = of_get_property(np_bat_supply,
"stericsson,battery-type", NULL);
- if (!bat_tech)
dev_warn(dev, "missing property battery-name/type\n");
- if (strncmp(bat_tech, "LION", 4) == 0) {
What if bat_tech is NULL?
[...]
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index bf02225..e117920 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -22,15 +22,16 @@ #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/kobject.h> -#include <linux/mfd/abx500/ab8500.h> -#include <linux/mfd/abx500.h> #include <linux/slab.h> -#include <linux/mfd/abx500/ab8500-bm.h> #include <linux/delay.h> -#include <linux/mfd/abx500/ab8500-gpadc.h> -#include <linux/mfd/abx500.h> #include <linux/time.h> +#include <linux/of.h> #include <linux/completion.h> +#include <linux/mfd/core.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-bm.h> +#include <linux/mfd/abx500/ab8500-gpadc.h> #define MILLI_TO_MICRO 1000 #define FG_LSB_IN_MA 1627 @@ -212,7 +213,6 @@ struct ab8500_fg { struct ab8500_fg_avg_cap avg_cap; struct ab8500 *parent; struct ab8500_gpadc *gpadc;
- struct abx500_fg_platform_data *pdata;
pdata should be removed from the description of the struct members as well.
-- Francesco
On 27 October 2012 20:37, Francesco Lavra francescolavra.fl@gmail.com wrote:
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
bat_tech = of_get_property(np_bat_supply,
"stericsson,battery-type", NULL);
if (!bat_tech)
dev_warn(dev, "missing property battery-name/type\n");
if (strncmp(bat_tech, "LION", 4) == 0) {
What if bat_tech is NULL?
It will be UNKNOWN
On 10/27/2012 06:00 PM, Rajanikanth HV wrote:
On 27 October 2012 20:37, Francesco Lavra francescolavra.fl@gmail.com wrote:
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
bat_tech = of_get_property(np_bat_supply,
"stericsson,battery-type", NULL);
if (!bat_tech)
dev_warn(dev, "missing property battery-name/type\n");
if (strncmp(bat_tech, "LION", 4) == 0) {
What if bat_tech is NULL?
It will be UNKNOWN
I wanted to draw your attention to the fact that if bat_tech is NULL you are passing a NULL pointer to strncmp(), which is not good. So you should assign a default value to bat_tech in case the battery type property is not found in the DT, as below:
if (!bat_tech) { dev_warn(dev, "missing property battery-name/type\n"); bat_tech = "UNKNOWN"; }
-- Francesco
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for battery-temperature-monitor driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com --- Documentation/devicetree/bindings/mfd/ab8500.txt | 6 ++ .../bindings/power_supply/ab8500/btemp.txt | 16 +++++ arch/arm/boot/dts/dbx5x0.dtsi | 5 ++ drivers/mfd/ab8500-core.c | 5 ++ drivers/power/Kconfig | 6 -- drivers/power/ab8500_bmdata.c | 4 +- drivers/power/ab8500_btemp.c | 66 ++++++++++++-------- 7 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index 6ca8d81..179c802 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -30,6 +30,12 @@ ab8500-fg : : vddadc : Fuel Gauge : LOW_BAT_F : : LOW threshold battery voltage : CC_INT_CALIB : : Coulomb Counter Internal Calibration : CCEOC : : Coulomb Counter End of Conversion +ab8500-btemp : : vtvout : Battery Temperature + : BAT_CTRL_INDB : : Battery Removal Indicator + : BTEMP_LOW : : Btemp < BtempLow, if battery temperature is lower than -10°C + : BTEMP_HIGH : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C + : BTEMP_LOW_MEDIUM : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp + : BTEMP_MEDIUM_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp” ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter SW_CONV_END : : ab8500-gpio : : : GPIO Controller diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt new file mode 100644 index 0000000..0ba1bcc --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt @@ -0,0 +1,16 @@ +=== AB8500 Battery Temperature Monitor Driver === + +The properties below describes the node for btemp driver. + +Required Properties: +- compatible = Shall be: "stericsson,ab8500-btemp" +- battery = Shall be battery specific information + + Example: + ab8500_btemp { + compatible = "stericsson,ab8500-btemp"; + battery = <&ab8500_battery>; + }; + +For information on battery specific node, Ref: +Documentation/devicetree/bindings/power_supply/ab8500/fg.txt diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 68317f5..79fdee4 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -362,6 +362,11 @@ battery = <&ab8500_battery>; };
+ ab8500_btemp { + compatible = "stericsson,ab8500-btemp"; + battery = <&ab8500_battery>; + }; + ab8500_usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4 diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 7c3017b..94d45be 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1046,8 +1046,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { }, { .name = "ab8500-btemp", + .of_compatible = "stericsson,ab8500-btemp", .num_resources = ARRAY_SIZE(ab8500_btemp_resources), .resources = ab8500_btemp_resources, +#ifndef CONFIG_OF + .platform_data = &ab8500_bm_data, + .pdata_size = sizeof(ab8500_bm_data), +#endif }, { .name = "ab8500-fg", diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index c1892f3..1434871 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -304,12 +304,6 @@ config AB8500_BM help Say Y to include support for AB8500 battery management.
-config AB8500_BATTERY_THERM_ON_BATCTRL - bool "Thermistor connected on BATCTRL ADC" - depends on AB8500_BM - help - Say Y to enable battery temperature measurements using - thermistor connected on BATCTRL ADC. endif # POWER_SUPPLY
source "drivers/power/avs/Kconfig" diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c index 393ac2b..0475db0 100644 --- a/drivers/power/ab8500_bmdata.c +++ b/drivers/power/ab8500_bmdata.c @@ -29,7 +29,7 @@ static struct abx500_res_to_temp temp_tbl_A_thermistor[] = { {65, 12500}, }; static struct abx500_res_to_temp temp_tbl_B_thermistor[] = { - {-5, 165418}, + {-5, 200000}, { 0, 159024}, { 5, 151921}, {10, 144300}, @@ -237,7 +237,7 @@ struct abx500_battery_type bat_type_thermistor[] = { }, { .name = POWER_SUPPLY_TECHNOLOGY_LIPO, - .resis_high = 165418, + .resis_high = 200000, .resis_low = 82869, .battery_resistance = 300, .charge_full_design = 900, diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 803870e..a6633b4 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -20,11 +20,13 @@ #include <linux/power_supply.h> #include <linux/completion.h> #include <linux/workqueue.h> -#include <linux/mfd/abx500/ab8500.h> +#include <linux/jiffies.h> +#include <linux/of.h> +#include <linux/mfd/core.h> #include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/abx500/ab8500-gpadc.h> -#include <linux/jiffies.h>
#define VTVOUT_V 1800
@@ -76,7 +78,6 @@ struct ab8500_btemp_ranges { * @parent: Pointer to the struct ab8500 * @gpadc: Pointer to the struct gpadc * @fg: Pointer to the struct fg - * @pdata: Pointer to the abx500_btemp platform data * @bat: Pointer to the abx500_bm platform data * @btemp_psy: Structure for BTEMP specific battery properties * @events: Structure for information about events triggered @@ -93,7 +94,6 @@ struct ab8500_btemp { struct ab8500 *parent; struct ab8500_gpadc *gpadc; struct ab8500_fg *fg; - struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct power_supply btemp_psy; struct ab8500_btemp_events events; @@ -955,48 +955,57 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev) flush_scheduled_work(); power_supply_unregister(&di->btemp_psy); platform_set_drvdata(pdev, NULL); - kfree(di);
return 0; }
+static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", +}; + static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { - struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct ab8500_btemp *di; int irq, i, ret = 0; u8 val;
- if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } - - di = kzalloc(sizeof(*di), GFP_KERNEL); - if (!di) + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); + if (!di) { + dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); return -ENOMEM; + } + di->bat = pdev->mfd_cell->platform_data; + if (!di->bat) { + if (np) { + ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); + if (ret) { + dev_err(&pdev->dev, + "failed to get battery information\n"); + return ret; + } + } else { + dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n"); + return -EINVAL; + } + } else { + dev_info(&pdev->dev, "falling back to legacy platform data\n"); + }
/* get parent data */ di->dev = &pdev->dev; di->parent = dev_get_drvdata(pdev->dev.parent); di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
- /* get btemp specific platform data */ - di->pdata = plat_data; - if (!di->pdata) { - dev_err(di->dev, "no btemp platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - /* BTEMP supply */ di->btemp_psy.name = "ab8500_btemp"; di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; di->btemp_psy.properties = ab8500_btemp_props; di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props); di->btemp_psy.get_property = ab8500_btemp_get_property; - di->btemp_psy.supplied_to = di->pdata->supplied_to; - di->btemp_psy.num_supplicants = di->pdata->num_supplicants; + di->btemp_psy.supplied_to = supply_interface; + di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface); di->btemp_psy.external_power_changed = ab8500_btemp_external_power_changed;
@@ -1006,7 +1015,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) create_singlethread_workqueue("ab8500_btemp_wq"); if (di->btemp_wq == NULL) { dev_err(di->dev, "failed to create work queue\n"); - goto free_device_info; + return -ENOMEM; }
/* Init work for measuring temperature periodically */ @@ -1084,12 +1093,14 @@ free_irq: } free_btemp_wq: destroy_workqueue(di->btemp_wq); -free_device_info: - kfree(di); - return ret; }
+static const struct of_device_id ab8500_btemp_match[] = { + { .compatible = "stericsson,ab8500-btemp", }, + { }, +}; + static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = __devexit_p(ab8500_btemp_remove), @@ -1098,6 +1109,7 @@ static struct platform_driver ab8500_btemp_driver = { .driver = { .name = "ab8500-btemp", .owner = THIS_MODULE, + .of_match_table = ab8500_btemp_match, }, };
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for battery-temperature-monitor driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com
Documentation/devicetree/bindings/mfd/ab8500.txt | 6 ++ .../bindings/power_supply/ab8500/btemp.txt | 16 +++++ arch/arm/boot/dts/dbx5x0.dtsi | 5 ++ drivers/mfd/ab8500-core.c | 5 ++ drivers/power/Kconfig | 6 -- drivers/power/ab8500_bmdata.c | 4 +- drivers/power/ab8500_btemp.c | 66 ++++++++++++-------- 7 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index 6ca8d81..179c802 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -30,6 +30,12 @@ ab8500-fg : : vddadc : Fuel Gauge : LOW_BAT_F : : LOW threshold battery voltage : CC_INT_CALIB : : Coulomb Counter Internal Calibration : CCEOC : : Coulomb Counter End of Conversion +ab8500-btemp : : vtvout : Battery Temperature
: BAT_CTRL_INDB : : Battery Removal Indicator
: BTEMP_LOW : : Btemp < BtempLow, if battery temperature is lower than -10°C
: BTEMP_HIGH : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C
: BTEMP_LOW_MEDIUM : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp
: BTEMP_MEDIUM_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp”
BTEMP_HIGH, BTEMP_LOW_MEDIUM and BTEMP_MEDIUM_HIGH are in the wrong order and don't correspond to their description.
-- Francesco
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for ab8500-charger driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com --- Documentation/devicetree/bindings/mfd/ab8500.txt | 14 ++++ .../bindings/power_supply/ab8500/charger.txt | 25 +++++++ arch/arm/boot/dts/dbx5x0.dtsi | 6 ++ drivers/mfd/ab8500-core.c | 5 ++ drivers/power/ab8500_charger.c | 72 ++++++++++++-------- 5 files changed, 94 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index 179c802..045dd87 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -36,6 +36,20 @@ ab8500-btemp : : vtvout : Battery Temperature : BTEMP_HIGH : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C : BTEMP_LOW_MEDIUM : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp : BTEMP_MEDIUM_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp” +ab8500-charger : : vddadc : Charger interface + : MAIN_CH_UNPLUG_DET : : main charger unplug detection management (not in 8505) + : MAIN_CHARGE_PLUG_DET : : main charger plug detection management (not in 8505) + : MAIN_EXT_CH_NOT_OK : : main charger not OK + : MAIN_CH_TH_PROT_R : : Die temp is above main charger + : MAIN_CH_TH_PROT_F : : Die temp is below main charger + : VBUS_DET_F : : VBUS falling detected + : VBUS_DET_R : : VBUS rising detected + : USB_LINK_STATUS : : USB link status has changed + : USB_CH_TH_PROT_R : : Die temp is above usb charger + : USB_CH_TH_PROT_F : : Die temp is below usb charger + : USB_CHARGER_NOT_OKR : : allowed USB charger not ok detection + : VBUS_OVV : : Overvoltage on Vbus ball detected (USB charge is stopped) + : CH_WD_EXP : : Charger watchdog detected ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter SW_CONV_END : : ab8500-gpio : : : GPIO Controller diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt new file mode 100644 index 0000000..6bdbb08 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt @@ -0,0 +1,25 @@ +=== AB8500 Charger Driver === + +Required Properties: +- compatible = Shall be "stericsson,ab8500-charger" +- battery = Shall be battery specific information + Example: + ab8500_charger { + compatible = "stericsson,ab8500-charger"; + battery = <&ab8500_battery>; + }; + +- vddadc-supply: Supply for USB and Main charger + Example: + ab8500-charger { + vddadc-supply = <&ab8500_ldo_tvout_reg>; + } +- autopower_cfg: + Boolean value depicting the presence of 'automatic poweron after powerloss' + Example: + ab8500-charger { + autopower_cfg; + }; + +For information on battery specific node, Ref: +Documentation/devicetree/bindings/power_supply/ab8500/fg.txt diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 79fdee4..b1ecb5d 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -367,6 +367,12 @@ battery = <&ab8500_battery>; };
+ ab8500_charger { + compatible = "stericsson,ab8500-charger"; + battery = <&ab8500_battery>; + vddadc-supply = <&ab8500_ldo_tvout_reg>; + }; + ab8500_usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4 diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 94d45be..c7a120b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1041,8 +1041,13 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { static struct mfd_cell __devinitdata ab8500_bm_devs[] = { { .name = "ab8500-charger", + .of_compatible = "stericsson,ab8500-charger", .num_resources = ARRAY_SIZE(ab8500_charger_resources), .resources = ab8500_charger_resources, +#ifndef CONFIG_OF + .platform_data = &ab8500_bm_data, + .pdata_size = sizeof(ab8500_bm_data), +#endif }, { .name = "ab8500-btemp", diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 78a730c..956943e 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -23,6 +23,8 @@ #include <linux/err.h> #include <linux/workqueue.h> #include <linux/kobject.h> +#include <linux/of.h> +#include <linux/mfd/core.h> #include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500-bm.h> @@ -183,7 +185,6 @@ struct ab8500_charger_usb_state { * @autopower Indicate if we should have automatic pwron after pwrloss * @parent: Pointer to the struct ab8500 * @gpadc: Pointer to the struct gpadc - * @pdata: Pointer to the abx500_charger platform data * @bat: Pointer to the abx500_bm platform data * @flags: Structure for information about events triggered * @usb_state: Structure for usb stack information @@ -218,9 +219,9 @@ struct ab8500_charger { int vbat; int old_vbat; bool autopower; + bool autopower_cfg; struct ab8500 *parent; struct ab8500_gpadc *gpadc; - struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct ab8500_charger_event_flags flags; struct ab8500_charger_usb_state usb_state; @@ -322,7 +323,7 @@ static void ab8500_power_loss_handling(struct ab8500_charger *di) static void ab8500_power_supply_changed(struct ab8500_charger *di, struct power_supply *psy) { - if (di->pdata->autopower_cfg) { + if (di->autopower_cfg) { if (!di->usb.charger_connected && !di->ac.charger_connected && di->autopower) { @@ -2526,25 +2527,45 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) power_supply_unregister(&di->usb_chg.psy); power_supply_unregister(&di->ac_chg.psy); platform_set_drvdata(pdev, NULL); - kfree(di);
return 0; }
+static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + static int __devinit ab8500_charger_probe(struct platform_device *pdev) { - struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct ab8500_charger *di; int irq, i, charger_status, ret = 0;
- if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } - - di = kzalloc(sizeof(*di), GFP_KERNEL); - if (!di) + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); + if (!di) { + dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); return -ENOMEM; + } + di->bat = pdev->mfd_cell->platform_data; + if (!di->bat) { + if (np) { + ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); + if (ret) { + dev_err(&pdev->dev, + "failed to get battery information\n"); + return ret; + } + di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); + } else { + dev_err(&pdev->dev, "missing dt node for ab8500_charger\n"); + return -EINVAL; + } + } else { + dev_info(&pdev->dev, "falling back to legacy platform data\n"); + di->autopower_cfg = false; + }
/* get parent data */ di->dev = &pdev->dev; @@ -2554,14 +2575,6 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock);
- /* get charger specific platform data */ - di->pdata = plat_data; - if (!di->pdata) { - dev_err(di->dev, "no charger platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - di->autopower = false;
/* AC supply */ @@ -2571,8 +2584,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.psy.properties = ab8500_charger_ac_props; di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; - di->ac_chg.psy.supplied_to = di->pdata->supplied_to; - di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants; + di->ac_chg.psy.supplied_to = supply_interface; + di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), /* ux500_charger sub-class */ di->ac_chg.ops.enable = &ab8500_charger_ac_en; di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; @@ -2589,8 +2602,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) di->usb_chg.psy.properties = ab8500_charger_usb_props; di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; - di->usb_chg.psy.supplied_to = di->pdata->supplied_to; - di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; + di->usb_chg.psy.supplied_to = supply_interface; + di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), /* ux500_charger sub-class */ di->usb_chg.ops.enable = &ab8500_charger_usb_en; di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; @@ -2606,7 +2619,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) create_singlethread_workqueue("ab8500_charger_wq"); if (di->charger_wq == NULL) { dev_err(di->dev, "failed to create work queue\n"); - goto free_device_info; + return -ENOMEM; }
/* Init work for HW failure check */ @@ -2748,12 +2761,14 @@ free_regulator: regulator_put(di->regu); free_charger_wq: destroy_workqueue(di->charger_wq); -free_device_info: - kfree(di); - return ret; }
+static const struct of_device_id ab8500_charger_match[] = { + { .compatible = "stericsson,ab8500-charger", }, + { }, +}; + static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, .remove = __devexit_p(ab8500_charger_remove), @@ -2762,6 +2777,7 @@ static struct platform_driver ab8500_charger_driver = { .driver = { .name = "ab8500-charger", .owner = THIS_MODULE, + .of_match_table = ab8500_charger_match, }, };
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for ab8500-charger driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com
[...]
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 78a730c..956943e 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -23,6 +23,8 @@ #include <linux/err.h> #include <linux/workqueue.h> #include <linux/kobject.h> +#include <linux/of.h> +#include <linux/mfd/core.h> #include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500-bm.h> @@ -183,7 +185,6 @@ struct ab8500_charger_usb_state {
- @autopower Indicate if we should have automatic pwron after pwrloss
- @parent: Pointer to the struct ab8500
- @gpadc: Pointer to the struct gpadc
- @pdata: Pointer to the abx500_charger platform data
- @bat: Pointer to the abx500_bm platform data
- @flags: Structure for information about events triggered
- @usb_state: Structure for usb stack information
@@ -218,9 +219,9 @@ struct ab8500_charger { int vbat; int old_vbat; bool autopower;
- bool autopower_cfg;
autopower_cfg should be added in the description of the struct members as well.
-- Francesco
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for charging algorithm driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com --- .../bindings/power_supply/ab8500/chargalg.txt | 16 ++++++ arch/arm/boot/dts/dbx5x0.dtsi | 5 ++ drivers/mfd/ab8500-core.c | 5 ++ drivers/power/abx500_chargalg.c | 54 ++++++++++++++------ include/linux/mfd/abx500.h | 6 --- 5 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt new file mode 100644 index 0000000..ef53283 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt @@ -0,0 +1,16 @@ +=== AB8500 Charging Algorithm Driver === + +The properties below describes the node for chargalg driver. + +Required Properties: +- compatible = Shall be: "stericsson,ab8500-chargalg" +- battery = Shall be battery specific information + +Example: +ab8500_chargalg { + compatible = "stericsson,ab8500-chargalg"; + battery = <&ab8500_battery>; +}; + +For information on battery specific node, Ref: +Documentation/devicetree/bindings/power_supply/ab8500/fg.txt diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index b1ecb5d..a678afa 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -373,6 +373,11 @@ vddadc-supply = <&ab8500_ldo_tvout_reg>; };
+ ab8500_chargalg { + compatible = "stericsson,ab8500-chargalg"; + battery = <&ab8500_battery>; + }; + ab8500_usb { compatible = "stericsson,ab8500-usb"; interrupts = < 90 0x4 diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index c7a120b..afe835b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1071,8 +1071,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { }, { .name = "ab8500-chargalg", + .of_compatible = "stericsson,ab8500-chargalg", .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), .resources = ab8500_chargalg_resources, +#ifndef CONFIG_USE_OF + .platform_data = &ab8500_bm_data, + .pdata_size = sizeof(ab8500_bm_data), +#endif }, };
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 88b5cc1..829fcfd 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -21,6 +21,8 @@ #include <linux/completion.h> #include <linux/workqueue.h> #include <linux/kobject.h> +#include <linux/of.h> +#include <linux/mfd/core.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ux500_chargalg.h> #include <linux/mfd/abx500/ab8500-bm.h> @@ -231,7 +233,6 @@ struct abx500_chargalg { struct abx500_chargalg_charger_info chg_info; struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_suspension_status susp_status; - struct abx500_bmdevs_plat_data *pdata; struct abx500_bm_data *bat; struct power_supply chargalg_psy; struct ux500_charger *ac_chg; @@ -1795,25 +1796,45 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev) flush_scheduled_work(); power_supply_unregister(&di->chargalg_psy); platform_set_drvdata(pdev, NULL); - kfree(di);
return 0; }
+static char *supply_interface[] = { + "ab8500_fg", +}; + static int __devinit abx500_chargalg_probe(struct platform_device *pdev) { - struct abx500_bmdevs_plat_data *plat_data; + struct device_node *np = pdev->dev.of_node; + struct abx500_chargalg *di; int ret = 0;
- struct abx500_chargalg *di = - kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL); - if (!di) + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); + if (!di) { + dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); return -ENOMEM; + } + di->bat = pdev->mfd_cell->platform_data; + if (!di->bat) { + if (np) { + ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); + if (ret) { + dev_err(&pdev->dev, + "failed to get battery information\n"); + return ret; + } + } else { + dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n"); + return -EINVAL; + } + } else { + dev_info(&pdev->dev, "falling back to legacy platform data\n"); + printk("%s falling back to legacy platform data\n", __func__); + }
/* get device struct */ di->dev = &pdev->dev; - plat_data = pdev->dev.platform_data; - di->pdata = plat_data;
/* chargalg supply */ di->chargalg_psy.name = "abx500_chargalg"; @@ -1821,8 +1842,8 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev) di->chargalg_psy.properties = abx500_chargalg_props; di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props); di->chargalg_psy.get_property = abx500_chargalg_get_property; - di->chargalg_psy.supplied_to = di->pdata->supplied_to; - di->chargalg_psy.num_supplicants = di->pdata->num_supplicants; + di->chargalg_psy.supplied_to = supply_interface; + di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface), di->chargalg_psy.external_power_changed = abx500_chargalg_external_power_changed;
@@ -1842,7 +1863,7 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev) create_singlethread_workqueue("abx500_chargalg_wq"); if (di->chargalg_wq == NULL) { dev_err(di->dev, "failed to create work queue\n"); - goto free_device_info; + return -ENOMEM; }
/* Init work for chargalg */ @@ -1883,20 +1904,23 @@ free_psy: power_supply_unregister(&di->chargalg_psy); free_chargalg_wq: destroy_workqueue(di->chargalg_wq); -free_device_info: - kfree(di); - return ret; }
+static const struct of_device_id ab8500_chargalg_match[] = { + { .compatible = "stericsson,ab8500-chargalg", }, + { }, +}; + static struct platform_driver abx500_chargalg_driver = { .probe = abx500_chargalg_probe, .remove = __devexit_p(abx500_chargalg_remove), .suspend = abx500_chargalg_suspend, .resume = abx500_chargalg_resume, .driver = { - .name = "abx500-chargalg", + .name = "ab8500-chargalg", .owner = THIS_MODULE, + .of_match_table = ab8500_chargalg_match, }, };
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index bbf3ad6..a14c1a6 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -389,12 +389,6 @@ struct abx500_bm_data {
extern struct abx500_bm_data ab8500_bm_data;
-struct abx500_bmdevs_plat_data { - char **supplied_to; - size_t num_supplicants; - bool autopower_cfg; -}; - enum { NTC_EXTERNAL = 0, NTC_INTERNAL,
On 10/25/2012 08:30 AM, Rajanikanth H.V wrote:
From: "Rajanikanth H.V" rajanikanth.hv@stericsson.com
This patch adds device tree support for charging algorithm driver
Signed-off-by: Rajanikanth H.V rajanikanth.hv@stericsson.com
[...]
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 88b5cc1..829fcfd 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -21,6 +21,8 @@ #include <linux/completion.h> #include <linux/workqueue.h> #include <linux/kobject.h> +#include <linux/of.h> +#include <linux/mfd/core.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ux500_chargalg.h> #include <linux/mfd/abx500/ab8500-bm.h> @@ -231,7 +233,6 @@ struct abx500_chargalg { struct abx500_chargalg_charger_info chg_info; struct abx500_chargalg_battery_data batt_data; struct abx500_chargalg_suspension_status susp_status;
- struct abx500_bmdevs_plat_data *pdata;
pdata should be removed from the description of the struct members as well.
struct abx500_bm_data *bat; struct power_supply chargalg_psy; struct ux500_charger *ac_chg; @@ -1795,25 +1796,45 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev) flush_scheduled_work(); power_supply_unregister(&di->chargalg_psy); platform_set_drvdata(pdev, NULL);
- kfree(di);
return 0; } +static char *supply_interface[] = {
- "ab8500_fg",
+};
static int __devinit abx500_chargalg_probe(struct platform_device *pdev) {
- struct abx500_bmdevs_plat_data *plat_data;
- struct device_node *np = pdev->dev.of_node;
- struct abx500_chargalg *di; int ret = 0;
- struct abx500_chargalg *di =
kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL);
- if (!di)
- di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
- if (!di) {
return -ENOMEM;dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
- }
- di->bat = pdev->mfd_cell->platform_data;
- if (!di->bat) {
if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
if (ret) {
dev_err(&pdev->dev,
"failed to get battery information\n");
return ret;
}
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
return -EINVAL;
}
- } else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
printk("%s falling back to legacy platform data\n", __func__);
You forgot to remove the printk() call.
-- Francesco