To support fuel gauging Energy now, Energy full, charge counter and capacity 
level Sysfs Interfaces are added to driver.
A table is added to look up voltage against charge.

Signed-off-by: Ramakrishna Pallala <[email protected]>
---
 drivers/power/intel_mdf_battery.c |  196 +++++++++++++++++++++++++++++++++++-
 1 files changed, 190 insertions(+), 6 deletions(-)

diff --git a/drivers/power/intel_mdf_battery.c 
b/drivers/power/intel_mdf_battery.c
index c0b3121..8de4cd6 100644
--- a/drivers/power/intel_mdf_battery.c
+++ b/drivers/power/intel_mdf_battery.c
@@ -244,6 +244,37 @@
 #define BATT_STRING_MAX                8
 #define HYSTR_SAMPLE_MAX       4
 
+#define DISCHRG_CURVE_MAX_SAMPLES 17
+#define DISCHRG_CURVE_MAX_COLOMNS 2
+
+
+/*
+ * This array represents the Discharge curve of the battery
+ * Colomn 0 represnts Voltage in mV and colomn 1 represent
+ * charge in mColoumbs.
+ */
+static uint32_t const dischargeCurve[DISCHRG_CURVE_MAX_SAMPLES]
+                               [DISCHRG_CURVE_MAX_COLOMNS] = {
+       /* in mV , in mC */
+       {4200, 56603000},
+       {4150, 55754000},
+       {4100, 54905000},
+       {4050, 52385000},
+       {4000, 49811000},
+       {3950, 46697000},
+       {3900, 43584000},
+       {3850, 39339000},
+       {3800, 35094000},
+       {3750, 27452000},
+       {3700, 19811000},
+       {3650, 12735000},
+       {3600, 5660000},
+       {3550, 3963000},
+       {3500, 2264000},
+       {3450, 1132000},
+       {3400, 0}
+};
+
 
 /* Valid msic exceptional events */
 enum msic_event {
@@ -356,9 +387,13 @@ struct msic_batt_props {
        unsigned int vol_max_des;
        unsigned int vol_now;
        unsigned int cur_now;
-       unsigned int charge_full;       /* in mAS */
-       unsigned int charge_now;        /* in mAS */
-       unsigned int charge_avg;        /* in units per second */
+       unsigned int charge_full;       /* in mAh */
+       unsigned int charge_now;        /* in mAh */
+       unsigned int charge_ctr;        /* Coloumb counter raw value */
+       unsigned int charge_avg;        /* moving avg of charge now */
+       unsigned int energy_full;       /* in mWh */
+       unsigned int energy_now;        /* in mWh */
+       unsigned int capacity_level;    /* enumerated values */
        unsigned int capacity;          /* in units persentage */
        unsigned int temperature;       /* in milli Centigrade*/
        char model[BATT_STRING_MAX];
@@ -471,14 +506,19 @@ static enum power_supply_property msic_battery_props[] = {
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CHARGE_COUNTER,
        POWER_SUPPLY_PROP_CHARGE_FULL,
        POWER_SUPPLY_PROP_CHARGE_AVG,
-       POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+       POWER_SUPPLY_PROP_ENERGY_FULL,
+       POWER_SUPPLY_PROP_ENERGY_NOW,
+       POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+       POWER_SUPPLY_PROP_CAPACITY,
        POWER_SUPPLY_PROP_TEMP,
        POWER_SUPPLY_PROP_MODEL_NAME,
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+
 static int enable_adc(struct msic_power_module_info *mbi)
 {
        int ret;
@@ -930,6 +970,128 @@ static unsigned int mdf_cal_avg(unsigned int avg)
        return avg / 2;
 }
 
+static unsigned int chrg_to_vol_lookup(unsigned int chrg)
+{
+       int ch_diff, ch_total_diff, volt_total_diff, i;
+       unsigned int volt;
+
+       /* Find the index of most nearest charge value */
+       for (i = 0; i < DISCHRG_CURVE_MAX_SAMPLES; i++) {
+               if (chrg < dischargeCurve[i][1])
+                       continue;
+               else
+                       break;
+       }
+
+       if (i >= DISCHRG_CURVE_MAX_SAMPLES) {
+               dev_dbg(msic_dev, "charge out of range\n");
+               return 0;
+       }
+
+       if (chrg == dischargeCurve[i][1])
+               return dischargeCurve[i][0];
+
+       /* Linear approximation of the charge to voltage */
+       ch_diff = chrg - dischargeCurve[i][1];
+       ch_total_diff = dischargeCurve[i-1][1] - dischargeCurve[i][1];
+       volt_total_diff = dischargeCurve[i-1][0] - dischargeCurve[i][0];
+
+       volt  =  dischargeCurve[i][0] +
+                               (ch_diff * volt_total_diff) / ch_total_diff;
+
+       return volt;
+}
+
+static unsigned int msic_read_energy_now(struct msic_power_module_info *mbi)
+{
+       unsigned int vltg, chrg;
+
+       /* Read CC register value */
+       chrg = msic_read_coloumb_ctr();
+       /* Covert to milli coloumbs */
+       chrg = cc_to_coloumbs(chrg);
+
+       /* get voltage form lookup table */
+       vltg = chrg_to_vol_lookup(chrg);
+
+       /* Convert from mColoumbs to mAh */
+       chrg = chrg / COLMB_TO_MAHRS_CONV_FCTR;
+
+       return  (vltg * chrg) / 1000;
+}
+
+static int read_avg_ibatt(struct msic_power_module_info *mbi)
+{
+       int i, ibatt[HYSTR_SAMPLE_MAX], ibatt_avg = 0;
+
+       /* Measure  battey average current */
+       for (i = 0; i < HYSTR_SAMPLE_MAX; i++) {
+               ibatt[i] = mdf_read_adc_regs(MSIC_ADC_CUR_IDX, mbi);
+               ibatt_avg += ibatt[i];
+       }
+       ibatt_avg = ibatt_avg / HYSTR_SAMPLE_MAX;
+
+       return ibatt_avg;
+}
+
+static unsigned int calculate_batt_capacity(struct msic_power_module_info *mbi)
+{
+       int vocv, vbatt, ibatt;
+       unsigned int cap_perc;
+
+       vbatt = mdf_read_adc_regs(MSIC_ADC_VOL_IDX, mbi);
+       ibatt = read_avg_ibatt(mbi);
+
+       vocv = vbatt - (ibatt * MSIC_CHRG_RBATT_VAL) / 1000;
+
+       /* Temporary fix for calculating capacity.
+        * will be modified once Coloumb Counter
+        * works correctly.
+        */
+       vocv = vocv - BATT_DEAD_CUTOFF_VOLT;
+       if (vocv < 0)
+               vocv = 0;
+
+       cap_perc = (vocv * 100) / (mbi->batt_props.vol_max_des -
+                                               BATT_DEAD_CUTOFF_VOLT);
+
+       /* vocv can be slighlty more than voltage
+        * max value if the ibatt is -ve and vbatt
+        * has reached a maximum value.
+        */
+       if (cap_perc > 100)
+               cap_perc = 100;
+
+       return cap_perc;
+}
+
+static int msic_read_capacity_level(struct msic_power_module_info *mbi)
+{
+       int cap_perc, cap_level;
+
+       /* Calculate % of charge left */
+       cap_perc = calculate_batt_capacity(mbi);
+
+       /*
+        * 0, 15, 40, 85 threshold cut-offs are temporary
+        * actuall  thresholds will be read from SMIP header
+        */
+       if (cap_perc >= 0 && cap_perc < 15)
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+       else if (cap_perc >= 15 && cap_perc < 40)
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+       else if (cap_perc >= 40 && cap_perc < 85)
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+       else if (cap_perc >= 85 && cap_perc < 100)
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
+       else if (cap_perc == 100)
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+       else
+               cap_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+
+       return cap_level;
+}
+
 /**
  * msic_battery_get_property - battery power source get property
  * @psy: battery power supply context
@@ -986,6 +1148,10 @@ static int msic_battery_get_property(struct power_supply 
*psy,
                mbi->batt_props.charge_now = msic_get_charge_now();
                val->intval = mbi->batt_props.charge_now * 1000;
                break;
+       case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+               mbi->batt_props.charge_ctr = msic_read_coloumb_ctr();
+               val->intval =  mbi->batt_props.charge_ctr;
+               break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
                val->intval = mbi->batt_props.charge_full * 1000;
                break;
@@ -994,7 +1160,19 @@ static int msic_battery_get_property(struct power_supply 
*psy,
                                mdf_cal_avg(mbi->batt_props.charge_avg);
                val->intval = mbi->batt_props.charge_avg * 1000;
                break;
+       case POWER_SUPPLY_PROP_ENERGY_FULL:
+               val->intval = mbi->batt_props.energy_full * 1000;
+               break;
+       case POWER_SUPPLY_PROP_ENERGY_NOW:
+               mbi->batt_props.energy_now = msic_read_energy_now(mbi);
+               val->intval = mbi->batt_props.energy_now * 1000;
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+               mbi->batt_props.capacity_level = msic_read_capacity_level(mbi);
+               val->intval = mbi->batt_props.capacity_level;
+               break;
        case POWER_SUPPLY_PROP_CAPACITY:
+               mbi->batt_props.capacity = calculate_batt_capacity(mbi);
                val->intval = mbi->batt_props.capacity;
                break;
        case POWER_SUPPLY_PROP_TEMP:
@@ -1930,9 +2108,15 @@ static void init_batt_props(struct 
msic_power_module_info *mbi)
        mbi->batt_props.cur_now = 0x0;
        mbi->batt_props.charge_full = CHARGE_FULL_IN_MAH;
        mbi->batt_props.charge_now = 0x0;
+       mbi->batt_props.charge_ctr = 0x0;
        mbi->batt_props.charge_avg = 0x0;
-       mbi->batt_props.capacity = 0;
-       mbi->batt_props.temperature = 0;
+       mbi->batt_props.capacity = 0x0;
+       mbi->batt_props.capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+       mbi->batt_props.temperature = 0x0;
+
+       mbi->batt_props.energy_now = 0x0;
+       mbi->batt_props.energy_full = (mbi->batt_props.vol_max_des *
+                                       mbi->batt_props.charge_full) / 1000;
 
        memcpy(mbi->batt_props.vender, sfi_table->batt_id.manufac,
                                sizeof(sfi_table->batt_id.manufac));
-- 
1.7.2.3

Attachment: 0004-Added-Support-for-Fuel-Gauging.patch
Description: 0004-Added-Support-for-Fuel-Gauging.patch

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to