diff mbox

[RFC] : mfd: Implement DT Support for AB8500 Btemp and fg

Message ID 1340974792-26016-1-git-send-email-rajanikanth.hv@stericsson.com
State New
Headers show

Commit Message

"Rajanikanth H.V June 29, 2012, 12:59 p.m. UTC
From: "Rajanikanth H.V" <rajanikanth.hv@linaro.org>

	This patch addes device tree support for
	battery temperature and fuel guage driver

Signed-off-by: Rajanikanth H.V <rajanikanth.hv@linaro.org>
---
 .../bindings/power_supply/ab8500/ab8500-btemp.txt  |  209 +++++++++++++
 .../bindings/power_supply/ab8500/ab8500-fg.txt     |   51 +++
 arch/arm/boot/dts/db8500.dtsi                      |  327 ++++++++++++++++++++
 drivers/mfd/ab8500-core.c                          |   16 +-
 drivers/power/ab8500_btemp.c                       |  299 +++++++++++++++++-
 drivers/power/ab8500_fg.c                          |   58 +++-
 include/linux/mfd/abx500.h                         |   17 +-
 include/linux/of.h                                 |   33 ++
 8 files changed, 966 insertions(+), 44 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
 create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt

Comments

Lee Jones June 29, 2012, 3:47 p.m. UTC | #1
I'm in favour of cutting out the middle-man on this on. I'll do a very 
quick review, then you should just get it up to the LKML and LAKML.

On 29/06/12 13:59, Rajanikanth H.V wrote:
> From: "Rajanikanth H.V" <rajanikanth.hv@linaro.org>
>
> 	This patch addes device tree support for
> 	battery temperature and fuel guage driver

Spell check.

> Signed-off-by: Rajanikanth H.V <rajanikanth.hv@linaro.org>
> ---
>   .../bindings/power_supply/ab8500/ab8500-btemp.txt  |  209 +++++++++++++
>   .../bindings/power_supply/ab8500/ab8500-fg.txt     |   51 +++
>   arch/arm/boot/dts/db8500.dtsi                      |  327 ++++++++++++++++++++
>   drivers/mfd/ab8500-core.c                          |   16 +-
>   drivers/power/ab8500_btemp.c                       |  299 +++++++++++++++++-
>   drivers/power/ab8500_fg.c                          |   58 +++-
>   include/linux/mfd/abx500.h                         |   17 +-
>   include/linux/of.h                                 |   33 ++
>   8 files changed, 966 insertions(+), 44 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
>   create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt

Consider breaking this down into multiple patches. Remembering to keep 
them orthogonal in case of a future revert.

> diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
> new file mode 100644
> index 0000000..9908934
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
> @@ -0,0 +1,209 @@
> +* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
> +
> +	battery temperature monitor:
> +
> +* Required properties:
> +- compatible: "stericsson,ab8500-btemp"
> +
> +* Sub-node:
> +- ab8500_bm_data:
> +
> +example:
> +   ab8500-btemp {
> +       compatible = "stericsson,ab8500-btemp";
> +		...
> +		...
> +       bat = <&ab8500_bm_data>;
> +   };
> +
> +ab8500_bm_data:
> +	Contain the battery management/monitor node with the following
> +	information to support different battery types.
> +
> +{
> +	temp_under			under this temp, charging is stopped
> +	temp_low			between this temp and temp_under charging is reduced
> +	temp_high			between this temp and temp_over charging is reduced
> +	temp_over			over this temp, charging is stopped
> +	temp_now			present battery temperature
> +	temp_interval_chg	temperature measurement interval in s when charging
> +	temp_interval_nochg	temperature measurement interval in s when not charging
> +	main_safety_tmr_h	safety timer for main charger
> +	usb_safety_tmr_h	safety timer for usb charger
> +	bkup_bat_v			voltage which we charge the backup battery with
> +	bkup_bat_i			current which we charge the backup battery with
> +	no_maintenance		indicates that maintenance charging is disabled
> +	abx500_adc_therm	placement of thermistor, batctrl or battemp adc
> +	chg_unknown_bat		flag to enable charging of unknown batteries
> +	enable_overshoot	flag to enable VBAT overshoot control
> +	auto_trig			flag to enable auto adc trigger
> +	fg_res				resistance of FG resistor in 0.1mOhm
> +	n_btypes			number of elements in array bat_type
> +	batt_id				index of the identified battery in array bat_type
> +	interval_charging	charge alg cycle period time when charging (sec)
> +	interval_not_charging charge alg cycle period time when not charging (sec)
> +	temp_hysteresis		temperature hysteresis
> +	gnd_lift_resistance	Battery ground to phone ground resistance (mOhm)
> +}
> +e.g:
> +	ab8500_bm_data: bm_data {
> +		temp_under		 = <3>;
> +		temp_low		 = <8>;
> +		temp_high		 = <43>;
> +		temp_over		 = <48>;
> +		temp_now		 = <0>;
> +		temp_interval_chg   = <20>;
> +		temp_interval_nochg = <120>;
> +		main_safety_tmr_h	= <4>;
> +		usb_safety_tmr_h	= <4>;
> +		bkup_bat_v		= <1>; /* BUP_VCH_SEL_2P6V */
> +		bkup_bat_i		= <4>; /* BUP_ICH_SEL_150UA */
> +		no_maintenance	= <0>;
> +		chg_unknown_bat	= <0>;
> +		enable_overshoot = <0>;
> +		auto_trig		 = <0>;
> +		adc_therm		 = <0>;
> +		fg_res			 = <100>;
> +		batt_id		   	 = <0>;
> +		interval_charging	  = <5>;
> +		interval_not_charging = <120>;
> +		temp_hysteresis	   	  = <3>;
> +		gnd_lift_resistance   = <34>;
> +	};
> +
> +* subnodes for the node 'ab8500_bm_data':
> +	- maxi		: maximization parameters
> +	- cap_levels: capacity in percent for the different capacity levels
> +	- bat_type	: table of supported battery types
> +	- chg_params: charger parameters
> +	- fg_params	: fuel gauge parameters
> +
> +example:
> +ab8500_bm_data: bm_data {
> +	...
> +	...
> +	n_btypes	= <3>; /* number of battery types */
> +	...
> +	maxi        = <&ab8500_bm_data_maxim_parameters>;
> +	cap_levels  = <&ab8500_bm_data_cap_levels>;
> +	bat_type    = <&ab8500_battery_type_0 &ab8500_battery_type_1 &ab8500_battery_type_2>;
> +	chg_params  = <&ab8500_bm_data_charger_parameters>;
> +	fg_params   = <&ab8500_bm_data_fuel_guage_parameters>;
> +
> +};
> +
> +bx500_battery_type:
> +	prepare battery type information from individual battery specification as:
> +	{
> +		name				: battery technology
> +		resis_high			: battery upper resistance limit
> +		resis_low			: battery lower resistance limit
> +		charge_full_design  : Maximum battery capacity in mAh
> +		nominal_voltage		: Nominal voltage of the battery in mV
> +		termination_vol		: max voltage upto which battery can be charged
> +		termination_curr	: battery charging termination current in mA
> +		recharge_vol		: battery voltage limit that will trigger a new
> +								full charging cycle in the case where maintenance
> +								charging has been disabled
> +		normal_cur_lvl		: charger current in normal state in mA
> +		normal_vol_lvl		: charger voltage in normal state in mV
> +		maint_a_cur_lvl		: charger current in maintenance A state in mA
> +		maint_a_vol_lvl		: charger voltage in maintenance A state in mV
> +		maint_a_chg_timer_h	: charge time in maintenance A state
> +		maint_b_cur_lvl		: charger current in maintenance B state in mA
> +		maint_b_vol_lvl		: charger voltage in maintenance B state in mV
> +		maint_b_chg_timer_h	: charge time in maintenance B state
> +		low_high_cur_lvl	: charger current in temp low/high state in mA
> +		low_high_vol_lvl	: charger voltage in temp low/high state in mV'
> +		battery_resistance	: battery inner resistance in mOhm.
> +		n_r_t_tbl_elements 	: number of elements in r_to_t_tbl
> +		r_to_t_tbl			: table containing resistance to temp points
> +		n_v_cap_tbl_elements:	number of elements in v_to_cap_tbl
> +		v_to_cap_tbl		: Voltage to capacity (in %) table
> +		n_batres_tbl_elements: number of elements in the batres_tbl
> +		batres_tbl			: battery internal resistance vs temperature table
> +	}
> +
> +	Note:
> +		Selected battery shall adhere to the specification provided in:
> +		http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf
> +
> +-example:
> +
> +    ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
> +        bat_name             = <3>;
> +        resis_high           = <53407>;
> +        resis_low            = <12500>;
> +        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>;
> +        battery_resistance   = <300>;
> +
> +        n_temp_tbl_elements =     <15>;
> +
> +		r_to_t_tbl - defines one point in a temp to res curve. To be used
> +			in battery packs that combines the identification resistor
> +			with a NTC resistor.
> +
> +        r_to_t_tbl = <
> +                0xfffffffb 53407 /* -5 */
> +                 0 48594	'battery pack temperature in Celcius' 'NTC resistor net total resistance'
> +                 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>;
> +
> +        n_v_cap_tbl_elements = <20>;
> +        v_to_cap_tbl = <	/* Table for translating voltage to capacity */
> +                4171  100	'Voltage in mV'	'Capacity in percent'
> +                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>;
> +
> +        n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
> +        batres_tbl = <	/* defines one point in a temp vs battery internal resistance curve. */
> +                40 120	'battery pack temperature in Celcius' 'battery internal reistance in mOhm'
> +                30 135
> +                20 165
> +                10 230
> +                00 325
> +                0xfffffff6 445 /* -10 */
> +                0xffffffec 595>; /* -20 */
> +    };
> diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
> new file mode 100644
> index 0000000..5e84852
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
> @@ -0,0 +1,51 @@
> +* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
> +	fuel guage:
> +
> +* Required properties:
> +- compatible: "stericsson,ab8500-fg"
> +
> +* Sub-node:
> +- ab8500_bm_data:
> +
> +example:
> +   ab8500-btemp {
> +       compatible = "stericsson,ab8500-fg";
> +		...
> +		...
> +       bat = <&ab8500_bm_data>;
> +   };
> +
> +Refer:
> +	Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt for
> +	information on 'ab8500_bm_data'
> +
> +* subnode for the node 'ab8500_bm_data':
> +	- fg_params	: fuel gauge parameters
> +
> +example:
> +
> +ab8500_bm_data: bm_data {
> +	...
> +	...
> +	...
> +	fg_params = <&ab8500_bm_data_fuel_guage_parameters>;
> +}
> +
> +	/* Fuel gauge algorithm parameters, in seconds */
> +	ab8500_bm_data_fuel_guage_parameters: bm_data_fuel_guage_parameters {
> +		recovery_sleep_timer   = <10>;	/* Time between measurements while recovering */
> +		recovery_total_time    = <100>; /* Total recovery time */
> +		init_timer             = <1>;   /* Measurement interval during startup */
> +		init_discard_time      = <5>;   /* Time we discard voltage measurement at startup */
> +		init_total_time        = <40>;  /* Total init time during startup */
> +		high_curr_time         = <60>;  /* Time current has to be high to go to recovery */
> +		accu_charging          = <30>;  /* FG accumulation time while charging */
> +		accu_high_curr         = <30>;  /* FG accumulation time in high current mode */
> +		high_curr_threshold    = <50>;  /* High current threshold, in mA */
> +		lowbat_threshold       = <3100>;/* Low battery threshold, in mV */
> +		battok_falling_th_sel0 = <2860>;/* Over battery threshold, in mV */
> +		battok_raising_th_sel1 = <2860>;/* Threshold in mV for battOk signal sel0 Resolution in 50 mV step. */
> +		user_cap_limit         = <15>;  /* Threshold in mV for battOk signal sel1 Resolution in 50 mV step. */
> +		maint_thres            = <97>;  /* Capacity reported from user must be within this limit to be considered as sane, in percentage points.
> +	};                                   * This is the threshold where we stop reporting battery full while in maintenance, in per cent
> +	

It looks like you've just copy and pasted lots of code into the 
documentation and commented on it, which isn't really documentation at 
all is it? Use the same layout as all the other docs in similar directories.

All vendor specific properties should have the vendor's name perpended 
e.g. stericsson,maint-thres. Also property names should contain '-', not 
'_'.
									 */
> diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
> index 26f895f..6f3b5df 100644
> --- a/arch/arm/boot/dts/db8500.dtsi
> +++ b/arch/arm/boot/dts/db8500.dtsi
> @@ -330,6 +330,333 @@
>   					vddadc-supply = <&ab8500_ldo_tvout_reg>;
>   				};
>
> +                ab8500-fg {
> +                    compatible = "stericsson,ab8500-fg";
> +                    interrupts = <24 0x4
> +                                  8 0x4
> +                                  28 0x4
> +                                  27 0x4
> +                                  26 0x4>;
> +                    interrupt-names = "NCONV_ACCU",
> +									  "BATT_OVV",
> +									  "LOW_BAT_F",
> +									  "CC_INT_CALIB",
> +									  "CCEOC";

Formatting (throughout).

> +                    supplied_to = "ab8500_chargalg", "ab8500_usb";
> +                    num_supplicants = <2>;
> +                    bat = <&ab8500_bm_data>;
> +                };
> +
> +                ab8500-btemp {
> +                    compatible = "stericsson,ab8500-btemp";
> +                    interrupts = <20 0x04
> +                                  80 0x04
> +                                  81 0x04
> +                                  82 0x04
> +                                  83 0x04>;
> +                    interrupt-names = "BAT_CTRL_INDB",
> +									  "BTEMP_LOW",
> +									  "BTEMP_HIGH",
> +									  "BTEMP_LOW_MEDIUM",
> +									  "BTEMP_MEDIUM_HIGH";
> +                    supplied_to = "ab8500_chargalg", "ab8500_fg";
> +                    num_supplicants = <2>;
> +                    bat = <&ab8500_bm_data>;
> +                };
> +
> +                ab8500_battery_type_0: ab8500_battery_unknown {
> +                    bat_name            =     <0>;
> +                    resis_high          =     <0>;
> +                    resis_low           =     <0>;
> +                    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>;
> +                    battery_resistance  =     <300>;
> +
> +                    n_temp_tbl_elements =     <15>;
> +                    r_to_t_tbl = <
> +                            0xfffffffb 214834 /* -5 */
> +                            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>;
> +
> +                    n_v_cap_tbl_elements = <24>;
> +                    v_to_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>;
> +
> +                    n_batres_tbl_elements = <7>;
> +                    batres_tbl = <
> +                            40 120
> +                            30 135
> +                            20 165
> +                            10 230
> +                            00 325
> +                            0xfffffff6 445 /* -10 */
> +                            0xffffffec 595>; /* -20 */
> +                };
> +
> +                ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
> +                    bat_name             = <3>;
> +                    resis_high           = <53407>;
> +                    resis_low            = <12500>;
> +                    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>;
> +                    battery_resistance   = <300>;
> +
> +                    n_temp_tbl_elements =     <15>;
> +                    r_to_t_tbl = <
> +                            0xfffffffb 53407 /* -5 */
> +                             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>;
> +
> +                    n_v_cap_tbl_elements = <20>;
> +                    v_to_cap_tbl = <
> +                            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>;
> +
> +                    n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
> +                    batres_tbl = <
> +                            40 120
> +                            30 135
> +                            20 165
> +                            10 230
> +                            00 325
> +                            0xfffffff6 445 /* -10 */
> +                            0xffffffec 595>; /* -20 */
> +                };
> +
> +                ab8500_battery_type_2: ab8500_battery_therm_on_batctrl_1 {
> +                    bat_name            = <3>;
> +                    resis_high          = <165418>;
> +                    resis_low           = <82869>;
> +                    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>;
> +                    battery_resistance  = <300>;
> +
> +                    n_temp_tbl_elements = <15>;
> +                    r_to_t_tbl = <
> +                               0xfffffffb  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>;
> +
> +                    n_v_cap_tbl_elements = <20>;
> +                    v_to_cap_tbl = <
> +                            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>;
> +
> +                    n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
> +                    batres_tbl = <
> +                            40 120
> +                            30 135
> +                            20 165
> +                            10 230
> +                            00 325
> +                            0xfffffff6 445 /* -10 */
> +                            0xffffffec 595>; /* -20 */
> +                };
> +
> +                ab8500_bm_data_cap_levels: bm_data_cap_levels {
> +                    critical   = <2>;
> +                    low        = <10>;
> +                    normal     = <70>;
> +                    high       = <95>;
> +                    full       = <100>;
> +                };
> +
> +                ab8500_bm_data_maxim_parameters: bm_data_maxim_parameters {
> +                    ena_maxi     = <1>;
> +                    chg_curr     = <910>;
> +                    wait_cycles = <10>;
> +                    charger_curr_step = <100>;
> +                };
> +
> +                ab8500_bm_data_charger_parameters: bm_data_charger_parameters {
> +                    usb_volt_max = <5500>;
> +                    usb_curr_max = <1500>;
> +                    ac_volt_max  = <7500>;
> +                    ac_curr_max  = <1500>;
> +                };
> +
> +                ab8500_bm_data_fuel_guage_parameters: bm_data_fuel_guage_parameters {
> +                    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>;
> +                };
> +
> +                ab8500_bm_data: bm_data {
> +                    temp_under            = <3>;
> +                    temp_low              = <8>;
> +                    temp_high             = <43>;
> +                    temp_over             = <48>;
> +                    temp_now              = <0>;
> +                    temp_interval_chg     = <20>;
> +                    temp_interval_nochg   = <120>;
> +                    main_safety_tmr_h     = <4>;
> +                    usb_safety_tmr_h      = <4>;
> +                    bkup_bat_v            = <1>; /* BUP_VCH_SEL_2P6V */
> +                    bkup_bat_i            = <4>; /* BUP_ICH_SEL_150UA */
> +                    no_maintenance        = <0>; /* CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
> +                    chg_unknown_bat       = <0>; /* CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
> +                    enable_overshoot      = <0>;
> +                    auto_trig             = <0>;
> +                    adc_therm             = <0>;
> +                    fg_res                = <100>;
> +                    n_btypes              = <3>;
> +                    batt_id               = <0>;
> +                    interval_charging     = <5>;
> +                    interval_not_charging = <120>;
> +                    temp_hysteresis       = <3>;
> +                    gnd_lift_resistance   = <34>;
> +                    maxi                  = <&ab8500_bm_data_maxim_parameters>;
> +                    cap_levels            = <&ab8500_bm_data_cap_levels>;
> +                    bat_type              = <&ab8500_battery_type_0 &ab8500_battery_type_1 &ab8500_battery_type_2>;
> +                    chg_params            = <&ab8500_bm_data_charger_parameters>;
> +                    fg_params             = <&ab8500_bm_data_fuel_guage_parameters>;
> +                };
> +

It looks like you've just taken values for all of the possible 
combinations. Is this to support different batteries, or different 
platforms/machines?

>   				ab8500-usb {
>   					compatible = "stericsson,ab8500-usb";
>   					interrupts = < 90 0x4
> diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
> index 6d613e8..837488b 100644
> --- a/drivers/mfd/ab8500-core.c
> +++ b/drivers/mfd/ab8500-core.c
> @@ -1419,15 +1419,15 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
>   					ab8500->irq_base);
>   		if (ret)
>   			goto out_freeirq;
> -	}
>
> -	if (!no_bm) {
> -		/* Add battery management devices */
> -		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
> -				      ARRAY_SIZE(ab8500_bm_devs), NULL,
> -				      ab8500->irq_base);
> -		if (ret)
> -			dev_err(ab8500->dev, "error adding bm devices\n");
> +		if (!no_bm) {
> +			/* Add battery management devices */
> +			ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
> +				ARRAY_SIZE(ab8500_bm_devs), NULL,
> +				ab8500->irq_base);
> +			if (ret)
> +				dev_err(ab8500->dev, "error adding bm devices\n");
> +		}
>   	}

Can you push you branch somewhere public, so I can get more context please?

>   	if (is_ab9540(ab8500))
> diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
> index bba3cca..04da929 100644
> --- a/drivers/power/ab8500_btemp.c
> +++ b/drivers/power/ab8500_btemp.c
> @@ -20,6 +20,7 @@
>   #include <linux/power_supply.h>
>   #include <linux/completion.h>
>   #include <linux/workqueue.h>
> +#include <linux/of.h>
>   #include <linux/mfd/abx500/ab8500.h>
>   #include <linux/mfd/abx500.h>
>   #include <linux/mfd/abx500/ab8500-bm.h>
> @@ -480,7 +481,7 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
>   		vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
>   		if (vntc < 0) {
>   			dev_err(di->dev,
> -				"%s gpadc conversion failed,"
> +				"%s gpadc conversion failed, "

Unrelated white space change. Was this intentional?

>   				" using previous value\n", __func__);
>   			return prev;
>   		}
> @@ -960,15 +961,249 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
>   	return 0;
>   }
>
> +int populate_abx8500_bm_data(struct device *dev,
> +		struct abx500_bm_data *bm_data,
> +		struct device_node *np)
> +{
> +	int i, plen, itbl, ret = 0;
> +	phandle *temp_phandle;
> +	struct abx500_battery_type *temp_bat_type;
> +	struct property *pbat_type;
> +	struct device_node *np_bat;
> +	const __be32 *p;
> +	u32 u;
> +
> +#define get_bm_data_property(node_p, prop_name)\

Whoa! Surely not?

Read Documentation/CodingStyle - Chapter 12.

... use an inline function instead.

> +	be32_to_cpup(of_get_property(node_p, prop_name, NULL));
> +
> +	temp_phandle = (phandle *)of_get_property(np, "bat", NULL);
> +	BUG_ON(!temp_phandle);
> +	np_bat = of_find_node_by_phandle(be32_to_cpup(temp_phandle));
> +	BUG_ON(!np_bat);

Why have you killed the kernel here instead of returning an error?

> +	bm_data->temp_under = get_bm_data_property(np_bat, "temp_under");
> +	bm_data->temp_low = get_bm_data_property(np_bat, "temp_low");
> +	bm_data->temp_high = get_bm_data_property(np_bat, "temp_high");
> +	bm_data->temp_over = get_bm_data_property(np_bat, "temp_over");
> +	bm_data->temp_now = get_bm_data_property(np_bat, "temp_now");
> +	bm_data->temp_interval_chg =
> +		get_bm_data_property(np_bat, "temp_interval_chg");
> +	bm_data->temp_interval_nochg =
> +		 get_bm_data_property(np_bat, "temp_interval_nochg");
> +	bm_data->main_safety_tmr_h =
> +		 get_bm_data_property(np_bat, "main_safety_tmr_h");
> +	bm_data->usb_safety_tmr_h =
> +		 get_bm_data_property(np_bat, "usb_safety_tmr_h");
> +	bm_data->bkup_bat_v =
> +		 get_bm_data_property(np_bat, "bkup_bat_v");
> +	bm_data->bkup_bat_i =
> +		 get_bm_data_property(np_bat, "bkup_bat_i");
> +	bm_data->no_maintenance =
> +		 get_bm_data_property(np_bat, "no_maintenance");
> +	bm_data->chg_unknown_bat =
> +		 get_bm_data_property(np_bat, "chg_unknown_bat");
> +	bm_data->enable_overshoot =
> +		 get_bm_data_property(np_bat, "enable_overshoot");
> +	bm_data->auto_trig =
> +		 get_bm_data_property(np_bat, "auto_trig");
> +	bm_data->adc_therm =
> +		 get_bm_data_property(np_bat, "adc_therm");
> +	bm_data->fg_res =
> +		 get_bm_data_property(np_bat, "fg_res");
> +	bm_data->n_btypes =
> +		 get_bm_data_property(np_bat, "n_btypes");
> +	bm_data->batt_id =
> +		 get_bm_data_property(np_bat, "batt_id");
> +	bm_data->interval_charging =
> +		 get_bm_data_property(np_bat, "interval_charging");
> +	bm_data->interval_not_charging =
> +		get_bm_data_property(np_bat, "interval_not_charging");
> +	bm_data->temp_hysteresis =
> +		get_bm_data_property(np_bat, "temp_hysteresis");
> +	bm_data->gnd_lift_resistance =
> +		get_bm_data_property(np_bat, "gnd_lift_resistance");
> +
> +	temp_phandle = (phandle *)of_get_property(np_bat, "bat_type", &plen);

Read Documentation/CodingStyle - Chapter 4.

> +	if (temp_phandle == NULL) {
> +		dev_warn(dev, "battery type not found\n");
> +		return -EINVAL;
> +	}
> +
> +	plen = plen/sizeof(u32);
> +
> +	if (bm_data->n_btypes != plen) {
> +		dev_crit(dev, "Invalid number of battery types\n");
> +		return -EINVAL;
> +	}
> +
> +	bm_data->bat_type =
> +		kzalloc(plen * sizeof(struct abx500_battery_type), GFP_KERNEL);
> +	if (bm_data->bat_type == NULL) {
> +		dev_crit(dev, "no mem for bm_data->bat_type\n");
> +		return -ENOMEM;
> +	}
> +
> +	of_node_put(np_bat);
> +
> +	/*
> +	 * traverse 'plen' times in 'allnext' for battery types and
> +	 * fillup bm_data->bat_type
> +	 */
> +	i = 0;
> +	for_each_node_by_phandle(np_bat, plen, temp_phandle)
> +	{
> +		temp_bat_type = (struct abx500_battery_type *)
> +				(bm_data->bat_type + i++);
> +		temp_bat_type->name	=
> +		 get_bm_data_property(np_bat, "bat_name");

Random formatting (throughout)

> +		temp_bat_type->resis_high =
> +		 get_bm_data_property(np_bat, "resis_high");
> +		temp_bat_type->resis_low =
> +		 get_bm_data_property(np_bat, "resis_low");
> +		temp_bat_type->charge_full_design =
> +		 get_bm_data_property(np_bat, "charge_full_design");
> +		temp_bat_type->nominal_voltage =
> +		 get_bm_data_property(np_bat, "nominal_voltage");
> +		temp_bat_type->termination_vol =
> +		 get_bm_data_property(np_bat, "termination_vol");
> +		temp_bat_type->termination_curr =
> +		 get_bm_data_property(np_bat, "termination_curr");
> +		temp_bat_type->recharge_vol	=
> +		 get_bm_data_property(np_bat, "recharge_vol");
> +		temp_bat_type->normal_cur_lvl =
> +		 get_bm_data_property(np_bat, "normal_cur_lvl");
> +		temp_bat_type->normal_vol_lvl =
> +		 get_bm_data_property(np_bat, "normal_vol_lvl");
> +		temp_bat_type->maint_a_cur_lvl =
> +		 get_bm_data_property(np_bat, "maint_a_cur_lvl");
> +		temp_bat_type->maint_a_vol_lvl =
> +		 get_bm_data_property(np_bat, "maint_a_vol_lvl");
> +		temp_bat_type->maint_a_chg_timer_h =
> +		 get_bm_data_property(np_bat, "maint_a_chg_timer_h");
> +		temp_bat_type->maint_b_cur_lvl =
> +		 get_bm_data_property(np_bat, "maint_b_cur_lvl");
> +		temp_bat_type->maint_b_vol_lvl =
> +		 get_bm_data_property(np_bat, "maint_b_vol_lvl");
> +		temp_bat_type->maint_b_chg_timer_h =
> +		 get_bm_data_property(np_bat, "maint_b_chg_timer_h");
> +		temp_bat_type->low_high_cur_lvl =
> +		 get_bm_data_property(np_bat, "low_high_cur_lvl");
> +		temp_bat_type->low_high_vol_lvl =
> +		 get_bm_data_property(np_bat, "low_high_vol_lvl");
> +		temp_bat_type->battery_resistance =
> +		 get_bm_data_property(np_bat, "battery_resistance");
> +
> +		temp_bat_type->n_temp_tbl_elements =
> +			get_bm_data_property(np_bat, "n_temp_tbl_elements");
> +		temp_bat_type->r_to_t_tbl = (struct abx500_res_to_temp *)
> +			kzalloc(sizeof(struct abx500_res_to_temp) *
> +			temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
> +		if (temp_bat_type->r_to_t_tbl == NULL) {
> +			dev_crit(dev, "no mem for r_to_t_tbl\n");
> +			kfree(bm_data->bat_type);
> +			return -ENOMEM;
> +		}
> +		itbl = 0;
> +		of_property_for_each_u32(np_bat, "r_to_t_tbl", pbat_type, p, u)
> +			*((int *)(temp_bat_type->r_to_t_tbl) + itbl++) = (int)u;

Eh!? Does this even compile?

It's also pretty ugly and unreadable.

> +
> +		temp_bat_type->n_v_cap_tbl_elements =
> +			get_bm_data_property(np_bat, "n_v_cap_tbl_elements");
> +		temp_bat_type->v_to_cap_tbl = (struct abx500_v_to_cap *)
> +			kzalloc(sizeof(struct abx500_v_to_cap) *
> +			temp_bat_type->n_v_cap_tbl_elements, GFP_KERNEL);
> +		if (temp_bat_type->v_to_cap_tbl == NULL) {
> +			ret = -ENOMEM;
> +			dev_crit(dev, "no mem for v_to_cap_tbl\n");
> +			goto out_free_mem1;
> +		}
> +		itbl = 0;
> +		of_property_for_each_u32(np_bat,
> +			"v_to_cap_tbl", pbat_type, p, u)
> +			*((int *)(temp_bat_type->v_to_cap_tbl) + itbl++) =
> +				(int)u;

And again. Am I missing something?

> +		temp_bat_type->n_batres_tbl_elements =
> +			get_bm_data_property(np_bat, "n_batres_tbl_elements");
> +		temp_bat_type->batres_tbl = (struct batres_vs_temp *)

Is this (another other like it) cast nessersary?

> +			kzalloc(sizeof(struct batres_vs_temp) *
> +			temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
> +		if (temp_bat_type->batres_tbl == NULL) {
> +			ret = -ENOMEM;
> +			dev_crit(dev, "no mem for batres_tbl\n");
> +			goto out_free_mem2;
> +		}
> +		itbl = 0;
> +		of_property_for_each_u32(np_bat, "batres_tbl", pbat_type, p, u)
> +			*((int *)(temp_bat_type->batres_tbl) + itbl++) = (int)u;
> +	}
> +
> +	of_node_put(np_bat);
> +
> +	bm_data->chg_params = (struct abx500_bm_charger_parameters *)
> +		kzalloc(sizeof(struct abx500_bm_charger_parameters),
> +			GFP_KERNEL);
> +	if (bm_data->chg_params == NULL) {
> +		dev_crit(dev, "Failed to alloc memory for chg_params\n");
> +		ret = -ENOMEM;
> +		goto out_free_mem3;
> +	}
> +	itbl = 0;
> +	of_property_for_each_u32(np_bat, "chg_params", pbat_type, p, u)
> +		*((int *)(bm_data->chg_params) + itbl++) = (int)u;
> +
> +	bm_data->fg_params = (struct abx500_fg_parameters *)
> +		kzalloc(sizeof(struct abx500_fg_parameters), GFP_KERNEL);
> +	if (bm_data->fg_params == NULL) {
> +		dev_crit(dev, "Failed to alloc memory for fg_params\n");
> +		ret = -ENOMEM;
> +		goto out_free_mem4;
> +	}
> +	itbl = 0;
> +	of_property_for_each_u32(np_bat, "fg_params", pbat_type, p, u)
> +		*((int *)(bm_data->fg_params) + itbl++) = (int)u;

There seems like an awful lot of code duplication going on here.
> +
> +	return ret;
> +
> +out_free_mem1:
> +	kfree(bm_data->bat_type);
> +	kfree(temp_bat_type->r_to_t_tbl);
> +	return ret;
> +
> +out_free_mem2:
> +	kfree(bm_data->bat_type);
> +	kfree(temp_bat_type->r_to_t_tbl);
> +	kfree(temp_bat_type->v_to_cap_tbl);
> +	return ret;
> +
> +out_free_mem3:
> +	kfree(bm_data->bat_type);
> +	kfree(temp_bat_type->r_to_t_tbl);
> +	kfree(temp_bat_type->v_to_cap_tbl);
> +	kfree(temp_bat_type->batres_tbl);
> +	return ret;
> +
> +out_free_mem4:
> +	kfree(bm_data->bat_type);
> +	kfree(temp_bat_type->r_to_t_tbl);
> +	kfree(temp_bat_type->v_to_cap_tbl);
> +	kfree(temp_bat_type->batres_tbl);
> +	kfree(bm_data->chg_params);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(populate_abx8500_bm_data);
> +
>   static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
>   {
>   	int irq, i, ret = 0;
>   	u8 val;
> -	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
> +	struct device_node *np = pdev->dev.of_node;

No, it's meant to work with _both_ platform and Device Tree registation.

>   	struct ab8500_btemp *di;
> +	const unsigned int *btemp_p_val;
> +	const char *pvalue = NULL;

value is not a good variable name.

> -	if (!plat_data) {
> -		dev_err(&pdev->dev, "No platform data\n");
> +	if (!np) {
> +		dev_err(&pdev->dev, "No platform data or DT found\n");

How do you know there is no platform data found? You haven't even looked.

>   		return -EINVAL;
>   	}
>
> @@ -982,20 +1217,46 @@ 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;
> -	if (!di->pdata) {
> -		dev_err(di->dev, "no btemp platform data supplied\n");
> -		ret = -EINVAL;
> -		goto free_device_info;
> +	btemp_p_val = of_get_property(np, "num_supplicants", NULL);
> +	BUG_ON(!btemp_p_val);

DEAD!

> +	di->pdata =
> +		kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL);
> +	if (di->pdata == NULL) {
> +		kfree(di);
> +		return -ENOMEM;
>   	}
>
> -	/* get battery specific platform data */
> -	di->bat = plat_data->battery;
> +	di->pdata->num_supplicants = be32_to_cpup(btemp_p_val);
> +	di->pdata->supplied_to =
> +		kzalloc(di->pdata->num_supplicants *
> +			sizeof(const char *), GFP_KERNEL);
> +	if (di->pdata->supplied_to == NULL) {
> +		kfree(di);
> +		kfree(di->pdata);
> +		return -ENOMEM;
> +	}
> +
> +	for (val = 0; val < di->pdata->num_supplicants; ++val)
> +		if (of_property_read_string_index
> +			(np, "supplied_to", val, &pvalue) == 0)
> +			*(di->pdata->supplied_to + val) = (char *)pvalue;
> +		else {
> +			dev_warn(di->dev, "insufficient number of supplied_to data found\n");
> +			goto free_device_info;
> +		}
> +	dev_dbg(di->dev, "getting DT battery information\n");
> +	di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
>   	if (!di->bat) {
> -		dev_err(di->dev, "no battery platform data supplied\n");
> -		ret = -EINVAL;
> +		kfree(di);
> +		kfree(di->pdata);
> +		return -ENOMEM;
> +	}
> +	if (populate_abx8500_bm_data(di->dev, di->bat, np) < 0) {
> +		dev_warn(di->dev, "Failed to bind DT\n");
>   		goto free_device_info;
>   	}
> +	dev_dbg(di->dev, "getting DT battery information...done\n");
>
>   	/* BTEMP supply */
>   	di->btemp_psy.name = "ab8500_btemp";
> @@ -1008,7 +1269,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
>   	di->btemp_psy.external_power_changed =
>   		ab8500_btemp_external_power_changed;
>
> -

Unrelated whitespace change.

>   	/* Create a work queue for the btemp */
>   	di->btemp_wq =
>   		create_singlethread_workqueue("ab8500_btemp_wq");
> @@ -1016,7 +1276,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
>   		dev_err(di->dev, "failed to create work queue\n");
>   		goto free_device_info;
>   	}
> -

And again.

>   	/* Init work for measuring temperature periodically */
>   	INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work,
>   		ab8500_btemp_periodic_work);
> @@ -1090,14 +1349,23 @@ free_irq:
>   		irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
>   		free_irq(irq, di);
>   	}
> +

.

>   free_btemp_wq:
>   	destroy_workqueue(di->btemp_wq);
> +

.

>   free_device_info:
>   	kfree(di);
> +	kfree(di->pdata);
> +	kfree(di->bat);
>
>   	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),
> @@ -1106,6 +1374,7 @@ static struct platform_driver ab8500_btemp_driver = {
>   	.driver = {
>   		.name = "ab8500-btemp",
>   		.owner = THIS_MODULE,
> +		.of_match_table = ab8500_btemp_match,
>   	},
>   };
>
> diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
> index bf02225..1d0e32a 100644
> --- a/drivers/power/ab8500_fg.c
> +++ b/drivers/power/ab8500_fg.c
> @@ -31,6 +31,7 @@
>   #include <linux/mfd/abx500.h>
>   #include <linux/time.h>
>   #include <linux/completion.h>
> +#include <linux/of.h>
>
>   #define MILLI_TO_MICRO			1000
>   #define FG_LSB_IN_MA			1627
> @@ -2446,11 +2447,12 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
>   {
>   	int i, irq;
>   	int ret = 0;
> -	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;

As above.

> +	const char *fg_p_val;
> +	struct device_node *np = pdev->dev.of_node;
>   	struct ab8500_fg *di;
>
> -	if (!plat_data) {
> -		dev_err(&pdev->dev, "No platform data\n");
> +	if (!np) {
> +		dev_err(&pdev->dev, "No DT node for platform data available\n");
>   		return -EINVAL;
>   	}
>
> @@ -2464,20 +2466,42 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
>   	di->dev = &pdev->dev;
>   	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;
> +	di->pdata =
> +		kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL);
> +	if (di->pdata == NULL) {
> +		kfree(di);
> +		return -ENOMEM;
> +	}
> +	di->pdata->num_supplicants =
> +		be32_to_cpup(of_get_property(np, "num_supplicants", NULL));
> +	di->pdata->supplied_to =
> +		kzalloc(di->pdata->num_supplicants *
> +			sizeof(const char *), GFP_KERNEL);
> +	if (di->pdata->supplied_to == NULL) {
> +		kfree(di);
> +		kfree(di->pdata);
> +		return -ENOMEM;
>   	}
>
> +	for (i = 0; i < di->pdata->num_supplicants; ++i)
> +		if (of_property_read_string_index
> +			(np, "supplied_to", i, &fg_p_val) == 0)
> +			*(di->pdata->supplied_to + i) = (char *)fg_p_val;
> +		else {
> +				dev_warn(di->dev, "insufficient number of supplied_to data found\n");
> +				goto free_device_info;
> +			}
> +
>   	/* get battery specific platform data */
> -	di->bat = plat_data->battery;
> +	di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
>   	if (!di->bat) {
> -		dev_err(di->dev, "no battery platform data supplied\n");
> -		ret = -EINVAL;
> +		kfree(di);
> +		kfree(di->pdata);
> +		return -ENOMEM;
> +	}
> +	ret = populate_abx8500_bm_data(di->dev, di->bat, np);
> +	if (ret < 0) {
> +		dev_warn(di->dev, "Failed to bind DT\n");
>   		goto free_device_info;
>   	}
>
> @@ -2607,10 +2631,15 @@ free_inst_curr_wq:
>   	destroy_workqueue(di->fg_wq);
>   free_device_info:
>   	kfree(di);
> +	kfree(di->pdata);
>
>   	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 +2648,7 @@ static struct platform_driver ab8500_fg_driver = {
>   	.driver = {
>   		.name = "ab8500-fg",
>   		.owner = THIS_MODULE,
> +		.of_match_table = ab8500_fg_match,
>   	},
>   };
>
> @@ -2632,7 +2662,7 @@ static void __exit ab8500_fg_exit(void)
>   	platform_driver_unregister(&ab8500_fg_driver);
>   }
>
> -subsys_initcall_sync(ab8500_fg_init);
> +subsys_initcall(ab8500_fg_init);

What does this do?

>   module_exit(ab8500_fg_exit);
>
>   MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
> index 1318ca6..9dbc4d1 100644
> --- a/include/linux/mfd/abx500.h
> +++ b/include/linux/mfd/abx500.h
> @@ -113,13 +113,13 @@ struct ab3100 {
>    * struct ab3100_platform_data
>    * Data supplied to initialize board connections to the AB3100
>    * @reg_constraints: regulator constraints for target board
> - *     the order of these constraints are: LDO A, C, D, E,
> - *     F, G, H, K, EXT and BUCK.
> + *	 the order of these constraints are: LDO A, C, D, E,
> + *	 F, G, H, K, EXT and BUCK.
>    * @reg_initvals: initial values for the regulator registers
> - *     plus two sleep settings for LDO E and the BUCK converter.
> - *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
> - *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
> - *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
> + *	 plus two sleep settings for LDO E and the BUCK converter.
> + *	 exactly AB3100_NUM_REGULATORS+2 values must be sent in.
> + *	 Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
> + *	 BUCK sleep, LDO D. (LDO D need to be initialized last.)
>    * @external_voltage: voltage level of the external regulator.
>    */
>   struct ab3100_platform_data {
> @@ -131,7 +131,7 @@ struct ab3100_platform_data {
>   int ab3100_event_register(struct ab3100 *ab3100,
>   			  struct notifier_block *nb);
>   int ab3100_event_unregister(struct ab3100 *ab3100,
> -			    struct notifier_block *nb);
> +				struct notifier_block *nb);

Was this intentional?

>
>   /**
>    * struct abx500_init_setting
> @@ -387,6 +387,9 @@ struct abx500_bm_data {
>   	const struct abx500_fg_parameters *fg_params;
>   };
>
> +int populate_abx8500_bm_data(struct device *, struct abx500_bm_data *,
> +						struct device_node *);
> +
>   struct abx500_chargalg_platform_data {
>   	char **supplied_to;
>   	size_t num_supplicants;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 2ec1083..61b4ac8 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -183,6 +183,39 @@ extern struct device_node *of_find_matching_node(struct device_node *from,
>   #define for_each_matching_node(dn, matches) \
>   	for (dn = of_find_matching_node(NULL, matches); dn; \
>   	     dn = of_find_matching_node(dn, matches))
> +
> +/*
> + * syntax: for_each_node_by_phandle(np, len, phandle);
> + * @np : pointer to node to start in the list
> + * @len: number of nodes expected
> + * @phandle: current phandle which is obtained through of_get_property(...)
> + *
> + * e.g:
> + *	 node_a: <> {
> + *		...
> + *	 };
> + *	 node_b: <> {
> + *		...
> + *	 };
> + *	 node_c: <> {
> + *		...
> + *	 };
> + *
> + *	 node_x: <> {
> + *		p1 = <v1>;
> + *		p2 = <v2>;
> + *		n_nodes = <3>
> + *		p3 = <&node_a &node_b &node_c ....>;
> + *	 };
> + *
> + * Note:
> + *	 - invoke of_node_put(...) as it uses of_find_node_by_phandle(...)
> + */
> +#define for_each_node_by_phandle(np, len, phandle) \
> +	for (np = of_find_node_by_phandle(be32_to_cpup(phandle));\
> +		(len--);\
> +		np = np->allnext)
> +

Seperate patch. To be submitted first.

>   extern struct device_node *of_find_node_by_path(const char *path);
>   extern struct device_node *of_find_node_by_phandle(phandle handle);
>   extern struct device_node *of_get_parent(const struct device_node *node);

Did this pass checkpatch.pl?

Kind regards,
Lee
"Rajanikanth H.V June 29, 2012, 7:44 p.m. UTC | #2
thanks for your review comments, i will post it on public branch,
how about a review from abx500 bm data structure perspective
ref: arch/arm/mach-ux500/board-mop500-bm.c

Thanks,
Rajanikanth
On 29 June 2012 21:17, Lee Jones <lee.jones@linaro.org> wrote:
> I'm in favour of cutting out the middle-man on this on. I'll do a very quick
> review, then you should just get it up to the LKML and LAKML.
>
> On 29/06/12 13:59, Rajanikanth H.V wrote:
>>
>> From: "Rajanikanth H.V" <rajanikanth.hv@linaro.org>
>>
>>        This patch addes device tree support for
>>        battery temperature and fuel guage driver
>
>
> Spell check.
>
>> Signed-off-by: Rajanikanth H.V <rajanikanth.hv@linaro.org>
>> ---
>>  .../bindings/power_supply/ab8500/ab8500-btemp.txt  |  209 +++++++++++++
>>  .../bindings/power_supply/ab8500/ab8500-fg.txt     |   51 +++
>>  arch/arm/boot/dts/db8500.dtsi                      |  327
>> ++++++++++++++++++++
>>  drivers/mfd/ab8500-core.c                          |   16 +-
>>  drivers/power/ab8500_btemp.c                       |  299
>> +++++++++++++++++-
>>  drivers/power/ab8500_fg.c                          |   58 +++-
>>  include/linux/mfd/abx500.h                         |   17 +-
>>  include/linux/of.h                                 |   33 ++
>>  8 files changed, 966 insertions(+), 44 deletions(-)
>>  create mode 100644
>> Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
>>  create mode 100644
>> Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
>
>
> Consider breaking this down into multiple patches. Remembering to keep them
> orthogonal in case of a future revert.
>
>> diff --git
>> a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
>> b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
>> new file mode 100644
>> index 0000000..9908934
>> --- /dev/null
>> +++
>> b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
>> @@ -0,0 +1,209 @@
>> +* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
>> +
>> +       battery temperature monitor:
>> +
>> +* Required properties:
>> +- compatible: "stericsson,ab8500-btemp"
>> +
>> +* Sub-node:
>> +- ab8500_bm_data:
>> +
>> +example:
>> +   ab8500-btemp {
>> +       compatible = "stericsson,ab8500-btemp";
>> +               ...
>> +               ...
>> +       bat = <&ab8500_bm_data>;
>> +   };
>> +
>> +ab8500_bm_data:
>> +       Contain the battery management/monitor node with the following
>> +       information to support different battery types.
>> +
>> +{
>> +       temp_under                      under this temp, charging is
>> stopped
>> +       temp_low                        between this temp and temp_under
>> charging is reduced
>> +       temp_high                       between this temp and temp_over
>> charging is reduced
>> +       temp_over                       over this temp, charging is
>> stopped
>> +       temp_now                        present battery temperature
>> +       temp_interval_chg       temperature measurement interval in s when
>> charging
>> +       temp_interval_nochg     temperature measurement interval in s when
>> not charging
>> +       main_safety_tmr_h       safety timer for main charger
>> +       usb_safety_tmr_h        safety timer for usb charger
>> +       bkup_bat_v                      voltage which we charge the backup
>> battery with
>> +       bkup_bat_i                      current which we charge the backup
>> battery with
>> +       no_maintenance          indicates that maintenance charging is
>> disabled
>> +       abx500_adc_therm        placement of thermistor, batctrl or
>> battemp adc
>> +       chg_unknown_bat         flag to enable charging of unknown
>> batteries
>> +       enable_overshoot        flag to enable VBAT overshoot control
>> +       auto_trig                       flag to enable auto adc trigger
>> +       fg_res                          resistance of FG resistor in
>> 0.1mOhm
>> +       n_btypes                        number of elements in array
>> bat_type
>> +       batt_id                         index of the identified battery in
>> array bat_type
>> +       interval_charging       charge alg cycle period time when charging
>> (sec)
>> +       interval_not_charging charge alg cycle period time when not
>> charging (sec)
>> +       temp_hysteresis         temperature hysteresis
>> +       gnd_lift_resistance     Battery ground to phone ground resistance
>> (mOhm)
>> +}
>> +e.g:
>> +       ab8500_bm_data: bm_data {
>> +               temp_under               = <3>;
>> +               temp_low                 = <8>;
>> +               temp_high                = <43>;
>> +               temp_over                = <48>;
>> +               temp_now                 = <0>;
>> +               temp_interval_chg   = <20>;
>> +               temp_interval_nochg = <120>;
>> +               main_safety_tmr_h       = <4>;
>> +               usb_safety_tmr_h        = <4>;
>> +               bkup_bat_v              = <1>; /* BUP_VCH_SEL_2P6V */
>> +               bkup_bat_i              = <4>; /* BUP_ICH_SEL_150UA */
>> +               no_maintenance  = <0>;
>> +               chg_unknown_bat = <0>;
>> +               enable_overshoot = <0>;
>> +               auto_trig                = <0>;
>> +               adc_therm                = <0>;
>> +               fg_res                   = <100>;
>> +               batt_id                  = <0>;
>> +               interval_charging         = <5>;
>> +               interval_not_charging = <120>;
>> +               temp_hysteresis           = <3>;
>> +               gnd_lift_resistance   = <34>;
>> +       };
>> +
>> +* subnodes for the node 'ab8500_bm_data':
>> +       - maxi          : maximization parameters
>> +       - cap_levels: capacity in percent for the different capacity
>> levels
>> +       - bat_type      : table of supported battery types
>> +       - chg_params: charger parameters
>> +       - fg_params     : fuel gauge parameters
>> +
>> +example:
>> +ab8500_bm_data: bm_data {
>> +       ...
>> +       ...
>> +       n_btypes        = <3>; /* number of battery types */
>> +       ...
>> +       maxi        = <&ab8500_bm_data_maxim_parameters>;
>> +       cap_levels  = <&ab8500_bm_data_cap_levels>;
>> +       bat_type    = <&ab8500_battery_type_0 &ab8500_battery_type_1
>> &ab8500_battery_type_2>;
>> +       chg_params  = <&ab8500_bm_data_charger_parameters>;
>> +       fg_params   = <&ab8500_bm_data_fuel_guage_parameters>;
>> +
>> +};
>> +
>> +bx500_battery_type:
>> +       prepare battery type information from individual battery
>> specification as:
>> +       {
>> +               name                            : battery technology
>> +               resis_high                      : battery upper resistance
>> limit
>> +               resis_low                       : battery lower resistance
>> limit
>> +               charge_full_design  : Maximum battery capacity in mAh
>> +               nominal_voltage         : Nominal voltage of the battery
>> in mV
>> +               termination_vol         : max voltage upto which battery
>> can be charged
>> +               termination_curr        : battery charging termination
>> current in mA
>> +               recharge_vol            : battery voltage limit that will
>> trigger a new
>> +                                                               full
>> charging cycle in the case where maintenance
>> +                                                               charging
>> has been disabled
>> +               normal_cur_lvl          : charger current in normal state
>> in mA
>> +               normal_vol_lvl          : charger voltage in normal state
>> in mV
>> +               maint_a_cur_lvl         : charger current in maintenance A
>> state in mA
>> +               maint_a_vol_lvl         : charger voltage in maintenance A
>> state in mV
>> +               maint_a_chg_timer_h     : charge time in maintenance A
>> state
>> +               maint_b_cur_lvl         : charger current in maintenance B
>> state in mA
>> +               maint_b_vol_lvl         : charger voltage in maintenance B
>> state in mV
>> +               maint_b_chg_timer_h     : charge time in maintenance B
>> state
>> +               low_high_cur_lvl        : charger current in temp low/high
>> state in mA
>> +               low_high_vol_lvl        : charger voltage in temp low/high
>> state in mV'
>> +               battery_resistance      : battery inner resistance in
>> mOhm.
>> +               n_r_t_tbl_elements      : number of elements in r_to_t_tbl
>> +               r_to_t_tbl                      : table containing
>> resistance to temp points
>> +               n_v_cap_tbl_elements:   number of elements in v_to_cap_tbl
>> +               v_to_cap_tbl            : Voltage to capacity (in %) table
>> +               n_batres_tbl_elements: number of elements in the
>> batres_tbl
>> +               batres_tbl                      : battery internal
>> resistance vs temperature table
>> +       }
>> +
>> +       Note:
>> +               Selected battery shall adhere to the specification
>> provided in:
>> +
>> http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf
>> +
>> +-example:
>> +
>> +    ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
>> +        bat_name             = <3>;
>> +        resis_high           = <53407>;
>> +        resis_low            = <12500>;
>> +        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>;
>> +        battery_resistance   = <300>;
>> +
>> +        n_temp_tbl_elements =     <15>;
>> +
>> +               r_to_t_tbl - defines one point in a temp to res curve. To
>> be used
>> +                       in battery packs that combines the identification
>> resistor
>> +                       with a NTC resistor.
>> +
>> +        r_to_t_tbl = <
>> +                0xfffffffb 53407 /* -5 */
>> +                 0 48594       'battery pack temperature in Celcius' 'NTC
>> resistor net total resistance'
>> +                 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>;
>> +
>> +        n_v_cap_tbl_elements = <20>;
>> +        v_to_cap_tbl = <       /* Table for translating voltage to
>> capacity */
>> +                4171  100      'Voltage in mV' 'Capacity in percent'
>> +                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>;
>> +
>> +        n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
>> +        batres_tbl = < /* defines one point in a temp vs battery internal
>> resistance curve. */
>> +                40 120 'battery pack temperature in Celcius' 'battery
>> internal reistance in mOhm'
>> +                30 135
>> +                20 165
>> +                10 230
>> +                00 325
>> +                0xfffffff6 445 /* -10 */
>> +                0xffffffec 595>; /* -20 */
>> +    };
>> diff --git
>> a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
>> b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
>> new file mode 100644
>> index 0000000..5e84852
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
>> @@ -0,0 +1,51 @@
>> +* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
>> +       fuel guage:
>> +
>> +* Required properties:
>> +- compatible: "stericsson,ab8500-fg"
>> +
>> +* Sub-node:
>> +- ab8500_bm_data:
>> +
>> +example:
>> +   ab8500-btemp {
>> +       compatible = "stericsson,ab8500-fg";
>> +               ...
>> +               ...
>> +       bat = <&ab8500_bm_data>;
>> +   };
>> +
>> +Refer:
>> +
>> Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt for
>> +       information on 'ab8500_bm_data'
>> +
>> +* subnode for the node 'ab8500_bm_data':
>> +       - fg_params     : fuel gauge parameters
>> +
>> +example:
>> +
>> +ab8500_bm_data: bm_data {
>> +       ...
>> +       ...
>> +       ...
>> +       fg_params = <&ab8500_bm_data_fuel_guage_parameters>;
>> +}
>> +
>> +       /* Fuel gauge algorithm parameters, in seconds */
>> +       ab8500_bm_data_fuel_guage_parameters:
>> bm_data_fuel_guage_parameters {
>> +               recovery_sleep_timer   = <10>;  /* Time between
>> measurements while recovering */
>> +               recovery_total_time    = <100>; /* Total recovery time */
>> +               init_timer             = <1>;   /* Measurement interval
>> during startup */
>> +               init_discard_time      = <5>;   /* Time we discard voltage
>> measurement at startup */
>> +               init_total_time        = <40>;  /* Total init time during
>> startup */
>> +               high_curr_time         = <60>;  /* Time current has to be
>> high to go to recovery */
>> +               accu_charging          = <30>;  /* FG accumulation time
>> while charging */
>> +               accu_high_curr         = <30>;  /* FG accumulation time in
>> high current mode */
>> +               high_curr_threshold    = <50>;  /* High current threshold,
>> in mA */
>> +               lowbat_threshold       = <3100>;/* Low battery threshold,
>> in mV */
>> +               battok_falling_th_sel0 = <2860>;/* Over battery threshold,
>> in mV */
>> +               battok_raising_th_sel1 = <2860>;/* Threshold in mV for
>> battOk signal sel0 Resolution in 50 mV step. */
>> +               user_cap_limit         = <15>;  /* Threshold in mV for
>> battOk signal sel1 Resolution in 50 mV step. */
>> +               maint_thres            = <97>;  /* Capacity reported from
>> user must be within this limit to be considered as sane, in percentage
>> points.
>> +       };                                   * This is the threshold where
>> we stop reporting battery full while in maintenance, in per cent
>> +
>
>
> It looks like you've just copy and pasted lots of code into the
> documentation and commented on it, which isn't really documentation at all
> is it? Use the same layout as all the other docs in similar directories.
>
> All vendor specific properties should have the vendor's name perpended e.g.
> stericsson,maint-thres. Also property names should contain '-', not '_'.
>                                                                         */
>>
>> diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
>> index 26f895f..6f3b5df 100644
>> --- a/arch/arm/boot/dts/db8500.dtsi
>> +++ b/arch/arm/boot/dts/db8500.dtsi
>> @@ -330,6 +330,333 @@
>>                                        vddadc-supply =
>> <&ab8500_ldo_tvout_reg>;
>>                                };
>>
>> +                ab8500-fg {
>> +                    compatible = "stericsson,ab8500-fg";
>> +                    interrupts = <24 0x4
>> +                                  8 0x4
>> +                                  28 0x4
>> +                                  27 0x4
>> +                                  26 0x4>;
>> +                    interrupt-names = "NCONV_ACCU",
>> +
>> "BATT_OVV",
>> +
>> "LOW_BAT_F",
>> +
>> "CC_INT_CALIB",
>> +
>> "CCEOC";
>
>
> Formatting (throughout).
>
>> +                    supplied_to = "ab8500_chargalg", "ab8500_usb";
>> +                    num_supplicants = <2>;
>> +                    bat = <&ab8500_bm_data>;
>> +                };
>> +
>> +                ab8500-btemp {
>> +                    compatible = "stericsson,ab8500-btemp";
>> +                    interrupts = <20 0x04
>> +                                  80 0x04
>> +                                  81 0x04
>> +                                  82 0x04
>> +                                  83 0x04>;
>> +                    interrupt-names = "BAT_CTRL_INDB",
>> +
>> "BTEMP_LOW",
>> +
>> "BTEMP_HIGH",
>> +
>> "BTEMP_LOW_MEDIUM",
>> +
>> "BTEMP_MEDIUM_HIGH";
>> +                    supplied_to = "ab8500_chargalg", "ab8500_fg";
>> +                    num_supplicants = <2>;
>> +                    bat = <&ab8500_bm_data>;
>> +                };
>> +
>> +                ab8500_battery_type_0: ab8500_battery_unknown {
>> +                    bat_name            =     <0>;
>> +                    resis_high          =     <0>;
>> +                    resis_low           =     <0>;
>> +                    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>;
>> +                    battery_resistance  =     <300>;
>> +
>> +                    n_temp_tbl_elements =     <15>;
>> +                    r_to_t_tbl = <
>> +                            0xfffffffb 214834 /* -5 */
>> +                            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>;
>> +
>> +                    n_v_cap_tbl_elements = <24>;
>> +                    v_to_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>;
>> +
>> +                    n_batres_tbl_elements = <7>;
>> +                    batres_tbl = <
>> +                            40 120
>> +                            30 135
>> +                            20 165
>> +                            10 230
>> +                            00 325
>> +                            0xfffffff6 445 /* -10 */
>> +                            0xffffffec 595>; /* -20 */
>> +                };
>> +
>> +                ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
>> +                    bat_name             = <3>;
>> +                    resis_high           = <53407>;
>> +                    resis_low            = <12500>;
>> +                    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>;
>> +                    battery_resistance   = <300>;
>> +
>> +                    n_temp_tbl_elements =     <15>;
>> +                    r_to_t_tbl = <
>> +                            0xfffffffb 53407 /* -5 */
>> +                             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>;
>> +
>> +                    n_v_cap_tbl_elements = <20>;
>> +                    v_to_cap_tbl = <
>> +                            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>;
>> +
>> +                    n_batres_tbl_elements = <7>; /*
>> ARRAY_SIZE(batres_tbl), */
>> +                    batres_tbl = <
>> +                            40 120
>> +                            30 135
>> +                            20 165
>> +                            10 230
>> +                            00 325
>> +                            0xfffffff6 445 /* -10 */
>> +                            0xffffffec 595>; /* -20 */
>> +                };
>> +
>> +                ab8500_battery_type_2: ab8500_battery_therm_on_batctrl_1
>> {
>> +                    bat_name            = <3>;
>> +                    resis_high          = <165418>;
>> +                    resis_low           = <82869>;
>> +                    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>;
>> +                    battery_resistance  = <300>;
>> +
>> +                    n_temp_tbl_elements = <15>;
>> +                    r_to_t_tbl = <
>> +                               0xfffffffb  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>;
>> +
>> +                    n_v_cap_tbl_elements = <20>;
>> +                    v_to_cap_tbl = <
>> +                            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>;
>> +
>> +                    n_batres_tbl_elements = <7>; /*
>> ARRAY_SIZE(batres_tbl), */
>> +                    batres_tbl = <
>> +                            40 120
>> +                            30 135
>> +                            20 165
>> +                            10 230
>> +                            00 325
>> +                            0xfffffff6 445 /* -10 */
>> +                            0xffffffec 595>; /* -20 */
>> +                };
>> +
>> +                ab8500_bm_data_cap_levels: bm_data_cap_levels {
>> +                    critical   = <2>;
>> +                    low        = <10>;
>> +                    normal     = <70>;
>> +                    high       = <95>;
>> +                    full       = <100>;
>> +                };
>> +
>> +                ab8500_bm_data_maxim_parameters: bm_data_maxim_parameters
>> {
>> +                    ena_maxi     = <1>;
>> +                    chg_curr     = <910>;
>> +                    wait_cycles = <10>;
>> +                    charger_curr_step = <100>;
>> +                };
>> +
>> +                ab8500_bm_data_charger_parameters:
>> bm_data_charger_parameters {
>> +                    usb_volt_max = <5500>;
>> +                    usb_curr_max = <1500>;
>> +                    ac_volt_max  = <7500>;
>> +                    ac_curr_max  = <1500>;
>> +                };
>> +
>> +                ab8500_bm_data_fuel_guage_parameters:
>> bm_data_fuel_guage_parameters {
>> +                    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>;
>> +                };
>> +
>> +                ab8500_bm_data: bm_data {
>> +                    temp_under            = <3>;
>> +                    temp_low              = <8>;
>> +                    temp_high             = <43>;
>> +                    temp_over             = <48>;
>> +                    temp_now              = <0>;
>> +                    temp_interval_chg     = <20>;
>> +                    temp_interval_nochg   = <120>;
>> +                    main_safety_tmr_h     = <4>;
>> +                    usb_safety_tmr_h      = <4>;
>> +                    bkup_bat_v            = <1>; /* BUP_VCH_SEL_2P6V */
>> +                    bkup_bat_i            = <4>; /* BUP_ICH_SEL_150UA */
>> +                    no_maintenance        = <0>; /*
>> CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
>> +                    chg_unknown_bat       = <0>; /*
>> CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
>> +                    enable_overshoot      = <0>;
>> +                    auto_trig             = <0>;
>> +                    adc_therm             = <0>;
>> +                    fg_res                = <100>;
>> +                    n_btypes              = <3>;
>> +                    batt_id               = <0>;
>> +                    interval_charging     = <5>;
>> +                    interval_not_charging = <120>;
>> +                    temp_hysteresis       = <3>;
>> +                    gnd_lift_resistance   = <34>;
>> +                    maxi                  =
>> <&ab8500_bm_data_maxim_parameters>;
>> +                    cap_levels            = <&ab8500_bm_data_cap_levels>;
>> +                    bat_type              = <&ab8500_battery_type_0
>> &ab8500_battery_type_1 &ab8500_battery_type_2>;
>> +                    chg_params            =
>> <&ab8500_bm_data_charger_parameters>;
>> +                    fg_params             =
>> <&ab8500_bm_data_fuel_guage_parameters>;
>> +                };
>> +
>
>
> It looks like you've just taken values for all of the possible combinations.
> Is this to support different batteries, or different platforms/machines?
>
>>                                ab8500-usb {
>>                                        compatible =
>> "stericsson,ab8500-usb";
>>                                        interrupts = < 90 0x4
>> diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
>> index 6d613e8..837488b 100644
>> --- a/drivers/mfd/ab8500-core.c
>> +++ b/drivers/mfd/ab8500-core.c
>> @@ -1419,15 +1419,15 @@ static int __devinit ab8500_probe(struct
>> platform_device *pdev)
>>                                        ab8500->irq_base);
>>                if (ret)
>>                        goto out_freeirq;
>> -       }
>>
>> -       if (!no_bm) {
>> -               /* Add battery management devices */
>> -               ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
>> -                                     ARRAY_SIZE(ab8500_bm_devs), NULL,
>> -                                     ab8500->irq_base);
>> -               if (ret)
>> -                       dev_err(ab8500->dev, "error adding bm devices\n");
>> +               if (!no_bm) {
>> +                       /* Add battery management devices */
>> +                       ret = mfd_add_devices(ab8500->dev, 0,
>> ab8500_bm_devs,
>> +                               ARRAY_SIZE(ab8500_bm_devs), NULL,
>> +                               ab8500->irq_base);
>> +                       if (ret)
>> +                               dev_err(ab8500->dev, "error adding bm
>> devices\n");
>> +               }
>>        }
>
>
> Can you push you branch somewhere public, so I can get more context please?
>
>>        if (is_ab9540(ab8500))
>> diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
>> index bba3cca..04da929 100644
>> --- a/drivers/power/ab8500_btemp.c
>> +++ b/drivers/power/ab8500_btemp.c
>> @@ -20,6 +20,7 @@
>>  #include <linux/power_supply.h>
>>  #include <linux/completion.h>
>>  #include <linux/workqueue.h>
>> +#include <linux/of.h>
>>  #include <linux/mfd/abx500/ab8500.h>
>>  #include <linux/mfd/abx500.h>
>>  #include <linux/mfd/abx500/ab8500-bm.h>
>> @@ -480,7 +481,7 @@ static int ab8500_btemp_measure_temp(struct
>> ab8500_btemp *di)
>>                vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
>>                if (vntc < 0) {
>>                        dev_err(di->dev,
>> -                               "%s gpadc conversion failed,"
>> +                               "%s gpadc conversion failed, "
>
>
> Unrelated white space change. Was this intentional?
>
>>                                " using previous value\n", __func__);
>>                        return prev;
>>                }
>> @@ -960,15 +961,249 @@ static int __devexit ab8500_btemp_remove(struct
>> platform_device *pdev)
>>        return 0;
>>  }
>>
>> +int populate_abx8500_bm_data(struct device *dev,
>> +               struct abx500_bm_data *bm_data,
>> +               struct device_node *np)
>> +{
>> +       int i, plen, itbl, ret = 0;
>> +       phandle *temp_phandle;
>> +       struct abx500_battery_type *temp_bat_type;
>> +       struct property *pbat_type;
>> +       struct device_node *np_bat;
>> +       const __be32 *p;
>> +       u32 u;
>> +
>> +#define get_bm_data_property(node_p, prop_name)\
>
>
> Whoa! Surely not?
>
> Read Documentation/CodingStyle - Chapter 12.
>
> ... use an inline function instead.
>
>> +       be32_to_cpup(of_get_property(node_p, prop_name, NULL));
>> +
>> +       temp_phandle = (phandle *)of_get_property(np, "bat", NULL);
>> +       BUG_ON(!temp_phandle);
>> +       np_bat = of_find_node_by_phandle(be32_to_cpup(temp_phandle));
>> +       BUG_ON(!np_bat);
>
>
> Why have you killed the kernel here instead of returning an error?
>
>> +       bm_data->temp_under = get_bm_data_property(np_bat, "temp_under");
>> +       bm_data->temp_low = get_bm_data_property(np_bat, "temp_low");
>> +       bm_data->temp_high = get_bm_data_property(np_bat, "temp_high");
>> +       bm_data->temp_over = get_bm_data_property(np_bat, "temp_over");
>> +       bm_data->temp_now = get_bm_data_property(np_bat, "temp_now");
>> +       bm_data->temp_interval_chg =
>> +               get_bm_data_property(np_bat, "temp_interval_chg");
>> +       bm_data->temp_interval_nochg =
>> +                get_bm_data_property(np_bat, "temp_interval_nochg");
>> +       bm_data->main_safety_tmr_h =
>> +                get_bm_data_property(np_bat, "main_safety_tmr_h");
>> +       bm_data->usb_safety_tmr_h =
>> +                get_bm_data_property(np_bat, "usb_safety_tmr_h");
>> +       bm_data->bkup_bat_v =
>> +                get_bm_data_property(np_bat, "bkup_bat_v");
>> +       bm_data->bkup_bat_i =
>> +                get_bm_data_property(np_bat, "bkup_bat_i");
>> +       bm_data->no_maintenance =
>> +                get_bm_data_property(np_bat, "no_maintenance");
>> +       bm_data->chg_unknown_bat =
>> +                get_bm_data_property(np_bat, "chg_unknown_bat");
>> +       bm_data->enable_overshoot =
>> +                get_bm_data_property(np_bat, "enable_overshoot");
>> +       bm_data->auto_trig =
>> +                get_bm_data_property(np_bat, "auto_trig");
>> +       bm_data->adc_therm =
>> +                get_bm_data_property(np_bat, "adc_therm");
>> +       bm_data->fg_res =
>> +                get_bm_data_property(np_bat, "fg_res");
>> +       bm_data->n_btypes =
>> +                get_bm_data_property(np_bat, "n_btypes");
>> +       bm_data->batt_id =
>> +                get_bm_data_property(np_bat, "batt_id");
>> +       bm_data->interval_charging =
>> +                get_bm_data_property(np_bat, "interval_charging");
>> +       bm_data->interval_not_charging =
>> +               get_bm_data_property(np_bat, "interval_not_charging");
>> +       bm_data->temp_hysteresis =
>> +               get_bm_data_property(np_bat, "temp_hysteresis");
>> +       bm_data->gnd_lift_resistance =
>> +               get_bm_data_property(np_bat, "gnd_lift_resistance");
>> +
>> +       temp_phandle = (phandle *)of_get_property(np_bat, "bat_type",
>> &plen);
>
>
> Read Documentation/CodingStyle - Chapter 4.
>
>> +       if (temp_phandle == NULL) {
>> +               dev_warn(dev, "battery type not found\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       plen = plen/sizeof(u32);
>> +
>> +       if (bm_data->n_btypes != plen) {
>> +               dev_crit(dev, "Invalid number of battery types\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       bm_data->bat_type =
>> +               kzalloc(plen * sizeof(struct abx500_battery_type),
>> GFP_KERNEL);
>> +       if (bm_data->bat_type == NULL) {
>> +               dev_crit(dev, "no mem for bm_data->bat_type\n");
>> +               return -ENOMEM;
>> +       }
>> +
>> +       of_node_put(np_bat);
>> +
>> +       /*
>> +        * traverse 'plen' times in 'allnext' for battery types and
>> +        * fillup bm_data->bat_type
>> +        */
>> +       i = 0;
>> +       for_each_node_by_phandle(np_bat, plen, temp_phandle)
>> +       {
>> +               temp_bat_type = (struct abx500_battery_type *)
>> +                               (bm_data->bat_type + i++);
>> +               temp_bat_type->name     =
>> +                get_bm_data_property(np_bat, "bat_name");
>
>
> Random formatting (throughout)
>
>> +               temp_bat_type->resis_high =
>> +                get_bm_data_property(np_bat, "resis_high");
>> +               temp_bat_type->resis_low =
>> +                get_bm_data_property(np_bat, "resis_low");
>> +               temp_bat_type->charge_full_design =
>> +                get_bm_data_property(np_bat, "charge_full_design");
>> +               temp_bat_type->nominal_voltage =
>> +                get_bm_data_property(np_bat, "nominal_voltage");
>> +               temp_bat_type->termination_vol =
>> +                get_bm_data_property(np_bat, "termination_vol");
>> +               temp_bat_type->termination_curr =
>> +                get_bm_data_property(np_bat, "termination_curr");
>> +               temp_bat_type->recharge_vol     =
>> +                get_bm_data_property(np_bat, "recharge_vol");
>> +               temp_bat_type->normal_cur_lvl =
>> +                get_bm_data_property(np_bat, "normal_cur_lvl");
>> +               temp_bat_type->normal_vol_lvl =
>> +                get_bm_data_property(np_bat, "normal_vol_lvl");
>> +               temp_bat_type->maint_a_cur_lvl =
>> +                get_bm_data_property(np_bat, "maint_a_cur_lvl");
>> +               temp_bat_type->maint_a_vol_lvl =
>> +                get_bm_data_property(np_bat, "maint_a_vol_lvl");
>> +               temp_bat_type->maint_a_chg_timer_h =
>> +                get_bm_data_property(np_bat, "maint_a_chg_timer_h");
>> +               temp_bat_type->maint_b_cur_lvl =
>> +                get_bm_data_property(np_bat, "maint_b_cur_lvl");
>> +               temp_bat_type->maint_b_vol_lvl =
>> +                get_bm_data_property(np_bat, "maint_b_vol_lvl");
>> +               temp_bat_type->maint_b_chg_timer_h =
>> +                get_bm_data_property(np_bat, "maint_b_chg_timer_h");
>> +               temp_bat_type->low_high_cur_lvl =
>> +                get_bm_data_property(np_bat, "low_high_cur_lvl");
>> +               temp_bat_type->low_high_vol_lvl =
>> +                get_bm_data_property(np_bat, "low_high_vol_lvl");
>> +               temp_bat_type->battery_resistance =
>> +                get_bm_data_property(np_bat, "battery_resistance");
>> +
>> +               temp_bat_type->n_temp_tbl_elements =
>> +                       get_bm_data_property(np_bat,
>> "n_temp_tbl_elements");
>> +               temp_bat_type->r_to_t_tbl = (struct abx500_res_to_temp *)
>> +                       kzalloc(sizeof(struct abx500_res_to_temp) *
>> +                       temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
>> +               if (temp_bat_type->r_to_t_tbl == NULL) {
>> +                       dev_crit(dev, "no mem for r_to_t_tbl\n");
>> +                       kfree(bm_data->bat_type);
>> +                       return -ENOMEM;
>> +               }
>> +               itbl = 0;
>> +               of_property_for_each_u32(np_bat, "r_to_t_tbl", pbat_type,
>> p, u)
>> +                       *((int *)(temp_bat_type->r_to_t_tbl) + itbl++) =
>> (int)u;
>
>
> Eh!? Does this even compile?
>
> It's also pretty ugly and unreadable.
>
>> +
>> +               temp_bat_type->n_v_cap_tbl_elements =
>> +                       get_bm_data_property(np_bat,
>> "n_v_cap_tbl_elements");
>> +               temp_bat_type->v_to_cap_tbl = (struct abx500_v_to_cap *)
>> +                       kzalloc(sizeof(struct abx500_v_to_cap) *
>> +                       temp_bat_type->n_v_cap_tbl_elements, GFP_KERNEL);
>> +               if (temp_bat_type->v_to_cap_tbl == NULL) {
>> +                       ret = -ENOMEM;
>> +                       dev_crit(dev, "no mem for v_to_cap_tbl\n");
>> +                       goto out_free_mem1;
>> +               }
>> +               itbl = 0;
>> +               of_property_for_each_u32(np_bat,
>> +                       "v_to_cap_tbl", pbat_type, p, u)
>> +                       *((int *)(temp_bat_type->v_to_cap_tbl) + itbl++) =
>> +                               (int)u;
>
>
> And again. Am I missing something?
>
>> +               temp_bat_type->n_batres_tbl_elements =
>> +                       get_bm_data_property(np_bat,
>> "n_batres_tbl_elements");
>> +               temp_bat_type->batres_tbl = (struct batres_vs_temp *)
>
>
> Is this (another other like it) cast nessersary?
>
>> +                       kzalloc(sizeof(struct batres_vs_temp) *
>> +                       temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
>> +               if (temp_bat_type->batres_tbl == NULL) {
>> +                       ret = -ENOMEM;
>> +                       dev_crit(dev, "no mem for batres_tbl\n");
>> +                       goto out_free_mem2;
>> +               }
>> +               itbl = 0;
>> +               of_property_for_each_u32(np_bat, "batres_tbl", pbat_type,
>> p, u)
>> +                       *((int *)(temp_bat_type->batres_tbl) + itbl++) =
>> (int)u;
>> +       }
>> +
>> +       of_node_put(np_bat);
>> +
>> +       bm_data->chg_params = (struct abx500_bm_charger_parameters *)
>> +               kzalloc(sizeof(struct abx500_bm_charger_parameters),
>> +                       GFP_KERNEL);
>> +       if (bm_data->chg_params == NULL) {
>> +               dev_crit(dev, "Failed to alloc memory for chg_params\n");
>> +               ret = -ENOMEM;
>> +               goto out_free_mem3;
>> +       }
>> +       itbl = 0;
>> +       of_property_for_each_u32(np_bat, "chg_params", pbat_type, p, u)
>> +               *((int *)(bm_data->chg_params) + itbl++) = (int)u;
>> +
>> +       bm_data->fg_params = (struct abx500_fg_parameters *)
>> +               kzalloc(sizeof(struct abx500_fg_parameters), GFP_KERNEL);
>> +       if (bm_data->fg_params == NULL) {
>> +               dev_crit(dev, "Failed to alloc memory for fg_params\n");
>> +               ret = -ENOMEM;
>> +               goto out_free_mem4;
>> +       }
>> +       itbl = 0;
>> +       of_property_for_each_u32(np_bat, "fg_params", pbat_type, p, u)
>> +               *((int *)(bm_data->fg_params) + itbl++) = (int)u;
>
>
> There seems like an awful lot of code duplication going on here.
>>
>> +
>> +       return ret;
>> +
>> +out_free_mem1:
>> +       kfree(bm_data->bat_type);
>> +       kfree(temp_bat_type->r_to_t_tbl);
>> +       return ret;
>> +
>> +out_free_mem2:
>> +       kfree(bm_data->bat_type);
>> +       kfree(temp_bat_type->r_to_t_tbl);
>> +       kfree(temp_bat_type->v_to_cap_tbl);
>> +       return ret;
>> +
>> +out_free_mem3:
>> +       kfree(bm_data->bat_type);
>> +       kfree(temp_bat_type->r_to_t_tbl);
>> +       kfree(temp_bat_type->v_to_cap_tbl);
>> +       kfree(temp_bat_type->batres_tbl);
>> +       return ret;
>> +
>> +out_free_mem4:
>> +       kfree(bm_data->bat_type);
>> +       kfree(temp_bat_type->r_to_t_tbl);
>> +       kfree(temp_bat_type->v_to_cap_tbl);
>> +       kfree(temp_bat_type->batres_tbl);
>> +       kfree(bm_data->chg_params);
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(populate_abx8500_bm_data);
>> +
>>  static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
>>  {
>>        int irq, i, ret = 0;
>>        u8 val;
>> -       struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
>> +       struct device_node *np = pdev->dev.of_node;
>
>
> No, it's meant to work with _both_ platform and Device Tree registation.
>
>>        struct ab8500_btemp *di;
>> +       const unsigned int *btemp_p_val;
>> +       const char *pvalue = NULL;
>
>
> value is not a good variable name.
>
>> -       if (!plat_data) {
>> -               dev_err(&pdev->dev, "No platform data\n");
>> +       if (!np) {
>> +               dev_err(&pdev->dev, "No platform data or DT found\n");
>
>
> How do you know there is no platform data found? You haven't even looked.
>
>>                return -EINVAL;
>>        }
>>
>> @@ -982,20 +1217,46 @@ 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;
>> -       if (!di->pdata) {
>> -               dev_err(di->dev, "no btemp platform data supplied\n");
>> -               ret = -EINVAL;
>> -               goto free_device_info;
>> +       btemp_p_val = of_get_property(np, "num_supplicants", NULL);
>> +       BUG_ON(!btemp_p_val);
>
>
> DEAD!
>
>> +       di->pdata =
>> +               kzalloc(sizeof(struct abx500_btemp_platform_data),
>> GFP_KERNEL);
>> +       if (di->pdata == NULL) {
>> +               kfree(di);
>> +               return -ENOMEM;
>>        }
>>
>> -       /* get battery specific platform data */
>> -       di->bat = plat_data->battery;
>> +       di->pdata->num_supplicants = be32_to_cpup(btemp_p_val);
>> +       di->pdata->supplied_to =
>> +               kzalloc(di->pdata->num_supplicants *
>> +                       sizeof(const char *), GFP_KERNEL);
>> +       if (di->pdata->supplied_to == NULL) {
>> +               kfree(di);
>> +               kfree(di->pdata);
>> +               return -ENOMEM;
>> +       }
>> +
>> +       for (val = 0; val < di->pdata->num_supplicants; ++val)
>> +               if (of_property_read_string_index
>> +                       (np, "supplied_to", val, &pvalue) == 0)
>> +                       *(di->pdata->supplied_to + val) = (char *)pvalue;
>> +               else {
>> +                       dev_warn(di->dev, "insufficient number of
>> supplied_to data found\n");
>> +                       goto free_device_info;
>> +               }
>> +       dev_dbg(di->dev, "getting DT battery information\n");
>> +       di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
>>        if (!di->bat) {
>> -               dev_err(di->dev, "no battery platform data supplied\n");
>> -               ret = -EINVAL;
>> +               kfree(di);
>> +               kfree(di->pdata);
>> +               return -ENOMEM;
>> +       }
>> +       if (populate_abx8500_bm_data(di->dev, di->bat, np) < 0) {
>> +               dev_warn(di->dev, "Failed to bind DT\n");
>>                goto free_device_info;
>>        }
>> +       dev_dbg(di->dev, "getting DT battery information...done\n");
>>
>>        /* BTEMP supply */
>>        di->btemp_psy.name = "ab8500_btemp";
>> @@ -1008,7 +1269,6 @@ static int __devinit ab8500_btemp_probe(struct
>> platform_device *pdev)
>>        di->btemp_psy.external_power_changed =
>>                ab8500_btemp_external_power_changed;
>>
>> -
>
>
> Unrelated whitespace change.
>
>>        /* Create a work queue for the btemp */
>>        di->btemp_wq =
>>                create_singlethread_workqueue("ab8500_btemp_wq");
>> @@ -1016,7 +1276,6 @@ static int __devinit ab8500_btemp_probe(struct
>> platform_device *pdev)
>>                dev_err(di->dev, "failed to create work queue\n");
>>                goto free_device_info;
>>        }
>> -
>
>
> And again.
>
>>        /* Init work for measuring temperature periodically */
>>        INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work,
>>                ab8500_btemp_periodic_work);
>> @@ -1090,14 +1349,23 @@ free_irq:
>>                irq = platform_get_irq_byname(pdev,
>> ab8500_btemp_irq[i].name);
>>                free_irq(irq, di);
>>        }
>> +
>
>
> .
>
>>  free_btemp_wq:
>>        destroy_workqueue(di->btemp_wq);
>> +
>
>
> .
>
>>  free_device_info:
>>        kfree(di);
>> +       kfree(di->pdata);
>> +       kfree(di->bat);
>>
>>        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),
>> @@ -1106,6 +1374,7 @@ static struct platform_driver ab8500_btemp_driver =
>> {
>>        .driver = {
>>                .name = "ab8500-btemp",
>>                .owner = THIS_MODULE,
>> +               .of_match_table = ab8500_btemp_match,
>>        },
>>  };
>>
>> diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
>> index bf02225..1d0e32a 100644
>> --- a/drivers/power/ab8500_fg.c
>> +++ b/drivers/power/ab8500_fg.c
>> @@ -31,6 +31,7 @@
>>  #include <linux/mfd/abx500.h>
>>  #include <linux/time.h>
>>  #include <linux/completion.h>
>> +#include <linux/of.h>
>>
>>  #define MILLI_TO_MICRO                        1000
>>  #define FG_LSB_IN_MA                  1627
>> @@ -2446,11 +2447,12 @@ static int __devinit ab8500_fg_probe(struct
>> platform_device *pdev)
>>  {
>>        int i, irq;
>>        int ret = 0;
>> -       struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
>
>
> As above.
>
>> +       const char *fg_p_val;
>> +       struct device_node *np = pdev->dev.of_node;
>>        struct ab8500_fg *di;
>>
>> -       if (!plat_data) {
>> -               dev_err(&pdev->dev, "No platform data\n");
>> +       if (!np) {
>> +               dev_err(&pdev->dev, "No DT node for platform data
>> available\n");
>>                return -EINVAL;
>>        }
>>
>> @@ -2464,20 +2466,42 @@ static int __devinit ab8500_fg_probe(struct
>> platform_device *pdev)
>>        di->dev = &pdev->dev;
>>        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;
>> +       di->pdata =
>> +               kzalloc(sizeof(struct abx500_btemp_platform_data),
>> GFP_KERNEL);
>> +       if (di->pdata == NULL) {
>> +               kfree(di);
>> +               return -ENOMEM;
>> +       }
>> +       di->pdata->num_supplicants =
>> +               be32_to_cpup(of_get_property(np, "num_supplicants",
>> NULL));
>> +       di->pdata->supplied_to =
>> +               kzalloc(di->pdata->num_supplicants *
>> +                       sizeof(const char *), GFP_KERNEL);
>> +       if (di->pdata->supplied_to == NULL) {
>> +               kfree(di);
>> +               kfree(di->pdata);
>> +               return -ENOMEM;
>>        }
>>
>> +       for (i = 0; i < di->pdata->num_supplicants; ++i)
>> +               if (of_property_read_string_index
>> +                       (np, "supplied_to", i, &fg_p_val) == 0)
>> +                       *(di->pdata->supplied_to + i) = (char *)fg_p_val;
>> +               else {
>> +                               dev_warn(di->dev, "insufficient number of
>> supplied_to data found\n");
>> +                               goto free_device_info;
>> +                       }
>> +
>>        /* get battery specific platform data */
>> -       di->bat = plat_data->battery;
>> +       di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
>>        if (!di->bat) {
>> -               dev_err(di->dev, "no battery platform data supplied\n");
>> -               ret = -EINVAL;
>> +               kfree(di);
>> +               kfree(di->pdata);
>> +               return -ENOMEM;
>> +       }
>> +       ret = populate_abx8500_bm_data(di->dev, di->bat, np);
>> +       if (ret < 0) {
>> +               dev_warn(di->dev, "Failed to bind DT\n");
>>                goto free_device_info;
>>        }
>>
>> @@ -2607,10 +2631,15 @@ free_inst_curr_wq:
>>        destroy_workqueue(di->fg_wq);
>>  free_device_info:
>>        kfree(di);
>> +       kfree(di->pdata);
>>
>>        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 +2648,7 @@ static struct platform_driver ab8500_fg_driver = {
>>        .driver = {
>>                .name = "ab8500-fg",
>>                .owner = THIS_MODULE,
>> +               .of_match_table = ab8500_fg_match,
>>        },
>>  };
>>
>> @@ -2632,7 +2662,7 @@ static void __exit ab8500_fg_exit(void)
>>        platform_driver_unregister(&ab8500_fg_driver);
>>  }
>>
>> -subsys_initcall_sync(ab8500_fg_init);
>> +subsys_initcall(ab8500_fg_init);
>
>
> What does this do?
>
>>  module_exit(ab8500_fg_exit);
>>
>>  MODULE_LICENSE("GPL v2");
>> diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
>> index 1318ca6..9dbc4d1 100644
>> --- a/include/linux/mfd/abx500.h
>> +++ b/include/linux/mfd/abx500.h
>> @@ -113,13 +113,13 @@ struct ab3100 {
>>   * struct ab3100_platform_data
>>   * Data supplied to initialize board connections to the AB3100
>>   * @reg_constraints: regulator constraints for target board
>> - *     the order of these constraints are: LDO A, C, D, E,
>> - *     F, G, H, K, EXT and BUCK.
>> + *      the order of these constraints are: LDO A, C, D, E,
>> + *      F, G, H, K, EXT and BUCK.
>>   * @reg_initvals: initial values for the regulator registers
>> - *     plus two sleep settings for LDO E and the BUCK converter.
>> - *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
>> - *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
>> - *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
>> + *      plus two sleep settings for LDO E and the BUCK converter.
>> + *      exactly AB3100_NUM_REGULATORS+2 values must be sent in.
>> + *      Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
>> + *      BUCK sleep, LDO D. (LDO D need to be initialized last.)
>>   * @external_voltage: voltage level of the external regulator.
>>   */
>>  struct ab3100_platform_data {
>> @@ -131,7 +131,7 @@ struct ab3100_platform_data {
>>  int ab3100_event_register(struct ab3100 *ab3100,
>>                          struct notifier_block *nb);
>>  int ab3100_event_unregister(struct ab3100 *ab3100,
>> -                           struct notifier_block *nb);
>> +                               struct notifier_block *nb);
>
>
> Was this intentional?
>
>>
>>  /**
>>   * struct abx500_init_setting
>> @@ -387,6 +387,9 @@ struct abx500_bm_data {
>>        const struct abx500_fg_parameters *fg_params;
>>  };
>>
>> +int populate_abx8500_bm_data(struct device *, struct abx500_bm_data *,
>> +                                               struct device_node *);
>> +
>>  struct abx500_chargalg_platform_data {
>>        char **supplied_to;
>>        size_t num_supplicants;
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index 2ec1083..61b4ac8 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -183,6 +183,39 @@ extern struct device_node
>> *of_find_matching_node(struct device_node *from,
>>  #define for_each_matching_node(dn, matches) \
>>        for (dn = of_find_matching_node(NULL, matches); dn; \
>>             dn = of_find_matching_node(dn, matches))
>> +
>> +/*
>> + * syntax: for_each_node_by_phandle(np, len, phandle);
>> + * @np : pointer to node to start in the list
>> + * @len: number of nodes expected
>> + * @phandle: current phandle which is obtained through
>> of_get_property(...)
>> + *
>> + * e.g:
>> + *      node_a: <> {
>> + *             ...
>> + *      };
>> + *      node_b: <> {
>> + *             ...
>> + *      };
>> + *      node_c: <> {
>> + *             ...
>> + *      };
>> + *
>> + *      node_x: <> {
>> + *             p1 = <v1>;
>> + *             p2 = <v2>;
>> + *             n_nodes = <3>
>> + *             p3 = <&node_a &node_b &node_c ....>;
>> + *      };
>> + *
>> + * Note:
>> + *      - invoke of_node_put(...) as it uses of_find_node_by_phandle(...)
>> + */
>> +#define for_each_node_by_phandle(np, len, phandle) \
>> +       for (np = of_find_node_by_phandle(be32_to_cpup(phandle));\
>> +               (len--);\
>> +               np = np->allnext)
>> +
>
>
> Seperate patch. To be submitted first.
>
>>  extern struct device_node *of_find_node_by_path(const char *path);
>>  extern struct device_node *of_find_node_by_phandle(phandle handle);
>>  extern struct device_node *of_get_parent(const struct device_node *node);
>
>
> Did this pass checkpatch.pl?
>
> Kind regards,
> Lee
>
> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> M: +44 77 88 633 515
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
>
>
Lee Jones July 2, 2012, 9 a.m. UTC | #3
On 29/06/12 20:44, Rajanikanth HV wrote:
> thanks for your review comments, i will post it on public branch,
> how about a review from abx500 bm data structure perspective
> ref: arch/arm/mach-ux500/board-mop500-bm.c

I already did:

>> It looks like you've just taken values for all of the possible combinations.
>> Is this to support different batteries, or different platforms/machines?

The values you put into the Device Tree should be Snowball specific, but 
it looks like you've loaded it up with _everything_. You need to make 
sure that all of the information you put in makes sense when booting the 
Snowball board. Any values which will never be used need to be extracted.

Kind regards,
Lee
"Rajanikanth H.V July 2, 2012, 9:49 a.m. UTC | #4
In order to accommodate allowable Batteries with in the ab8500 parameters
limit battery type information got bloated. (Ref: board-mop500-bm.c)

Recommended battery for snowball is: 3.7v 2600ma
     Ref: http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf

However, i currently i am using "SonyEricsson BST41", 3.6v. 1500mAh, 5.4w


Thanks,
Rajanikanth



On 2 July 2012 14:30, Lee Jones <lee.jones@linaro.org> wrote:
> On 29/06/12 20:44, Rajanikanth HV wrote:
>>
>> thanks for your review comments, i will post it on public branch,
>> how about a review from abx500 bm data structure perspective
>> ref: arch/arm/mach-ux500/board-mop500-bm.c
>
>
> I already did:
>
>
>>> It looks like you've just taken values for all of the possible
>>> combinations.
>>> Is this to support different batteries, or different platforms/machines?
>
>
> The values you put into the Device Tree should be Snowball specific, but it
> looks like you've loaded it up with _everything_. You need to make sure that
> all of the information you put in makes sense when booting the Snowball
> board. Any values which will never be used need to be extracted.
>
>
> Kind regards,
> Lee
>
> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> M: +44 77 88 633 515
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
>
>
Lee Jones July 2, 2012, 10:25 a.m. UTC | #5
On 02/07/12 10:49, Rajanikanth HV wrote:
> In order to accommodate allowable Batteries with in the ab8500 parameters
> limit battery type information got bloated. (Ref: board-mop500-bm.c)

Then maybe we should move the settings from platform data and into the 
driver itself? I'm not keen on the way it looks now.

Arnd, do you have an opinion?

> Recommended battery for snowball is: 3.7v 2600ma
>       Ref: http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf
>
> However, i currently i am using "SonyEricsson BST41", 3.6v. 1500mAh, 5.4w
>
>
> Thanks,
> Rajanikanth
>
>
>
> On 2 July 2012 14:30, Lee Jones <lee.jones@linaro.org> wrote:
>> On 29/06/12 20:44, Rajanikanth HV wrote:
>>>
>>> thanks for your review comments, i will post it on public branch,
>>> how about a review from abx500 bm data structure perspective
>>> ref: arch/arm/mach-ux500/board-mop500-bm.c
>>
>>
>> I already did:
>>
>>
>>>> It looks like you've just taken values for all of the possible
>>>> combinations.
>>>> Is this to support different batteries, or different platforms/machines?
>>
>>
>> The values you put into the Device Tree should be Snowball specific, but it
>> looks like you've loaded it up with _everything_. You need to make sure that
>> all of the information you put in makes sense when booting the Snowball
>> board. Any values which will never be used need to be extracted.
>>
>>
>> Kind regards,
>> Lee
>>
>> --
>> Lee Jones
>> Linaro ST-Ericsson Landing Team Lead
>> M: +44 77 88 633 515
>> Linaro.org │ Open source software for ARM SoCs
>> Follow Linaro: Facebook | Twitter | Blog
>>
>>
"Rajanikanth H.V July 2, 2012, 10:38 a.m. UTC | #6
how will you accommodate new battery types information then?

Thanks,
Rajanikanth


On 2 July 2012 15:55, Lee Jones <lee.jones@linaro.org> wrote:
> On 02/07/12 10:49, Rajanikanth HV wrote:
>>
>> In order to accommodate allowable Batteries with in the ab8500 parameters
>> limit battery type information got bloated. (Ref: board-mop500-bm.c)
>
>
> Then maybe we should move the settings from platform data and into the
> driver itself? I'm not keen on the way it looks now.
>
> Arnd, do you have an opinion?
>
>
>> Recommended battery for snowball is: 3.7v 2600ma
>>       Ref:
>> http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf
>>
>> However, i currently i am using "SonyEricsson BST41", 3.6v. 1500mAh, 5.4w
>>
>>
>> Thanks,
>> Rajanikanth
>>
>>
>>
>> On 2 July 2012 14:30, Lee Jones <lee.jones@linaro.org> wrote:
>>>
>>> On 29/06/12 20:44, Rajanikanth HV wrote:
>>>>
>>>>
>>>> thanks for your review comments, i will post it on public branch,
>>>> how about a review from abx500 bm data structure perspective
>>>> ref: arch/arm/mach-ux500/board-mop500-bm.c
>>>
>>>
>>>
>>> I already did:
>>>
>>>
>>>>> It looks like you've just taken values for all of the possible
>>>>> combinations.
>>>>> Is this to support different batteries, or different
>>>>> platforms/machines?
>>>
>>>
>>>
>>> The values you put into the Device Tree should be Snowball specific, but
>>> it
>>> looks like you've loaded it up with _everything_. You need to make sure
>>> that
>>> all of the information you put in makes sense when booting the Snowball
>>> board. Any values which will never be used need to be extracted.
>>>
>>>
>>> Kind regards,
>>> Lee
>>>
>>> --
>>> Lee Jones
>>> Linaro ST-Ericsson Landing Team Lead
>>> M: +44 77 88 633 515
>>> Linaro.org │ Open source software for ARM SoCs
>>> Follow Linaro: Facebook | Twitter | Blog
>>>
>>>
>
>
> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> M: +44 77 88 633 515
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
>
>
Lee Jones July 2, 2012, 12:46 p.m. UTC | #7
On 02/07/12 11:38, Rajanikanth HV wrote:
> how will you accommodate new battery types information then?

Add them to the driver too?

 From what I can see, the structs in board-mop500-bm.c are more of a 
capability thing than saying "this is what we have".

Please correct my snap-judgment if I'm incorrect.
Arnd Bergmann July 2, 2012, 3:12 p.m. UTC | #8
On Monday 02 July 2012, Lee Jones wrote:
> On 02/07/12 11:38, Rajanikanth HV wrote:
> > how will you accommodate new battery types information then?
> 
> Add them to the driver too?
> 
>  From what I can see, the structs in board-mop500-bm.c are more of a 
> capability thing than saying "this is what we have".
> 
> Please correct my snap-judgment if I'm incorrect.

My first reaction to this would have been to put it all into the
device tree, but I agree that the amount of data is a bit excessive.

Looking at the Sony xperia sola source code, it seems that the same
data is used for *all* boards, and nothing in it looks board specific,
so putting it all into the driver itself sounds like the easiest solution.
We can always add some form of abstraction if we later need something more
complex.

The version I'm looking at uses a compile-time configuration symbol
"CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL". This has to get removed
and turned into a run-time option.

The regulator names in the platform data look should probably be taken
from the device tree.

	Arnd
dsaxena-linaro2 July 2, 2012, 10:14 p.m. UTC | #9
On 29 June 2012 12:44, Rajanikanth HV <rajanikanth.hv@linaro.org> wrote:
> thanks for your review comments, i will post it on public branch,

Posting on a public branch once you have your git issues sorted is
good, but we want the patches themselves posted on the relevant email
lists. Please make the cleanups suggested and repost directly for
upstream review and Lee and Arnd can directly comment on those lists.
Rease Documentation/SubmittingPatches if you have not done so yet.

Thanks,
~Deepak
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
new file mode 100644
index 0000000..9908934
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt
@@ -0,0 +1,209 @@ 
+* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
+
+	battery temperature monitor:
+
+* Required properties:
+- compatible: "stericsson,ab8500-btemp"
+
+* Sub-node:
+- ab8500_bm_data:
+
+example:
+   ab8500-btemp {
+       compatible = "stericsson,ab8500-btemp";
+		...
+		...
+       bat = <&ab8500_bm_data>;
+   };
+
+ab8500_bm_data:
+	Contain the battery management/monitor node with the following
+	information to support different battery types.
+
+{
+	temp_under			under this temp, charging is stopped
+	temp_low			between this temp and temp_under charging is reduced
+	temp_high			between this temp and temp_over charging is reduced
+	temp_over			over this temp, charging is stopped
+	temp_now			present battery temperature
+	temp_interval_chg	temperature measurement interval in s when charging
+	temp_interval_nochg	temperature measurement interval in s when not charging
+	main_safety_tmr_h	safety timer for main charger
+	usb_safety_tmr_h	safety timer for usb charger
+	bkup_bat_v			voltage which we charge the backup battery with
+	bkup_bat_i			current which we charge the backup battery with
+	no_maintenance		indicates that maintenance charging is disabled
+	abx500_adc_therm	placement of thermistor, batctrl or battemp adc
+	chg_unknown_bat		flag to enable charging of unknown batteries
+	enable_overshoot	flag to enable VBAT overshoot control
+	auto_trig			flag to enable auto adc trigger
+	fg_res				resistance of FG resistor in 0.1mOhm
+	n_btypes			number of elements in array bat_type
+	batt_id				index of the identified battery in array bat_type
+	interval_charging	charge alg cycle period time when charging (sec)
+	interval_not_charging charge alg cycle period time when not charging (sec)
+	temp_hysteresis		temperature hysteresis
+	gnd_lift_resistance	Battery ground to phone ground resistance (mOhm)
+}
+e.g:
+	ab8500_bm_data: bm_data {
+		temp_under		 = <3>;
+		temp_low		 = <8>;
+		temp_high		 = <43>;
+		temp_over		 = <48>;
+		temp_now		 = <0>;
+		temp_interval_chg   = <20>;
+		temp_interval_nochg = <120>;
+		main_safety_tmr_h	= <4>;
+		usb_safety_tmr_h	= <4>;
+		bkup_bat_v		= <1>; /* BUP_VCH_SEL_2P6V */
+		bkup_bat_i		= <4>; /* BUP_ICH_SEL_150UA */
+		no_maintenance	= <0>;
+		chg_unknown_bat	= <0>;
+		enable_overshoot = <0>;
+		auto_trig		 = <0>;
+		adc_therm		 = <0>;
+		fg_res			 = <100>;
+		batt_id		   	 = <0>;
+		interval_charging	  = <5>;
+		interval_not_charging = <120>;
+		temp_hysteresis	   	  = <3>;
+		gnd_lift_resistance   = <34>;
+	};
+
+* subnodes for the node 'ab8500_bm_data':
+	- maxi		: maximization parameters
+	- cap_levels: capacity in percent for the different capacity levels
+	- bat_type	: table of supported battery types
+	- chg_params: charger parameters
+	- fg_params	: fuel gauge parameters
+
+example:
+ab8500_bm_data: bm_data {
+	...
+	...
+	n_btypes	= <3>; /* number of battery types */
+	...
+	maxi        = <&ab8500_bm_data_maxim_parameters>;
+	cap_levels  = <&ab8500_bm_data_cap_levels>;
+	bat_type    = <&ab8500_battery_type_0 &ab8500_battery_type_1 &ab8500_battery_type_2>;
+	chg_params  = <&ab8500_bm_data_charger_parameters>;
+	fg_params   = <&ab8500_bm_data_fuel_guage_parameters>;
+
+};
+
+bx500_battery_type:
+	prepare battery type information from individual battery specification as:
+	{
+		name				: battery technology
+		resis_high			: battery upper resistance limit
+		resis_low			: battery lower resistance limit
+		charge_full_design  : Maximum battery capacity in mAh
+		nominal_voltage		: Nominal voltage of the battery in mV
+		termination_vol		: max voltage upto which battery can be charged
+		termination_curr	: battery charging termination current in mA
+		recharge_vol		: battery voltage limit that will trigger a new
+								full charging cycle in the case where maintenance
+								charging has been disabled
+		normal_cur_lvl		: charger current in normal state in mA
+		normal_vol_lvl		: charger voltage in normal state in mV
+		maint_a_cur_lvl		: charger current in maintenance A state in mA
+		maint_a_vol_lvl		: charger voltage in maintenance A state in mV
+		maint_a_chg_timer_h	: charge time in maintenance A state
+		maint_b_cur_lvl		: charger current in maintenance B state in mA
+		maint_b_vol_lvl		: charger voltage in maintenance B state in mV
+		maint_b_chg_timer_h	: charge time in maintenance B state
+		low_high_cur_lvl	: charger current in temp low/high state in mA
+		low_high_vol_lvl	: charger voltage in temp low/high state in mV'
+		battery_resistance	: battery inner resistance in mOhm.
+		n_r_t_tbl_elements 	: number of elements in r_to_t_tbl
+		r_to_t_tbl			: table containing resistance to temp points
+		n_v_cap_tbl_elements:	number of elements in v_to_cap_tbl
+		v_to_cap_tbl		: Voltage to capacity (in %) table
+		n_batres_tbl_elements: number of elements in the batres_tbl
+		batres_tbl			: battery internal resistance vs temperature table
+	}
+
+	Note:
+		Selected battery shall adhere to the specification provided in:
+		http://www.giga-concept.fr/media/uploads/products/documents/2008/09/9100.pdf
+
+-example:
+
+    ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
+        bat_name             = <3>;
+        resis_high           = <53407>;
+        resis_low            = <12500>;
+        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>;
+        battery_resistance   = <300>;
+
+        n_temp_tbl_elements =     <15>;
+
+		r_to_t_tbl - defines one point in a temp to res curve. To be used
+			in battery packs that combines the identification resistor
+			with a NTC resistor.
+
+        r_to_t_tbl = <
+                0xfffffffb 53407 /* -5 */
+                 0 48594	'battery pack temperature in Celcius' 'NTC resistor net total resistance'
+                 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>;
+
+        n_v_cap_tbl_elements = <20>;
+        v_to_cap_tbl = <	/* Table for translating voltage to capacity */
+                4171  100	'Voltage in mV'	'Capacity in percent'
+                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>;
+
+        n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
+        batres_tbl = <	/* defines one point in a temp vs battery internal resistance curve. */
+                40 120	'battery pack temperature in Celcius' 'battery internal reistance in mOhm'
+                30 135
+                20 165
+                10 230
+                00 325
+                0xfffffff6 445 /* -10 */
+                0xffffffec 595>; /* -20 */
+    };
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
new file mode 100644
index 0000000..5e84852
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/ab8500-fg.txt
@@ -0,0 +1,51 @@ 
+* St-Ericsson AB8500 Power Management Integrated Circuit (PMIC)
+	fuel guage:
+
+* Required properties:
+- compatible: "stericsson,ab8500-fg"
+
+* Sub-node:
+- ab8500_bm_data:
+
+example:
+   ab8500-btemp {
+       compatible = "stericsson,ab8500-fg";
+		...
+		...
+       bat = <&ab8500_bm_data>;
+   };
+
+Refer:
+	Documentation/devicetree/bindings/power_supply/ab8500/ab8500-btemp.txt for
+	information on 'ab8500_bm_data'
+
+* subnode for the node 'ab8500_bm_data':
+	- fg_params	: fuel gauge parameters
+
+example:
+
+ab8500_bm_data: bm_data {
+	...
+	...
+	...
+	fg_params = <&ab8500_bm_data_fuel_guage_parameters>;
+}
+
+	/* Fuel gauge algorithm parameters, in seconds */
+	ab8500_bm_data_fuel_guage_parameters: bm_data_fuel_guage_parameters {
+		recovery_sleep_timer   = <10>;	/* Time between measurements while recovering */
+		recovery_total_time    = <100>; /* Total recovery time */
+		init_timer             = <1>;   /* Measurement interval during startup */
+		init_discard_time      = <5>;   /* Time we discard voltage measurement at startup */
+		init_total_time        = <40>;  /* Total init time during startup */
+		high_curr_time         = <60>;  /* Time current has to be high to go to recovery */
+		accu_charging          = <30>;  /* FG accumulation time while charging */
+		accu_high_curr         = <30>;  /* FG accumulation time in high current mode */
+		high_curr_threshold    = <50>;  /* High current threshold, in mA */
+		lowbat_threshold       = <3100>;/* Low battery threshold, in mV */
+		battok_falling_th_sel0 = <2860>;/* Over battery threshold, in mV */
+		battok_raising_th_sel1 = <2860>;/* Threshold in mV for battOk signal sel0 Resolution in 50 mV step. */
+		user_cap_limit         = <15>;  /* Threshold in mV for battOk signal sel1 Resolution in 50 mV step. */
+		maint_thres            = <97>;  /* Capacity reported from user must be within this limit to be considered as sane, in percentage points.
+	};                                   * This is the threshold where we stop reporting battery full while in maintenance, in per cent 
+										 */
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
index 26f895f..6f3b5df 100644
--- a/arch/arm/boot/dts/db8500.dtsi
+++ b/arch/arm/boot/dts/db8500.dtsi
@@ -330,6 +330,333 @@ 
 					vddadc-supply = <&ab8500_ldo_tvout_reg>;
 				};
 
+                ab8500-fg {
+                    compatible = "stericsson,ab8500-fg";
+                    interrupts = <24 0x4
+                                  8 0x4
+                                  28 0x4
+                                  27 0x4
+                                  26 0x4>;
+                    interrupt-names = "NCONV_ACCU",
+									  "BATT_OVV",
+									  "LOW_BAT_F",
+									  "CC_INT_CALIB",
+									  "CCEOC";
+                    supplied_to = "ab8500_chargalg", "ab8500_usb";
+                    num_supplicants = <2>;
+                    bat = <&ab8500_bm_data>;
+                };
+
+                ab8500-btemp {
+                    compatible = "stericsson,ab8500-btemp";
+                    interrupts = <20 0x04
+                                  80 0x04
+                                  81 0x04
+                                  82 0x04
+                                  83 0x04>;
+                    interrupt-names = "BAT_CTRL_INDB",
+									  "BTEMP_LOW",
+									  "BTEMP_HIGH",
+									  "BTEMP_LOW_MEDIUM",
+									  "BTEMP_MEDIUM_HIGH";
+                    supplied_to = "ab8500_chargalg", "ab8500_fg";
+                    num_supplicants = <2>;
+                    bat = <&ab8500_bm_data>;
+                };
+
+                ab8500_battery_type_0: ab8500_battery_unknown {
+                    bat_name            =     <0>;
+                    resis_high          =     <0>;
+                    resis_low           =     <0>;
+                    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>;
+                    battery_resistance  =     <300>;
+
+                    n_temp_tbl_elements =     <15>;
+                    r_to_t_tbl = <
+                            0xfffffffb 214834 /* -5 */
+                            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>;
+
+                    n_v_cap_tbl_elements = <24>;
+                    v_to_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>;
+
+                    n_batres_tbl_elements = <7>;
+                    batres_tbl = <
+                            40 120
+                            30 135
+                            20 165
+                            10 230
+                            00 325
+                            0xfffffff6 445 /* -10 */
+                            0xffffffec 595>; /* -20 */
+                };
+
+                ab8500_battery_type_1: ab8500_battery_therm_on_batctrl {
+                    bat_name             = <3>;
+                    resis_high           = <53407>;
+                    resis_low            = <12500>;
+                    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>;
+                    battery_resistance   = <300>;
+
+                    n_temp_tbl_elements =     <15>;
+                    r_to_t_tbl = <
+                            0xfffffffb 53407 /* -5 */
+                             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>;
+
+                    n_v_cap_tbl_elements = <20>;
+                    v_to_cap_tbl = <
+                            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>;
+
+                    n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
+                    batres_tbl = <
+                            40 120
+                            30 135
+                            20 165
+                            10 230
+                            00 325
+                            0xfffffff6 445 /* -10 */
+                            0xffffffec 595>; /* -20 */
+                };
+
+                ab8500_battery_type_2: ab8500_battery_therm_on_batctrl_1 {
+                    bat_name            = <3>;
+                    resis_high          = <165418>;
+                    resis_low           = <82869>;
+                    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>;
+                    battery_resistance  = <300>;
+
+                    n_temp_tbl_elements = <15>;
+                    r_to_t_tbl = <
+                               0xfffffffb  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>;
+
+                    n_v_cap_tbl_elements = <20>;
+                    v_to_cap_tbl = <
+                            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>;
+
+                    n_batres_tbl_elements = <7>; /* ARRAY_SIZE(batres_tbl), */
+                    batres_tbl = <
+                            40 120
+                            30 135
+                            20 165
+                            10 230
+                            00 325
+                            0xfffffff6 445 /* -10 */
+                            0xffffffec 595>; /* -20 */
+                };
+
+                ab8500_bm_data_cap_levels: bm_data_cap_levels {
+                    critical   = <2>;
+                    low        = <10>;
+                    normal     = <70>;
+                    high       = <95>;
+                    full       = <100>;
+                };
+
+                ab8500_bm_data_maxim_parameters: bm_data_maxim_parameters {
+                    ena_maxi     = <1>;
+                    chg_curr     = <910>;
+                    wait_cycles = <10>;
+                    charger_curr_step = <100>;
+                };
+
+                ab8500_bm_data_charger_parameters: bm_data_charger_parameters {
+                    usb_volt_max = <5500>;
+                    usb_curr_max = <1500>;
+                    ac_volt_max  = <7500>;
+                    ac_curr_max  = <1500>;
+                };
+
+                ab8500_bm_data_fuel_guage_parameters: bm_data_fuel_guage_parameters {
+                    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>;
+                };
+
+                ab8500_bm_data: bm_data {
+                    temp_under            = <3>;
+                    temp_low              = <8>;
+                    temp_high             = <43>;
+                    temp_over             = <48>;
+                    temp_now              = <0>;
+                    temp_interval_chg     = <20>;
+                    temp_interval_nochg   = <120>;
+                    main_safety_tmr_h     = <4>;
+                    usb_safety_tmr_h      = <4>;
+                    bkup_bat_v            = <1>; /* BUP_VCH_SEL_2P6V */
+                    bkup_bat_i            = <4>; /* BUP_ICH_SEL_150UA */
+                    no_maintenance        = <0>; /* CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
+                    chg_unknown_bat       = <0>; /* CONFIG_AB8500_9100_LI_ION_BATTERY not considered */
+                    enable_overshoot      = <0>;
+                    auto_trig             = <0>;
+                    adc_therm             = <0>;
+                    fg_res                = <100>;
+                    n_btypes              = <3>;
+                    batt_id               = <0>;
+                    interval_charging     = <5>;
+                    interval_not_charging = <120>;
+                    temp_hysteresis       = <3>;
+                    gnd_lift_resistance   = <34>;
+                    maxi                  = <&ab8500_bm_data_maxim_parameters>;
+                    cap_levels            = <&ab8500_bm_data_cap_levels>;
+                    bat_type              = <&ab8500_battery_type_0 &ab8500_battery_type_1 &ab8500_battery_type_2>;
+                    chg_params            = <&ab8500_bm_data_charger_parameters>;
+                    fg_params             = <&ab8500_bm_data_fuel_guage_parameters>;
+                };
+
 				ab8500-usb {
 					compatible = "stericsson,ab8500-usb";
 					interrupts = < 90 0x4
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 6d613e8..837488b 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1419,15 +1419,15 @@  static int __devinit ab8500_probe(struct platform_device *pdev)
 					ab8500->irq_base);
 		if (ret)
 			goto out_freeirq;
-	}
 
-	if (!no_bm) {
-		/* Add battery management devices */
-		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
-				      ARRAY_SIZE(ab8500_bm_devs), NULL,
-				      ab8500->irq_base);
-		if (ret)
-			dev_err(ab8500->dev, "error adding bm devices\n");
+		if (!no_bm) {
+			/* Add battery management devices */
+			ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
+				ARRAY_SIZE(ab8500_bm_devs), NULL,
+				ab8500->irq_base);
+			if (ret)
+				dev_err(ab8500->dev, "error adding bm devices\n");
+		}
 	}
 
 	if (is_ab9540(ab8500))
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index bba3cca..04da929 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -20,6 +20,7 @@ 
 #include <linux/power_supply.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
@@ -480,7 +481,7 @@  static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
 		vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
 		if (vntc < 0) {
 			dev_err(di->dev,
-				"%s gpadc conversion failed,"
+				"%s gpadc conversion failed, "
 				" using previous value\n", __func__);
 			return prev;
 		}
@@ -960,15 +961,249 @@  static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
 	return 0;
 }
 
+int populate_abx8500_bm_data(struct device *dev,
+		struct abx500_bm_data *bm_data,
+		struct device_node *np)
+{
+	int i, plen, itbl, ret = 0;
+	phandle *temp_phandle;
+	struct abx500_battery_type *temp_bat_type;
+	struct property *pbat_type;
+	struct device_node *np_bat;
+	const __be32 *p;
+	u32 u;
+
+#define get_bm_data_property(node_p, prop_name)\
+	be32_to_cpup(of_get_property(node_p, prop_name, NULL));
+
+	temp_phandle = (phandle *)of_get_property(np, "bat", NULL);
+	BUG_ON(!temp_phandle);
+	np_bat = of_find_node_by_phandle(be32_to_cpup(temp_phandle));
+	BUG_ON(!np_bat);
+
+	bm_data->temp_under = get_bm_data_property(np_bat, "temp_under");
+	bm_data->temp_low = get_bm_data_property(np_bat, "temp_low");
+	bm_data->temp_high = get_bm_data_property(np_bat, "temp_high");
+	bm_data->temp_over = get_bm_data_property(np_bat, "temp_over");
+	bm_data->temp_now = get_bm_data_property(np_bat, "temp_now");
+	bm_data->temp_interval_chg =
+		get_bm_data_property(np_bat, "temp_interval_chg");
+	bm_data->temp_interval_nochg =
+		 get_bm_data_property(np_bat, "temp_interval_nochg");
+	bm_data->main_safety_tmr_h =
+		 get_bm_data_property(np_bat, "main_safety_tmr_h");
+	bm_data->usb_safety_tmr_h =
+		 get_bm_data_property(np_bat, "usb_safety_tmr_h");
+	bm_data->bkup_bat_v =
+		 get_bm_data_property(np_bat, "bkup_bat_v");
+	bm_data->bkup_bat_i =
+		 get_bm_data_property(np_bat, "bkup_bat_i");
+	bm_data->no_maintenance =
+		 get_bm_data_property(np_bat, "no_maintenance");
+	bm_data->chg_unknown_bat =
+		 get_bm_data_property(np_bat, "chg_unknown_bat");
+	bm_data->enable_overshoot =
+		 get_bm_data_property(np_bat, "enable_overshoot");
+	bm_data->auto_trig =
+		 get_bm_data_property(np_bat, "auto_trig");
+	bm_data->adc_therm =
+		 get_bm_data_property(np_bat, "adc_therm");
+	bm_data->fg_res =
+		 get_bm_data_property(np_bat, "fg_res");
+	bm_data->n_btypes =
+		 get_bm_data_property(np_bat, "n_btypes");
+	bm_data->batt_id =
+		 get_bm_data_property(np_bat, "batt_id");
+	bm_data->interval_charging =
+		 get_bm_data_property(np_bat, "interval_charging");
+	bm_data->interval_not_charging =
+		get_bm_data_property(np_bat, "interval_not_charging");
+	bm_data->temp_hysteresis =
+		get_bm_data_property(np_bat, "temp_hysteresis");
+	bm_data->gnd_lift_resistance =
+		get_bm_data_property(np_bat, "gnd_lift_resistance");
+
+	temp_phandle = (phandle *)of_get_property(np_bat, "bat_type", &plen);
+	if (temp_phandle == NULL) {
+		dev_warn(dev, "battery type not found\n");
+		return -EINVAL;
+	}
+
+	plen = plen/sizeof(u32);
+
+	if (bm_data->n_btypes != plen) {
+		dev_crit(dev, "Invalid number of battery types\n");
+		return -EINVAL;
+	}
+
+	bm_data->bat_type =
+		kzalloc(plen * sizeof(struct abx500_battery_type), GFP_KERNEL);
+	if (bm_data->bat_type == NULL) {
+		dev_crit(dev, "no mem for bm_data->bat_type\n");
+		return -ENOMEM;
+	}
+
+	of_node_put(np_bat);
+
+	/*
+	 * traverse 'plen' times in 'allnext' for battery types and
+	 * fillup bm_data->bat_type
+	 */
+	i = 0;
+	for_each_node_by_phandle(np_bat, plen, temp_phandle)
+	{
+		temp_bat_type = (struct abx500_battery_type *)
+				(bm_data->bat_type + i++);
+		temp_bat_type->name	=
+		 get_bm_data_property(np_bat, "bat_name");
+		temp_bat_type->resis_high =
+		 get_bm_data_property(np_bat, "resis_high");
+		temp_bat_type->resis_low =
+		 get_bm_data_property(np_bat, "resis_low");
+		temp_bat_type->charge_full_design =
+		 get_bm_data_property(np_bat, "charge_full_design");
+		temp_bat_type->nominal_voltage =
+		 get_bm_data_property(np_bat, "nominal_voltage");
+		temp_bat_type->termination_vol =
+		 get_bm_data_property(np_bat, "termination_vol");
+		temp_bat_type->termination_curr =
+		 get_bm_data_property(np_bat, "termination_curr");
+		temp_bat_type->recharge_vol	=
+		 get_bm_data_property(np_bat, "recharge_vol");
+		temp_bat_type->normal_cur_lvl =
+		 get_bm_data_property(np_bat, "normal_cur_lvl");
+		temp_bat_type->normal_vol_lvl =
+		 get_bm_data_property(np_bat, "normal_vol_lvl");
+		temp_bat_type->maint_a_cur_lvl =
+		 get_bm_data_property(np_bat, "maint_a_cur_lvl");
+		temp_bat_type->maint_a_vol_lvl =
+		 get_bm_data_property(np_bat, "maint_a_vol_lvl");
+		temp_bat_type->maint_a_chg_timer_h =
+		 get_bm_data_property(np_bat, "maint_a_chg_timer_h");
+		temp_bat_type->maint_b_cur_lvl =
+		 get_bm_data_property(np_bat, "maint_b_cur_lvl");
+		temp_bat_type->maint_b_vol_lvl =
+		 get_bm_data_property(np_bat, "maint_b_vol_lvl");
+		temp_bat_type->maint_b_chg_timer_h =
+		 get_bm_data_property(np_bat, "maint_b_chg_timer_h");
+		temp_bat_type->low_high_cur_lvl =
+		 get_bm_data_property(np_bat, "low_high_cur_lvl");
+		temp_bat_type->low_high_vol_lvl =
+		 get_bm_data_property(np_bat, "low_high_vol_lvl");
+		temp_bat_type->battery_resistance =
+		 get_bm_data_property(np_bat, "battery_resistance");
+
+		temp_bat_type->n_temp_tbl_elements =
+			get_bm_data_property(np_bat, "n_temp_tbl_elements");
+		temp_bat_type->r_to_t_tbl = (struct abx500_res_to_temp *)
+			kzalloc(sizeof(struct abx500_res_to_temp) *
+			temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
+		if (temp_bat_type->r_to_t_tbl == NULL) {
+			dev_crit(dev, "no mem for r_to_t_tbl\n");
+			kfree(bm_data->bat_type);
+			return -ENOMEM;
+		}
+		itbl = 0;
+		of_property_for_each_u32(np_bat, "r_to_t_tbl", pbat_type, p, u)
+			*((int *)(temp_bat_type->r_to_t_tbl) + itbl++) = (int)u;
+
+		temp_bat_type->n_v_cap_tbl_elements =
+			get_bm_data_property(np_bat, "n_v_cap_tbl_elements");
+		temp_bat_type->v_to_cap_tbl = (struct abx500_v_to_cap *)
+			kzalloc(sizeof(struct abx500_v_to_cap) *
+			temp_bat_type->n_v_cap_tbl_elements, GFP_KERNEL);
+		if (temp_bat_type->v_to_cap_tbl == NULL) {
+			ret = -ENOMEM;
+			dev_crit(dev, "no mem for v_to_cap_tbl\n");
+			goto out_free_mem1;
+		}
+		itbl = 0;
+		of_property_for_each_u32(np_bat,
+			"v_to_cap_tbl", pbat_type, p, u)
+			*((int *)(temp_bat_type->v_to_cap_tbl) + itbl++) =
+				(int)u;
+
+		temp_bat_type->n_batres_tbl_elements =
+			get_bm_data_property(np_bat, "n_batres_tbl_elements");
+		temp_bat_type->batres_tbl = (struct batres_vs_temp *)
+			kzalloc(sizeof(struct batres_vs_temp) *
+			temp_bat_type->n_temp_tbl_elements, GFP_KERNEL);
+		if (temp_bat_type->batres_tbl == NULL) {
+			ret = -ENOMEM;
+			dev_crit(dev, "no mem for batres_tbl\n");
+			goto out_free_mem2;
+		}
+		itbl = 0;
+		of_property_for_each_u32(np_bat, "batres_tbl", pbat_type, p, u)
+			*((int *)(temp_bat_type->batres_tbl) + itbl++) = (int)u;
+	}
+
+	of_node_put(np_bat);
+
+	bm_data->chg_params = (struct abx500_bm_charger_parameters *)
+		kzalloc(sizeof(struct abx500_bm_charger_parameters),
+			GFP_KERNEL);
+	if (bm_data->chg_params == NULL) {
+		dev_crit(dev, "Failed to alloc memory for chg_params\n");
+		ret = -ENOMEM;
+		goto out_free_mem3;
+	}
+	itbl = 0;
+	of_property_for_each_u32(np_bat, "chg_params", pbat_type, p, u)
+		*((int *)(bm_data->chg_params) + itbl++) = (int)u;
+
+	bm_data->fg_params = (struct abx500_fg_parameters *)
+		kzalloc(sizeof(struct abx500_fg_parameters), GFP_KERNEL);
+	if (bm_data->fg_params == NULL) {
+		dev_crit(dev, "Failed to alloc memory for fg_params\n");
+		ret = -ENOMEM;
+		goto out_free_mem4;
+	}
+	itbl = 0;
+	of_property_for_each_u32(np_bat, "fg_params", pbat_type, p, u)
+		*((int *)(bm_data->fg_params) + itbl++) = (int)u;
+
+	return ret;
+
+out_free_mem1:
+	kfree(bm_data->bat_type);
+	kfree(temp_bat_type->r_to_t_tbl);
+	return ret;
+
+out_free_mem2:
+	kfree(bm_data->bat_type);
+	kfree(temp_bat_type->r_to_t_tbl);
+	kfree(temp_bat_type->v_to_cap_tbl);
+	return ret;
+
+out_free_mem3:
+	kfree(bm_data->bat_type);
+	kfree(temp_bat_type->r_to_t_tbl);
+	kfree(temp_bat_type->v_to_cap_tbl);
+	kfree(temp_bat_type->batres_tbl);
+	return ret;
+
+out_free_mem4:
+	kfree(bm_data->bat_type);
+	kfree(temp_bat_type->r_to_t_tbl);
+	kfree(temp_bat_type->v_to_cap_tbl);
+	kfree(temp_bat_type->batres_tbl);
+	kfree(bm_data->chg_params);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(populate_abx8500_bm_data);
+
 static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
 {
 	int irq, i, ret = 0;
 	u8 val;
-	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
 	struct ab8500_btemp *di;
+	const unsigned int *btemp_p_val;
+	const char *pvalue = NULL;
 
-	if (!plat_data) {
-		dev_err(&pdev->dev, "No platform data\n");
+	if (!np) {
+		dev_err(&pdev->dev, "No platform data or DT found\n");
 		return -EINVAL;
 	}
 
@@ -982,20 +1217,46 @@  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;
-	if (!di->pdata) {
-		dev_err(di->dev, "no btemp platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
+	btemp_p_val = of_get_property(np, "num_supplicants", NULL);
+	BUG_ON(!btemp_p_val);
+
+	di->pdata =
+		kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL);
+	if (di->pdata == NULL) {
+		kfree(di);
+		return -ENOMEM;
 	}
 
-	/* get battery specific platform data */
-	di->bat = plat_data->battery;
+	di->pdata->num_supplicants = be32_to_cpup(btemp_p_val);
+	di->pdata->supplied_to =
+		kzalloc(di->pdata->num_supplicants *
+			sizeof(const char *), GFP_KERNEL);
+	if (di->pdata->supplied_to == NULL) {
+		kfree(di);
+		kfree(di->pdata);
+		return -ENOMEM;
+	}
+
+	for (val = 0; val < di->pdata->num_supplicants; ++val)
+		if (of_property_read_string_index
+			(np, "supplied_to", val, &pvalue) == 0)
+			*(di->pdata->supplied_to + val) = (char *)pvalue;
+		else {
+			dev_warn(di->dev, "insufficient number of supplied_to data found\n");
+			goto free_device_info;
+		}
+	dev_dbg(di->dev, "getting DT battery information\n");
+	di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
 	if (!di->bat) {
-		dev_err(di->dev, "no battery platform data supplied\n");
-		ret = -EINVAL;
+		kfree(di);
+		kfree(di->pdata);
+		return -ENOMEM;
+	}
+	if (populate_abx8500_bm_data(di->dev, di->bat, np) < 0) {
+		dev_warn(di->dev, "Failed to bind DT\n");
 		goto free_device_info;
 	}
+	dev_dbg(di->dev, "getting DT battery information...done\n");
 
 	/* BTEMP supply */
 	di->btemp_psy.name = "ab8500_btemp";
@@ -1008,7 +1269,6 @@  static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
 	di->btemp_psy.external_power_changed =
 		ab8500_btemp_external_power_changed;
 
-
 	/* Create a work queue for the btemp */
 	di->btemp_wq =
 		create_singlethread_workqueue("ab8500_btemp_wq");
@@ -1016,7 +1276,6 @@  static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
 		dev_err(di->dev, "failed to create work queue\n");
 		goto free_device_info;
 	}
-
 	/* Init work for measuring temperature periodically */
 	INIT_DELAYED_WORK_DEFERRABLE(&di->btemp_periodic_work,
 		ab8500_btemp_periodic_work);
@@ -1090,14 +1349,23 @@  free_irq:
 		irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
 		free_irq(irq, di);
 	}
+
 free_btemp_wq:
 	destroy_workqueue(di->btemp_wq);
+
 free_device_info:
 	kfree(di);
+	kfree(di->pdata);
+	kfree(di->bat);
 
 	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),
@@ -1106,6 +1374,7 @@  static struct platform_driver ab8500_btemp_driver = {
 	.driver = {
 		.name = "ab8500-btemp",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_btemp_match,
 	},
 };
 
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index bf02225..1d0e32a 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -31,6 +31,7 @@ 
 #include <linux/mfd/abx500.h>
 #include <linux/time.h>
 #include <linux/completion.h>
+#include <linux/of.h>
 
 #define MILLI_TO_MICRO			1000
 #define FG_LSB_IN_MA			1627
@@ -2446,11 +2447,12 @@  static int __devinit ab8500_fg_probe(struct platform_device *pdev)
 {
 	int i, irq;
 	int ret = 0;
-	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+	const char *fg_p_val;
+	struct device_node *np = pdev->dev.of_node;
 	struct ab8500_fg *di;
 
-	if (!plat_data) {
-		dev_err(&pdev->dev, "No platform data\n");
+	if (!np) {
+		dev_err(&pdev->dev, "No DT node for platform data available\n");
 		return -EINVAL;
 	}
 
@@ -2464,20 +2466,42 @@  static int __devinit ab8500_fg_probe(struct platform_device *pdev)
 	di->dev = &pdev->dev;
 	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;
+	di->pdata =
+		kzalloc(sizeof(struct abx500_btemp_platform_data), GFP_KERNEL);
+	if (di->pdata == NULL) {
+		kfree(di);
+		return -ENOMEM;
+	}
+	di->pdata->num_supplicants =
+		be32_to_cpup(of_get_property(np, "num_supplicants", NULL));
+	di->pdata->supplied_to =
+		kzalloc(di->pdata->num_supplicants *
+			sizeof(const char *), GFP_KERNEL);
+	if (di->pdata->supplied_to == NULL) {
+		kfree(di);
+		kfree(di->pdata);
+		return -ENOMEM;
 	}
 
+	for (i = 0; i < di->pdata->num_supplicants; ++i)
+		if (of_property_read_string_index
+			(np, "supplied_to", i, &fg_p_val) == 0)
+			*(di->pdata->supplied_to + i) = (char *)fg_p_val;
+		else {
+				dev_warn(di->dev, "insufficient number of supplied_to data found\n");
+				goto free_device_info;
+			}
+
 	/* get battery specific platform data */
-	di->bat = plat_data->battery;
+	di->bat = kzalloc(sizeof(struct abx500_bm_data), GFP_KERNEL);
 	if (!di->bat) {
-		dev_err(di->dev, "no battery platform data supplied\n");
-		ret = -EINVAL;
+		kfree(di);
+		kfree(di->pdata);
+		return -ENOMEM;
+	}
+	ret = populate_abx8500_bm_data(di->dev, di->bat, np);
+	if (ret < 0) {
+		dev_warn(di->dev, "Failed to bind DT\n");
 		goto free_device_info;
 	}
 
@@ -2607,10 +2631,15 @@  free_inst_curr_wq:
 	destroy_workqueue(di->fg_wq);
 free_device_info:
 	kfree(di);
+	kfree(di->pdata);
 
 	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 +2648,7 @@  static struct platform_driver ab8500_fg_driver = {
 	.driver = {
 		.name = "ab8500-fg",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_fg_match,
 	},
 };
 
@@ -2632,7 +2662,7 @@  static void __exit ab8500_fg_exit(void)
 	platform_driver_unregister(&ab8500_fg_driver);
 }
 
-subsys_initcall_sync(ab8500_fg_init);
+subsys_initcall(ab8500_fg_init);
 module_exit(ab8500_fg_exit);
 
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 1318ca6..9dbc4d1 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -113,13 +113,13 @@  struct ab3100 {
  * struct ab3100_platform_data
  * Data supplied to initialize board connections to the AB3100
  * @reg_constraints: regulator constraints for target board
- *     the order of these constraints are: LDO A, C, D, E,
- *     F, G, H, K, EXT and BUCK.
+ *	 the order of these constraints are: LDO A, C, D, E,
+ *	 F, G, H, K, EXT and BUCK.
  * @reg_initvals: initial values for the regulator registers
- *     plus two sleep settings for LDO E and the BUCK converter.
- *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
- *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
- *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
+ *	 plus two sleep settings for LDO E and the BUCK converter.
+ *	 exactly AB3100_NUM_REGULATORS+2 values must be sent in.
+ *	 Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
+ *	 BUCK sleep, LDO D. (LDO D need to be initialized last.)
  * @external_voltage: voltage level of the external regulator.
  */
 struct ab3100_platform_data {
@@ -131,7 +131,7 @@  struct ab3100_platform_data {
 int ab3100_event_register(struct ab3100 *ab3100,
 			  struct notifier_block *nb);
 int ab3100_event_unregister(struct ab3100 *ab3100,
-			    struct notifier_block *nb);
+				struct notifier_block *nb);
 
 /**
  * struct abx500_init_setting
@@ -387,6 +387,9 @@  struct abx500_bm_data {
 	const struct abx500_fg_parameters *fg_params;
 };
 
+int populate_abx8500_bm_data(struct device *, struct abx500_bm_data *,
+						struct device_node *);
+
 struct abx500_chargalg_platform_data {
 	char **supplied_to;
 	size_t num_supplicants;
diff --git a/include/linux/of.h b/include/linux/of.h
index 2ec1083..61b4ac8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -183,6 +183,39 @@  extern struct device_node *of_find_matching_node(struct device_node *from,
 #define for_each_matching_node(dn, matches) \
 	for (dn = of_find_matching_node(NULL, matches); dn; \
 	     dn = of_find_matching_node(dn, matches))
+
+/*
+ * syntax: for_each_node_by_phandle(np, len, phandle);
+ * @np : pointer to node to start in the list
+ * @len: number of nodes expected
+ * @phandle: current phandle which is obtained through of_get_property(...)
+ *
+ * e.g:
+ *	 node_a: <> {
+ *		...
+ *	 };
+ *	 node_b: <> {
+ *		...
+ *	 };
+ *	 node_c: <> {
+ *		...
+ *	 };
+ *
+ *	 node_x: <> {
+ *		p1 = <v1>;
+ *		p2 = <v2>;
+ *		n_nodes = <3>
+ *		p3 = <&node_a &node_b &node_c ....>;
+ *	 };
+ *
+ * Note:
+ *	 - invoke of_node_put(...) as it uses of_find_node_by_phandle(...)
+ */
+#define for_each_node_by_phandle(np, len, phandle) \
+	for (np = of_find_node_by_phandle(be32_to_cpup(phandle));\
+		(len--);\
+		np = np->allnext)
+
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);