Check_charge_full function is added to determine the charge full condition.
Added a function calculate the charge cycles. Temperature based charging worker
is modified according to support SW charge termination and maintenance charging.


Signed-off-by: Ramakrishna Pallala <[email protected]>

--- drivers/power/intel_mdf_battery-Fuel-Gauge.c        2010-11-27 
04:59:24.670431339 +0530
+++ drivers/power/intel_mdf_battery.c   2010-11-27 05:01:35.122675000 +0530
@@ -300,6 +300,11 @@ enum {
 static void *otg_handle;
 static struct device *msic_dev;
 
+/* Variables for counting charge cycles */
+static unsigned int charge_cycle_ctr;
+static unsigned int chr_clmb_ctr;
+
+
 /*
  * This array represents the Battery Pack thermistor
  * temarature and corresponding ADC value limits
@@ -517,6 +522,7 @@ static enum power_supply_property msic_b
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+
 static int enable_adc(struct msic_power_module_info *mbi)
 {
        int ret;
@@ -1482,7 +1488,12 @@ static int msic_batt_do_charging(struct 
        dev_dbg(msic_dev, "Charger Enabled\n");
 
        mutex_lock(&mbi->batt_lock);
-       mbi->batt_props.status = POWER_SUPPLY_STATUS_CHARGING;
+       spin_lock(&mbi->event_lock);
+       if (mbi->charging_mode == BATT_CHARGING_MODE_MAINTAINENCE)
+               mbi->batt_props.status = POWER_SUPPLY_STATUS_FULL;
+       else
+               mbi->batt_props.status = POWER_SUPPLY_STATUS_CHARGING;
+       spin_unlock(&mbi->event_lock);
        mbi->batt_props.health = POWER_SUPPLY_HEALTH_GOOD;
        mutex_unlock(&mbi->batt_lock);
 
@@ -1559,6 +1570,111 @@ static void msic_update_disconn_status(s
        power_supply_changed(&mbi->batt);
 }
 
+static int check_charge_full(struct msic_power_module_info *mbi, int vref)
+{
+       static int vbat_prev[HYSTR_SAMPLE_MAX];
+       int vflag, vbat, vbat_diff, vocv, i;
+       int ibatt_avg, is_full = false;
+
+       /* Read battey vbatt */
+       vbat = mdf_read_adc_regs(MSIC_ADC_VOL_IDX, mbi);
+       /* Read battery current */
+       ibatt_avg = read_avg_ibatt(mbi);
+
+       /* Check the Vbat is consitant with in the range */
+       for (i = 0; i < HYSTR_SAMPLE_MAX; i++) {
+               vbat_diff = vbat - vbat_prev[i];
+               if (vbat_diff >= -20 && vbat_diff <= 20)
+                       continue;
+               else
+                       break;
+       }
+
+       if (i >= HYSTR_SAMPLE_MAX)
+               vflag = true;
+       else
+               vflag = false;
+
+       /*
+        * Rbatt value should be read from SMIP header but as a
+        * temporary fix we are hardcoding the Rbatt as 180 mOhms
+        */
+       vocv = vbat - (ibatt_avg * MSIC_CHRG_RBATT_VAL)/1000;
+       dev_dbg(msic_dev, "vocv:%d  vbat:%d\n", vocv, vbat);
+
+       /*
+        * Check if Vbat is equal to max charge voltage and
+        * charge rate is less than or equal to 0.05 coloumbs
+        */
+       if (vflag && (vocv >= (vref - BATT_ADC_VOLT_ERROR))) {
+               dev_dbg(msic_dev, "Charge Full Detected\n");
+               /* Disable Charging */
+               msic_batt_stop_charging(mbi);
+               is_full = true;
+       }
+
+       /* Push the array with latest value */
+       for (i = HYSTR_SAMPLE_MAX - 1; i > 0; i--)
+               vbat_prev[i] = vbat_prev[i-1];
+       vbat_prev[0] = vbat;
+
+       return is_full;
+}
+
+static bool is_maint_cutoff_vol(int adc_volt)
+{
+       static int vmaint_prev[HYSTR_SAMPLE_MAX];
+       int i;
+       bool flag;
+
+       /* Check whether the voltage is droping
+        * consistantly to enable maintenence charging
+        */
+       for (i = 0; i < HYSTR_SAMPLE_MAX; i++) {
+               if (adc_volt < vmaint_prev[i])
+                       continue;
+               else
+                       break;
+       }
+
+       if (i >= HYSTR_SAMPLE_MAX)
+               flag = true;
+       else
+               flag = false;
+
+       /* Push the array with latest value */
+       for (i = HYSTR_SAMPLE_MAX - 1; i > 0; i--)
+               vmaint_prev[i] = vmaint_prev[i-1];
+       vmaint_prev[0] = adc_volt;
+
+       return flag;
+}
+
+static void calculate_charge_cycles(struct msic_power_module_info *mbi,
+                                                               bool start_bit)
+{
+       static unsigned int chr_prev;
+       unsigned int chr_now, chr_now_ctr, chr_prev_ctr = 0;
+
+       if (start_bit)
+               chr_prev = 0;
+
+       chr_now = msic_read_coloumb_ctr();
+       chr_now_ctr = cc_to_coloumbs(chr_now);
+
+       chr_prev_ctr = cc_to_coloumbs(chr_prev);
+
+       /* count inflow charge given by charger */
+       if (!chr_prev)
+               chr_clmb_ctr += chr_now_ctr - chr_prev_ctr;
+
+       if (chr_clmb_ctr >= CHARGE_FULL_IN_MAH) {
+               charge_cycle_ctr++;
+               chr_clmb_ctr = 0;
+       }
+       chr_prev = chr_now;
+}
+
 /**
 * msic_batt_temp_charging - manages the charging based on temperature
 * @charge_param: charging parameter
@@ -1569,9 +1685,9 @@ static void msic_update_disconn_status(s
 */
 static void msic_batt_temp_charging(struct work_struct *work)
 {
-       int ret, i;
-       static int iprev = -1;
-       short int cv = 0, cc = 0, vinlimit = 0;
+       int ret, i, charge_now, is_maint_chrg = false;
+       static int iprev = -1, is_chrg_enbl;
+       short int cv = 0, cc = 0, vinlimit = 0, cvref;
        int adc_temp, adc_vol;
        struct charge_params charge_param;
        struct msic_power_module_info *mbi = container_of(work,
@@ -1587,13 +1703,13 @@ static void msic_batt_temp_charging(stru
                                        POWER_SUPPLY_CHARGE_TYPE_UNKNOWN ||
                mbi->usb_chrg_props.charger_type ==
                                                POWER_SUPPLY_CHARGE_TYPE_NONE) {
-
                /*
                 * If the the charger type is unknown or None
                 * better start the charging again and compute
                 * the properties again.
                 */
                iprev = -1;
+               is_chrg_enbl = false;
        }
        mutex_unlock(&mbi->usb_chrg_lock);
 
@@ -1607,6 +1723,7 @@ static void msic_batt_temp_charging(stru
 
                        cv = sfi_table->temp_mon_range[i].full_chrg_vol;
                        cc = sfi_table->temp_mon_range[i].full_chrg_cur;
+                       cvref = cv;
 
                        /* D7,D6 bits of CHRCNTL will set the VINILMT */
                        if (charge_param.vinilmt > 950)
@@ -1624,48 +1741,71 @@ static void msic_batt_temp_charging(stru
 
        if (i >= sfi_table->temp_mon_ranges) {
                dev_warn(msic_dev, "TEMP RANGE NOT EXIST\n");
+               /*
+                * If we are in middle of charge cycle is safer to Reset WDT
+                * Timer Register.Because battery temperature and Changre
+                * status register are not related.
+                */
+               reset_wdt_timer(mbi);
                goto lbl_sched_work;
        }
 
        /*
+        * Check for Charge full condition and set the battery
+        * properties accordingly. Also check for charging mode
+        * whether it is normal or maintenence mode.
+        */
+       spin_lock(&mbi->event_lock);
+       if (mbi->charging_mode == BATT_CHARGING_MODE_MAINTAINENCE) {
+               cvref = sfi_table->temp_mon_range[i].maint_chrg_vol_ul;
+               is_maint_chrg = true;
+       }
+       ret = check_charge_full(mbi, cvref);
+       if (ret) {
+               is_chrg_enbl = false;
+               if (mbi->charging_mode != BATT_CHARGING_MODE_MAINTAINENCE) {
+                       dev_dbg(msic_dev, "Going to Maintenence CHRG Mode\n");
+                       mbi->charging_mode = BATT_CHARGING_MODE_MAINTAINENCE;
+                       is_maint_chrg = true;
+
+                       mutex_lock(&mbi->batt_lock);
+                       charge_now = msic_read_coloumb_ctr();
+                       mbi->batt_props.charge_full =
+                                               cc_to_coloumbs(charge_now);
+                       mbi->batt_props.status = POWER_SUPPLY_STATUS_FULL;
+                       mutex_unlock(&mbi->batt_lock);
+               }
+       }
+       spin_unlock(&mbi->event_lock);
+
+       /*
         * If we are in same Temparature range check for check for the
         * maintainence charging mode and enable the charging depending
-        * on the adc voltage and lower threshold.
-        * If Temparature range is changed then anyways we need to set
-        * charging parameters and enable charging, in that case no need
-        * to check for Maintainence mode.
+        * on the voltage.If Temparature range is changed then anyways
+        * we need to set charging parameters and enable charging.
         */
        if (i == iprev) {
-
-               spin_lock(&mbi->event_lock);
-               if (mbi->charging_mode == BATT_CHARGING_MODE_MAINTAINENCE) {
-
-                       spin_unlock(&mbi->event_lock);
+               /*
+                * Check if the voltage falls below lower threshold
+                * if we are in maintenence mode charging.
+                */
+               if (is_maint_chrg && !is_chrg_enbl) {
                        temp_mon = &sfi_table->temp_mon_range[i];
-                       /* Read ADC value for battery Voltage */
+                       /* Read battery Voltage */
                        adc_vol = mdf_read_adc_regs(MSIC_ADC_VOL_IDX, mbi);
 
-                       /*
-                        * Check if the voltage falls below lower threshold
-                        * set charge voltage to maintainence voltage upper
-                        * limit and enable charging otherwise just
-                        * schedule the work
-                        */
-                       if (adc_vol <= temp_mon->maint_chrg_vol_ll)
+                       /* Cosidering ADC error of BATT_ADC_VOLT_ERROR */
+                       if ((adc_vol + 20) <= temp_mon->maint_chrg_vol_ll &&
+                                               is_maint_cutoff_vol(adc_vol)) {
+                               dev_dbg(msic_dev, "restart charging\n");
                                cv = temp_mon->maint_chrg_vol_ul;
-                       else
+                       } else {
+                               dev_dbg(msic_dev, "vbat is more than ll\n");
                                goto lbl_sched_work;
-
+                       }
                } else {
-
-                       spin_unlock(&mbi->event_lock);
-
-                       /*
-                        * We are not in normal Mode and no change in temp
-                        * range so just write the WDT timer and
-                        * schedule the wirk again.
-                        */
-                       dev_dbg(msic_dev, "NoChange in Temp Range\n");
+                       /* count charge cycles */
+                       calculate_charge_cycles(mbi, false);
                        /* Reset WDT Timer Register for 60 Sec */
                        reset_wdt_timer(mbi);
                        goto lbl_sched_work;
@@ -1683,9 +1823,6 @@ static void msic_batt_temp_charging(stru
        cc = cc << 3;
 
        charge_param.ccur = cc;
-
-       /* Enable Charge Termination */
-       vinlimit |= 0x08;
        charge_param.vinilmt = vinlimit;
 
        dev_dbg(msic_dev, "params  vol: %x  cur:%x vinilmt:%x\n",
@@ -1713,6 +1850,9 @@ static void msic_batt_temp_charging(stru
                dev_warn(msic_dev, "msic_batt_do_charging failed\n");
                goto lbl_sched_work;
        }
+       /* Start cycle counting */
+       calculate_charge_cycles(mbi, true);
+       is_chrg_enbl = true;
        power_supply_changed(&mbi->usb);
 
 lbl_sched_work:
@@ -2338,6 +2478,19 @@ ioremap_failed:
        return retval;
 }
 
+static void do_exit_ops(struct msic_power_module_info *mbi)
+{
+       /* disable MSIC Charger */
+       mutex_lock(&mbi->batt_lock);
+       if (mbi->batt_props.status != POWER_SUPPLY_STATUS_DISCHARGING)
+               msic_batt_stop_charging(mbi);
+       mutex_unlock(&mbi->batt_lock);
+
+       /* Check charge Cycles */
+       if (chr_clmb_ctr >= (CHARGE_FULL_IN_MAH / 2))
+               charge_cycle_ctr++;
+}
+
 /**
  * msic_battery_remove - msic battery finalize
  * @pdev: msic battery platform  device structure
@@ -2356,6 +2509,7 @@ static int msic_battery_remove(struct pl
                flush_scheduled_work();
                free_adc_channels(mbi->adc_index, mbi);
                free_irq(mbi->irq, mbi);
+               do_exit_ops(mbi);
                if (mbi->msic_regs_iomap != NULL)
                        iounmap(mbi->msic_regs_iomap);
                device_remove_file(&pdev->dev, &dev_attr_emrg_charge_enable);

Attachment: 005-Intel-MFLD-Battery-Driver-SW-Chrg-Termination.patch
Description: 005-Intel-MFLD-Battery-Driver-SW-Chrg-Termination.patch

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

Reply via email to