From: "Rajanikanth H.V" <rajanikanth...@stericsson.com>

This patch adds device tree support for
fuel guage driver

Signed-off-by: Rajanikanth H.V <rajanikanth...@stericsson.com>
---
 Documentation/devicetree/bindings/mfd/ab8500.txt   |    8 +-
 .../devicetree/bindings/power_supply/ab8500/fg.txt |   86 ++++
 arch/arm/boot/dts/dbx5x0.dtsi                      |   22 +-
 drivers/mfd/ab8500-core.c                          |    1 +
 drivers/power/Makefile                             |    2 +-
 drivers/power/ab8500_bmdata.c                      |  454 ++++++++++++++++++++
 drivers/power/ab8500_fg.c                          |  169 +++++++-
 include/linux/mfd/abx500.h                         |    7 +-
 include/linux/mfd/abx500/ab8500-bm.h               |    7 +
 9 files changed, 731 insertions(+), 25 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
 create mode 100644 drivers/power/ab8500_bmdata.c

diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt 
b/Documentation/devicetree/bindings/mfd/ab8500.txt
index ce83c8d..762dc11 100644
--- a/Documentation/devicetree/bindings/mfd/ab8500.txt
+++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
@@ -24,7 +24,13 @@ ab8500-bm                :                      :            
  : Battery Manager
 ab8500-btemp             :                      :              : Battery 
Temperature
 ab8500-charger           :                      :              : Battery 
Charger
 ab8500-codec             :                      :              : Audio Codec
-ab8500-fg                :                      :              : Fuel Gauge
+ab8500-fg                :                     : vddadc       : Fuel Gauge
+                        : NCONV_ACCU           :              : Accumulate N 
Sample Conversion
+                        : BATT_OVV             :              : Battery Over 
Voltage
+                        : LOW_BAT_F            :              : LOW threshold 
battery voltage
+                        : CC_INT_CALIB         :              : Counter 
Counter Internal Calibration
+                        : CCEOC                :              : Coulomb 
Counter End of Conversion
+                        :                      :              :
 ab8500-gpadc             : HW_CONV_END          : vddadc       : Analogue to 
Digital Converter
                            SW_CONV_END          :              :
 ab8500-gpio              :                      :              : GPIO 
Controller
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt 
b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
new file mode 100644
index 0000000..c576558
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,86 @@
+=== AB8500 Fuel Gauge Driver ===
+
+AB8500 is a mixed signal multimedia and power management
+device comprising: power and energy-management-module,
+wall-charger, usb-charger, audio codec, general purpose adc,
+tvout, clock management and sim card interface.
+
+Fuel-guage support is part of energy-management-module, the other
+components of this module are:
+main-charger, usb-combo-charger and Battery temperature monitoring.
+
+The properties below describes the node for fuel guage driver.
+
+Required Properties:
+- compatible = "stericsson,ab8500-fg"
+- interface-name:
+       Name of the controller/driver which is part of energy-management-module
+- supplied-to:
+       This property shall have dependent nodes which represent other
+       energy-management-module.
+       This is a logical binding w.r.t power supply events
+       across energy-management-module drivers where-in, the
+       runtime battery properties are shared along with uevent
+       notification.
+       ref: di->fg.external_power_changed =
+               ab8500_fg_external_power_changed;
+               ab8500_fg.c
+
+       Need for this property:
+               energy-management-module driver updates power-supply properties
+               which are subset of events listed in 'enum 
power_supply_property',
+               ref: power_supply.h file
+               Event handler invokes power supply change notifier
+               which in-turn invokes registered power supply class call-back
+               based on the 'supplied-to' string.
+               ref:
+               power_supply_changed_work(..) 
./drivers/power/power_supply_core.c
+               di->fg_psy.external_power_changed
+
+       example:
+       ab8500-fg {
+               /* Other enery management module */
+               supplied-to  = <&ab8500_chargalg &ab8500_usb>;
+       };
+
+       ab8500_battery_info: ab8500_bat_type {
+               battery-type = <2>;
+               thermistor-on-batctrl = <1>;
+       };
+
+Other dependent node for fuel-gauge is:
+       ab8500_battery_info: ab8500_bat_type {
+       };
+       This node will provide information on 'thermistor interface' and
+       'battery technology type' used.
+
+Properties of this node are:
+thermistor-on-batctrl:
+       A boolean value indicating thermistor interface to battery
+
+       Note:
+       'btemp' and 'batctrl' are the pins interfaced for battery temperature
+       measurement, 'btemp' signal is used when NTC(negative temperature
+       coefficient) resister is interfaced external to battery whereas
+       'batctrl' pin is used when NTC resister is internal to battery.
+
+       e.g:
+       ab8500_battery_info: ab8500_bat_type {
+               thermistor-on-batctrl;
+       };
+       indiactes: NTC resister is internal to battery, 'batctrl' is used
+               for thermal measurement.
+
+       The absence of property 'thermal-on-batctrl' indicates
+       NTC resister is external to battery and  'btemp' signal is used
+       for thermal measurement.
+
+battery-type:
+       This shall be the battery manufacturing technology type,
+       allowed types are:
+               "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
+       e.g:
+       ab8500_battery_info: ab8500_bat_type {
+               battery-name = "LION";
+       }
+
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 748ba7a..22f38b8 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -352,8 +352,28 @@
                                        vddadc-supply = <&ab8500_ldo_tvout_reg>;
                                };
 
-                               ab8500-usb {
+                               ab8500_battery_info: ab8500_bat_type {
+                                       battery-name = "LION";
+                                       thermistor-on-batctrl;
+                               };
+
+                               ab8500_chargalg: ab8500_chalg {
+                                       compatible     = 
"stericsson,ab8500-chargalg";
+                                       interface-name = "ab8500_chargalg";
+                                       battery-info   = <&ab8500_battery_info>;
+                                       supplied-to    = <&ab8500_fuel_guage>;
+                               };
+
+                               ab8500_fuel_guage: ab8500_fg {
+                                       compatible     = "stericsson,ab8500-fg";
+                                       interface-name = "ab8500_fg";
+                                       battery-info   = <&ab8500_battery_info>;
+                                       supplied-to    = <&ab8500_chargalg 
&ab8500_usb>;
+                               };
+
+                               ab8500_usb: ab8500_usb_if {
                                        compatible = "stericsson,ab8500-usb";
+                                       interface-name = "ab8500_usb";
                                        interrupts = < 90 0x4
                                                       96 0x4
                                                       14 0x4
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77..6c3d7c2 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1051,6 +1051,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
        },
        {
                .name = "ab8500-fg",
+               .of_compatible = "stericsson,ab8500-fg",
                .num_resources = ARRAY_SIZE(ab8500_fg_resources),
                .resources = ab8500_fg_resources,
        },
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee58afb..2c58d4e 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)   += jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)        += intel_mid_battery.o
-obj-$(CONFIG_AB8500_BM)                += ab8500_charger.o ab8500_btemp.o 
ab8500_fg.o abx500_chargalg.o
+obj-$(CONFIG_AB8500_BM)                += ab8500_bmdata.o ab8500_charger.o 
ab8500_fg.o ab8500_btemp.o abx500_chargalg.o
 obj-$(CONFIG_CHARGER_ISP1704)  += isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)  += max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
new file mode 100644
index 0000000..1333650
--- /dev/null
+++ b/drivers/power/ab8500_bmdata.c
@@ -0,0 +1,454 @@
+#include <linux/export.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+
+/*
+ * These are the defined batteries that uses a NTC and ID resistor placed
+ * inside of the battery pack.
+ * Note that the res_to_temp table must be strictly sorted by falling 
resistance
+ * values to work.
+ */
+static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
+       {-5, 53407},
+       { 0, 48594},
+       { 5, 43804},
+       {10, 39188},
+       {15, 34870},
+       {20, 30933},
+       {25, 27422},
+       {30, 24347},
+       {35, 21694},
+       {40, 19431},
+       {45, 17517},
+       {50, 15908},
+       {55, 14561},
+       {60, 13437},
+       {65, 12500},
+};
+static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
+       {-5, 165418},
+       { 0, 159024},
+       { 5, 151921},
+       {10, 144300},
+       {15, 136424},
+       {20, 128565},
+       {25, 120978},
+       {30, 113875},
+       {35, 107397},
+       {40, 101629},
+       {45,  96592},
+       {50,  92253},
+       {55,  88569},
+       {60,  85461},
+       {65,  82869},
+};
+static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
+       {4171,  100},
+       {4114,   95},
+       {4009,   83},
+       {3947,   74},
+       {3907,   67},
+       {3863,   59},
+       {3830,   56},
+       {3813,   53},
+       {3791,   46},
+       {3771,   33},
+       {3754,   25},
+       {3735,   20},
+       {3717,   17},
+       {3681,   13},
+       {3664,    8},
+       {3651,    6},
+       {3635,    5},
+       {3560,    3},
+       {3408,    1},
+       {3247,    0},
+};
+static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
+       {4161,  100},
+       {4124,   98},
+       {4044,   90},
+       {4003,   85},
+       {3966,   80},
+       {3933,   75},
+       {3888,   67},
+       {3849,   60},
+       {3813,   55},
+       {3787,   47},
+       {3772,   30},
+       {3751,   25},
+       {3718,   20},
+       {3681,   16},
+       {3660,   14},
+       {3589,   10},
+       {3546,    7},
+       {3495,    4},
+       {3404,    2},
+       {3250,    0},
+};
+
+static struct abx500_v_to_cap cap_tbl[] = {
+       {4186,  100},
+       {4163,   99},
+       {4114,   95},
+       {4068,   90},
+       {3990,   80},
+       {3926,   70},
+       {3898,   65},
+       {3866,   60},
+       {3833,   55},
+       {3812,   50},
+       {3787,   40},
+       {3768,   30},
+       {3747,   25},
+       {3730,   20},
+       {3705,   15},
+       {3699,   14},
+       {3684,   12},
+       {3672,    9},
+       {3657,    7},
+       {3638,    6},
+       {3556,    4},
+       {3424,    2},
+       {3317,    1},
+       {3094,    0},
+};
+
+/*
+ * Note that the res_to_temp table must be strictly sorted by falling
+ * resistance values to work.
+ */
+static struct abx500_res_to_temp temp_tbl[] = {
+       {-5, 214834},
+       { 0, 162943},
+       { 5, 124820},
+       {10,  96520},
+       {15,  75306},
+       {20,  59254},
+       {25,  47000},
+       {30,  37566},
+       {35,  30245},
+       {40,  24520},
+       {45,  20010},
+       {50,  16432},
+       {55,  13576},
+       {60,  11280},
+       {65,   9425},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
+       { 40, 120},
+       { 30, 135},
+       { 20, 165},
+       { 10, 230},
+       { 00, 325},
+       {-10, 445},
+       {-20, 595},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
+       { 60, 300},
+       { 30, 300},
+       { 20, 300},
+       { 10, 300},
+       { 00, 300},
+       {-10, 300},
+       {-20, 300},
+};
+EXPORT_SYMBOL(temp_to_batres_tbl_ext_thermistor);
+
+/* battery resistance table for LI ION 9100 battery */
+struct batres_vs_temp temp_to_batres_tbl_9100[] = {
+       { 60, 180},
+       { 30, 180},
+       { 20, 180},
+       { 10, 180},
+       { 00, 180},
+       {-10, 180},
+       {-20, 180},
+};
+EXPORT_SYMBOL(temp_to_batres_tbl_9100);
+
+struct abx500_battery_type bat_type_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+       /* First element always represent the UNKNOWN battery */
+       .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+       .resis_high = 0,
+       .resis_low = 0,
+       .battery_resistance = 300,
+       .charge_full_design = 612,
+       .nominal_voltage = 3700,
+       .termination_vol = 4050,
+       .termination_curr = 200,
+       .recharge_vol = 3990,
+       .normal_cur_lvl = 400,
+       .normal_vol_lvl = 4100,
+       .maint_a_cur_lvl = 400,
+       .maint_a_vol_lvl = 4050,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 400,
+       .maint_b_vol_lvl = 4000,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 53407,
+       .resis_low = 12500,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3600,
+       .termination_vol = 4150,
+       .termination_curr = 80,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
+       .r_to_t_tbl = temp_tbl_A_thermistor,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
+       .v_to_cap_tbl = cap_tbl_A_thermistor,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 165418,
+       .resis_low = 82869,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3600,
+       .termination_vol = 4150,
+       .termination_curr = 80,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
+       .r_to_t_tbl = temp_tbl_B_thermistor,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
+       .v_to_cap_tbl = cap_tbl_B_thermistor,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+EXPORT_SYMBOL(bat_type_thermistor);
+
+struct abx500_battery_type bat_type_ext_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+       /* First element always represent the UNKNOWN battery */
+       .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+       .resis_high = 0,
+       .resis_low = 0,
+       .battery_resistance = 300,
+       .charge_full_design = 612,
+       .nominal_voltage = 3700,
+       .termination_vol = 4050,
+       .termination_curr = 200,
+       .recharge_vol = 3990,
+       .normal_cur_lvl = 400,
+       .normal_vol_lvl = 4100,
+       .maint_a_cur_lvl = 400,
+       .maint_a_vol_lvl = 4050,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 400,
+       .maint_b_vol_lvl = 4000,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+/*
+ * These are the batteries that doesn't have an internal NTC resistor to 
measure
+ * its temperature. The temperature in this case is measure with a NTC placed
+ * near the battery but on the PCB.
+ */
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+       .resis_high = 76000,
+       .resis_low = 53000,
+       .battery_resistance = 300,
+       .charge_full_design = 900,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LION,
+       .resis_high = 30000,
+       .resis_low = 10000,
+       .battery_resistance = 300,
+       .charge_full_design = 950,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+       .name = POWER_SUPPLY_TECHNOLOGY_LION,
+       .resis_high = 95000,
+       .resis_low = 76001,
+       .battery_resistance = 300,
+       .charge_full_design = 950,
+       .nominal_voltage = 3700,
+       .termination_vol = 4150,
+       .termination_curr = 100,
+       .recharge_vol = 4130,
+       .normal_cur_lvl = 700,
+       .normal_vol_lvl = 4200,
+       .maint_a_cur_lvl = 600,
+       .maint_a_vol_lvl = 4150,
+       .maint_a_chg_timer_h = 60,
+       .maint_b_cur_lvl = 600,
+       .maint_b_vol_lvl = 4100,
+       .maint_b_chg_timer_h = 200,
+       .low_high_cur_lvl = 300,
+       .low_high_vol_lvl = 4000,
+       .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+       .r_to_t_tbl = temp_tbl,
+       .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+       .v_to_cap_tbl = cap_tbl,
+       .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+       .batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+EXPORT_SYMBOL(bat_type_ext_thermistor);
+
+static const struct abx500_bm_capacity_levels cap_levels = {
+       .critical       = 2,
+       .low            = 10,
+       .normal         = 70,
+       .high           = 95,
+       .full           = 100,
+};
+
+static const struct abx500_fg_parameters fg = {
+       .recovery_sleep_timer = 10,
+       .recovery_total_time = 100,
+       .init_timer = 1,
+       .init_discard_time = 5,
+       .init_total_time = 40,
+       .high_curr_time = 60,
+       .accu_charging = 30,
+       .accu_high_curr = 30,
+       .high_curr_threshold = 50,
+       .lowbat_threshold = 3100,
+       .battok_falling_th_sel0 = 2860,
+       .battok_raising_th_sel1 = 2860,
+       .user_cap_limit = 15,
+       .maint_thres = 97,
+};
+
+static const struct abx500_maxim_parameters maxi_params = {
+       .ena_maxi = true,
+       .chg_curr = 910,
+       .wait_cycles = 10,
+       .charger_curr_step = 100,
+};
+
+static const struct abx500_bm_charger_parameters chg = {
+       .usb_volt_max           = 5500,
+       .usb_curr_max           = 1500,
+       .ac_volt_max            = 7500,
+       .ac_curr_max            = 1500,
+};
+
+struct abx500_bm_data ab8500_bm_data = {
+       .temp_under             = 3,
+       .temp_low               = 8,
+       .temp_high              = 43,
+       .temp_over              = 48,
+       .main_safety_tmr_h      = 4,
+       .temp_interval_chg      = 20,
+       .temp_interval_nochg    = 120,
+       .usb_safety_tmr_h       = 4,
+       .bkup_bat_v             = BUP_VCH_SEL_2P6V,
+       .bkup_bat_i             = BUP_ICH_SEL_150UA,
+       .no_maintenance         = false,
+       .adc_therm              = ABx500_ADC_THERM_BATCTRL,
+       .chg_unknown_bat        = false,
+       .enable_overshoot       = false,
+       .fg_res                 = 100,
+       .cap_levels             = &cap_levels,
+       .bat_type               = bat_type_thermistor,
+       .n_btypes               = 3,
+       .batt_id                = 0,
+       .interval_charging      = 5,
+       .interval_not_charging  = 120,
+       .temp_hysteresis        = 3,
+       .gnd_lift_resistance    = 34,
+       .maxi                   = &maxi_params,
+       .chg_params             = &chg,
+       .fg_params              = &fg,
+};
+EXPORT_SYMBOL(ab8500_bm_data);
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index bf02225..0f6578c 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -22,15 +22,15 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/kobject.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500.h>
 #include <linux/slab.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/of.h>
 #include <linux/delay.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/mfd/abx500.h>
 #include <linux/time.h>
 #include <linux/completion.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/mfd/abx500/ab8500-gpadc.h>
 
 #define MILLI_TO_MICRO                 1000
 #define FG_LSB_IN_MA                   1627
@@ -544,14 +544,14 @@ cc_err:
                ret = abx500_set_register_interruptible(di->dev,
                        AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
                        SEC_TO_SAMPLE(10));
-               if (ret)
+               if (ret < 0)
                        goto fail;
 
                /* Start the CC */
                ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
                        AB8500_RTC_CC_CONF_REG,
                        (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
-               if (ret)
+               if (ret < 0)
                        goto fail;
        } else {
                di->turn_off_fg = false;
@@ -2429,7 +2429,6 @@ static int __devexit ab8500_fg_remove(struct 
platform_device *pdev)
        flush_scheduled_work();
        power_supply_unregister(&di->fg_psy);
        platform_set_drvdata(pdev, NULL);
-       kfree(di);
        return ret;
 }
 
@@ -2442,22 +2441,149 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
        {"CCEOC", ab8500_fg_cc_data_end_handler},
 };
 
+static int __devinit
+fg_of_probe(struct device *dev,
+               struct device_node *np,
+               struct abx500_bm_plat_data *bm_pdata)
+{
+       int     i, ret = 0, thermistor = NTC_INTERNAL;
+       const   __be32 *ph;
+       const   char *bat_tech;
+       struct  abx500_fg_platform_data  *fg = bm_pdata->fg;
+       struct  abx500_bm_data           *bat;
+       struct  abx500_battery_type      *btype;
+       struct  device_node              *np_bat_supply;
+
+       /* get phandle to 'supplied-to' node */
+       ph = of_get_property(np, "supplied-to", &fg->num_supplicants);
+       if (ph == NULL) {
+               dev_err(dev, "no supplied_to property specified\n");
+               return -EINVAL;
+       }
+       fg->num_supplicants /= sizeof(int);
+       fg->supplied_to =
+               devm_kzalloc(dev, fg->num_supplicants *
+                       sizeof(const char *), GFP_KERNEL);
+       if (fg->supplied_to == NULL) {
+               dev_err(dev, "%s no mem for supplied-to\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < fg->num_supplicants; ++i) {
+               np_bat_supply = of_find_node_by_phandle(be32_to_cpup(ph) + i);
+               if (np_bat_supply == NULL) {
+                       dev_err(dev, "invalid supplied_to property\n");
+                       return -EINVAL;
+               }
+               ret = of_property_read_string(np_bat_supply, "interface-name",
+                               (const char **)(fg->supplied_to + i));
+               if (ret < 0) {
+                       of_node_put(np_bat_supply);
+                       dev_err(dev, "supply/interface name not found\n");
+                       return ret;
+               }
+               dev_dbg(dev, "%s power supply interface_name:%s\n",
+                       __func__, *(fg->supplied_to + i));
+       }
+       /* get phandle to 'battery-info' node */
+       ph = of_get_property(np, "battery-info", NULL);
+       if (ph == NULL) {
+               dev_err(dev, "missing property battery-info\n");
+               return -EINVAL;
+       }
+       np_bat_supply = of_find_node_by_phandle(be32_to_cpup(ph));
+       if (np_bat_supply == NULL) {
+               dev_err(dev, "invalid battery-info node\n");
+               return -EINVAL;
+       }
+       if (of_property_read_bool(np_bat_supply,
+                       "thermistor-on-batctrl") == false){
+               dev_warn(dev, "missing property thermistor-on-batctrl\n");
+               thermistor = NTC_EXTERNAL;
+       }
+       bm_pdata->battery = &ab8500_bm_data;
+       bat = bm_pdata->battery;
+       if (thermistor == NTC_EXTERNAL) {
+               bat->n_btypes  = 4;
+               bat->bat_type  = bat_type_ext_thermistor;
+               bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
+       }
+       ret = of_property_read_string(np_bat_supply, "battery-name", &bat_tech);
+       if (ret < 0) {
+               dev_warn(dev, "missing property battery-name/type\n");
+               bat_tech = "UNKNOWN";
+       }
+       of_node_put(np_bat_supply);
+       if (strcmp(bat_tech, "LION") == 0) {
+               bat->no_maintenance  = true;
+               bat->chg_unknown_bat = true;
+               bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
+               bat->bat_type[BATTERY_UNKNOWN].termination_vol    = 4150;
+               bat->bat_type[BATTERY_UNKNOWN].recharge_vol       = 4130;
+               bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl     = 520;
+               bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl     = 4200;
+       }
+       /* select the battery resolution table */
+       for (i = 0; i < bat->n_btypes; ++i) {
+               btype = (bat->bat_type + i);
+               if (thermistor == NTC_EXTERNAL) {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_ext_thermistor;
+               } else if (strcmp(bat_tech, "LION") == 0) {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_9100;
+               } else {
+                       btype->batres_tbl =
+                               temp_to_batres_tbl_thermistor;
+               }
+       }
+       return 0;
+}
+
 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;
+       struct device_node *np = pdev->dev.of_node;
        struct ab8500_fg *di;
 
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       if (!di) {
+               dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
+               return -ENOMEM;
+       }
+       if (np) {
+               if (!plat_data) {
+                       plat_data =
+                       devm_kzalloc(&pdev->dev, sizeof(*plat_data), 
GFP_KERNEL);
+                       if (!plat_data) {
+                               dev_err(&pdev->dev,
+                                       "%s no mem for plat_data\n", __func__);
+                               return -ENOMEM;
+                       }
+                       plat_data->fg = devm_kzalloc(&pdev->dev,
+                                       sizeof(*plat_data->fg), GFP_KERNEL);
+                       if (!plat_data->fg) {
+                               devm_kfree(&pdev->dev, plat_data);
+                               dev_err(&pdev->dev,
+                                       "%s no mem for pdata->fg\n",
+                                       __func__);
+                               return -ENOMEM;
+                       }
+               }
+               /* get battery specific platform data */
+               ret = fg_of_probe(&pdev->dev, np, plat_data);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to get platform data\n");
+                       return ret;
+               }
+       }
        if (!plat_data) {
-               dev_err(&pdev->dev, "No platform data\n");
+               dev_err(&pdev->dev,
+                       "%s no fg platform data found\n", __func__);
                return -EINVAL;
        }
 
-       di = kzalloc(sizeof(*di), GFP_KERNEL);
-       if (!di)
-               return -ENOMEM;
-
        mutex_init(&di->cc_lock);
 
        /* get parent data */
@@ -2469,16 +2595,14 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
        di->pdata = plat_data->fg;
        if (!di->pdata) {
                dev_err(di->dev, "no fg platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
+               return -EINVAL;
        }
 
        /* get battery specific platform data */
        di->bat = plat_data->battery;
        if (!di->bat) {
                dev_err(di->dev, "no battery platform data supplied\n");
-               ret = -EINVAL;
-               goto free_device_info;
+               return -EINVAL;
        }
 
        di->fg_psy.name = "ab8500_fg";
@@ -2506,7 +2630,7 @@ static int __devinit ab8500_fg_probe(struct 
platform_device *pdev)
        di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
        if (di->fg_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
-               goto free_device_info;
+               return -ENOMEM;
        }
 
        /* Init work for running the fg algorithm instantly */
@@ -2605,12 +2729,14 @@ free_irq:
        }
 free_inst_curr_wq:
        destroy_workqueue(di->fg_wq);
-free_device_info:
-       kfree(di);
-
        return ret;
 }
 
+static const struct of_device_id ab8500_fg_match[] = {
+       {.compatible = "stericsson,ab8500-fg",},
+       {},
+};
+
 static struct platform_driver ab8500_fg_driver = {
        .probe = ab8500_fg_probe,
        .remove = __devexit_p(ab8500_fg_remove),
@@ -2619,6 +2745,7 @@ static struct platform_driver ab8500_fg_driver = {
        .driver = {
                .name = "ab8500-fg",
                .owner = THIS_MODULE,
+               .of_match_table = ab8500_fg_match,
        },
 };
 
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 1318ca6..4c7f62a 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -382,7 +382,7 @@ struct abx500_bm_data {
        int gnd_lift_resistance;
        const struct abx500_maxim_parameters *maxi;
        const struct abx500_bm_capacity_levels *cap_levels;
-       const struct abx500_battery_type *bat_type;
+       struct abx500_battery_type *bat_type;
        const struct abx500_bm_charger_parameters *chg_params;
        const struct abx500_fg_parameters *fg_params;
 };
@@ -416,6 +416,11 @@ struct abx500_bm_plat_data {
        struct abx500_chargalg_platform_data *chargalg;
 };
 
+enum {
+       NTC_EXTERNAL = 0,
+       NTC_INTERNAL,
+};
+
 int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
        u8 value);
 int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
diff --git a/include/linux/mfd/abx500/ab8500-bm.h 
b/include/linux/mfd/abx500/ab8500-bm.h
index 44310c9..d15b7f1 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -422,6 +422,13 @@ struct ab8500_chargalg_platform_data {
 struct ab8500_btemp;
 struct ab8500_gpadc;
 struct ab8500_fg;
+
+extern struct abx500_bm_data ab8500_bm_data;
+extern struct abx500_battery_type bat_type_ext_thermistor[];
+extern struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[];
+extern struct batres_vs_temp temp_to_batres_tbl_9100[];
+extern struct batres_vs_temp temp_to_batres_tbl_thermistor[];
+
 #ifdef CONFIG_AB8500_BM
 void ab8500_fg_reinit(void);
 void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
-- 
1.7.9.5


_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to