rk3188:pmu:rt5025:updata rt5025 drivers, modify some fg and charger bug
author张晴 <zhangqing@rock-chips.com>
Sat, 24 Aug 2013 08:17:34 +0000 (16:17 +0800)
committer张晴 <zhangqing@rock-chips.com>
Sat, 24 Aug 2013 08:17:34 +0000 (16:17 +0800)
17 files changed:
arch/arm/mach-rk30/board-pmu-rt5025.c
arch/arm/mach-rk30/board-rk3168-tb.c
drivers/gpio/rt5025-gpio.c
drivers/mfd/rt5025-debug.c
drivers/mfd/rt5025-i2c.c
drivers/mfd/rt5025-irq.c
drivers/mfd/rt5025-misc.c
drivers/power/rt5025-battery.c
drivers/power/rt5025-power.c
drivers/power/rt5025-swjeita.c
drivers/regulator/rt5025-regulator.c
include/linux/mfd/rt5025-misc.h
include/linux/mfd/rt5025.h
include/linux/power/rockchip-general-bat.h [new file with mode: 0755]
include/linux/power/rt5025-battery.h
include/linux/power/rt5025-power.h
include/linux/power/rt5025-swjeita.h

index 17b99fa43dbd01bd6056f821108d816fafa3a35f..95dac82ea75d7f6a6368ad7fa67f96f5e2828a9d 100644 (file)
@@ -268,8 +268,8 @@ static struct rt5025_power_data rt5025_power_data = {
                .bitfield = {
                        .CHGBC_EN = 1,
                        .TE = 1,
-                       .CCCHG_TIMEOUT = RT5025_CCCHG_TO_6H,
-                       .PRECHG_TIMEOUT = RT5025_PRECHG_TO_30M,
+                       .CCCHG_TIMEOUT = RT5025_CCCHG_TO_10H,
+                       .PRECHG_TIMEOUT = RT5025_PRECHG_TO_60M,
                },
        },
        .CHGControl3 = {
@@ -280,8 +280,8 @@ static struct rt5025_power_data rt5025_power_data = {
        .CHGControl4 = {
                .bitfield = {
                        .AICR_CON = 1,
-                       .AICR = RT5025_AICR_500MA,
-                       .ICC = RT5025_ICC_0P5A,
+                       .AICR = RT5025_AICR_1A,
+                       .ICC = RT5025_ICC_1A,
                },
        },
        .CHGControl5 = {
@@ -291,7 +291,7 @@ static struct rt5025_power_data rt5025_power_data = {
        },
        .CHGControl6 = {
                .bitfield = {
-                       .IPREC = RT5025_IPREC_10P,
+                       .IPREC = RT5025_IPREC_20P,
                        .IEOC = RT5025_IEOC_10P,
                        .VPREC = RT5025_VPREC_3V,
                },
@@ -321,7 +321,7 @@ static struct rt5025_misc_data rt5025_misc_data = {
        },
        .VSYSCtrl = {
                .bitfield = {
-                       .VOFF = RT5025_VOFF_3P4V,
+                       .VOFF = RT5025_VOFF_3P0V,
                },
        },
        .PwrOnCfg = {
@@ -346,7 +346,7 @@ static struct rt5025_misc_data rt5025_misc_data = {
                        .DCDC3LV_ENSHDN = 0,
                        .DCDC2LV_ENSHDN = 0,
                        .DCDC1LV_ENSHDN = 0,
-                       .SYSLV_ENSHDN = 0,
+                       .SYSLV_ENSHDN = 1,
                },
        },
 };
@@ -354,7 +354,7 @@ static struct rt5025_misc_data rt5025_misc_data = {
 static struct rt5025_irq_data rt5025_irq_data = {
        .irq_enable1 = {
                .bitfield = {
-                       .BATABS = 1,
+                       .BATABS = 0,
                        .INUSB_PLUGIN = 1,
                        .INUSBOVP = 1,
                        .INAC_PLUGIN = 1,
@@ -366,17 +366,17 @@ static struct rt5025_irq_data rt5025_irq_data = {
                        .CHTERMI = 1,
                        .CHBATOVI = 1,
                        .CHGOODI_INUSB = 0,
-                       .CHBADI_INUSB = 1,
+                       .CHBADI_INUSB = 0,
                        .CHSLPI_INUSB = 1,
                        .CHGOODI_INAC = 0,
-                       .CHBADI_INAC = 1,
+                       .CHBADI_INAC = 0,
                        .CHSLPI_INAC = 1,
                },
        },
        .irq_enable3 = {
                .bitfield = {
-                       .TIMEOUT_CC = 1,
-                       .TIMEOUT_PC = 1,
+                       .TIMEOUT_CC = 0,
+                       .TIMEOUT_PC = 0,
                        .CHVSREGI = 0,
                        .CHTREGI = 0,
                        .CHRCHGI = 1,
@@ -384,13 +384,13 @@ static struct rt5025_irq_data rt5025_irq_data = {
        },
        .irq_enable4 = {
                .bitfield = {
-                       .SYSLV = 1,
-                       .DCDC4LVHV = 1,
+                       .SYSLV = 0,
+                       .DCDC4LVHV = 0,
                        .PWRONLP = 0,
                        .PWRONSP = 0,
-                       .DCDC3LV = 1,
-                       .DCDC2LV = 1,
-                       .DCDC1LV = 1,
+                       .DCDC3LV = 0,
+                       .DCDC2LV = 0,
+                       .DCDC1LV = 0,
                        .OT = 1,
                },
        },
@@ -409,10 +409,11 @@ static struct rt5025_irq_data rt5025_irq_data = {
 
 //temp unit: 'c*10 degree
 static int jeita_temp[4] = { 0, 150, 500, 600};
-static u8 jeita_scalar[4] = { 0x2d,  0x25, 0x12, 0x0e};
+                            //-5',  5',   15', 20',   45'   55'   55',  65'
+static u8 jeita_scalar[8] = { 0x30, 0x2B, 0x25, 0x20, 0x15, 0x10, 0x10, 0x0D };
 //cc unit: xxx mA
 static int jeita_temp_cc[][5] = {{ 500,  500,  500,  500, 500},    // not plugin
-                                {   0 , 250,  500,  250,   0},    // normal USB
+                                {   0 , 500,  500,  500,   0},    // normal USB
                                 {   0,  500, 1000,  500,   0},    // USB charger
                                 {   0,  500, 1000,  500,   0}};   // AC Adapter
 //cv unit: xxx mV
@@ -430,7 +431,7 @@ static struct rt5025_jeita_data rt5025_jeita_data = {
 
 static void rt5025_charger_event_callback(uint32_t detected)
 {
-       RTINFO("event detected = 0x%08x\n", detected);
+       RTINFO("charger event detected = 0x%08x\n", detected);
        if (detected & CHG_EVENT_CHTERMI)
        {
                pr_info("charger termination OK\n");
@@ -439,11 +440,7 @@ static void rt5025_charger_event_callback(uint32_t detected)
 
 static void rt5025_power_event_callback(uint32_t detected)
 {
-       RTINFO("event detected = 0x%08x\n", detected);
-       if (detected & PWR_EVENT_SYSLV)
-       {
-               pr_info("sys voltage low\n");
-       }
+       RTINFO("power event detected = 0x%08x\n", detected);
 }
 
 static struct rt5025_event_callback rt5025_event_callback = {
index e6bf4c50e136b44af67b3f56e386cb265f72e669..bd74a1bac58ec0b51e50f41a92a8d2b3243959f7 100755 (executable)
@@ -2114,6 +2114,12 @@ static struct pmu_info  rt5025_dcdc_info[] = {
                .max_uv         = 3300000,
        },
        
+       {
+               .name          = "rt5025-dcdc4",   //vccio
+               .min_uv         = 5000000,
+               .max_uv         = 5000000,
+       },
+       
 };
 static  struct pmu_info  rt5025_ldo_info[] = {
        {
index e4636f95975702e767730d3f7bd0acf991c9a881..97bebcd597c15dd75e288b5b7b743f3c999637dd 100755 (executable)
@@ -232,3 +232,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("GPIO driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-gpio");
+MODULE_VERSION(RT5025_DRV_VER);
index b50c70990d5345294ce75397940e57844d9aaa8c..5f6d8167834e887373a88dadf1e075b1c22f85d2 100644 (file)
@@ -32,6 +32,7 @@ static struct dentry *debugfs_rt_dent;
 static struct dentry *debugfs_peek;
 static struct dentry *debugfs_poke;
 static struct dentry *debugfs_regs;
+static struct dentry *debugfs_reset_b;
 
 static unsigned char read_data[10];
 
@@ -140,6 +141,14 @@ static ssize_t reg_debug_write(struct file *filp,
                }
                else
                        rc = -EINVAL;
+       } else if (!strcmp(access_str, "reset_b")) {
+               /* read */
+               rc = get_parameters(lbuf, param, 1);
+               if (param[0] == 1 && rc == 0)
+               {
+                       memset(lbuf, 0, 15);
+                       rt5025_reg_block_write(client, 0x21, 15, lbuf);
+               }
        }
 
        if (rc == 0)
@@ -180,6 +189,10 @@ static int __devinit rt5025_debug_probe(struct platform_device *pdev)
                debugfs_regs = debugfs_create_file("regs",
                S_IFREG | S_IRUGO, debugfs_rt_dent,
                (void *) "regs", &reg_debug_ops);
+
+               debugfs_reset_b = debugfs_create_file("reset_b",
+               S_IFREG | S_IRUGO, debugfs_rt_dent,
+               (void *) "reset_b", &reg_debug_ops);
        }
 
        platform_set_drvdata(pdev, di);
@@ -224,3 +237,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Debug driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-debug");
+MODULE_VERSION(RT5025_DRV_VER);
index b44a20dc16897511f676d1c535914650fcbd04be..df23585365ad4d602474f69967a66031a54f7deb 100644 (file)
@@ -288,6 +288,7 @@ static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 {
        struct rt5025_chip *chip = i2c_get_clientdata(client);
        chip->suspend = 1;
+       RTINFO("\n");
        return 0;
 }
 
@@ -295,6 +296,7 @@ static int rt5025_i2c_resume(struct i2c_client *client)
 {
        struct rt5025_chip *chip = i2c_get_clientdata(client);
        chip->suspend = 0;
+       RTINFO("\n");
        return 0;
 }
 
@@ -336,3 +338,4 @@ module_exit(rt5025_i2c_exit);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("I2C Driver for Richtek RT5025");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_VERSION(RT5025_DRV_VER);
index dcb15ecaf4de086a3b68abfc2fab06d84c12198e..161aefa787ce5ed1c1aefd4592044d1f8e3465a5 100644 (file)
@@ -239,7 +239,7 @@ static int __init rt5025_irq_init(void)
 {
        return platform_driver_register(&rt5025_irq_driver);
 }
-subsys_initcall_sync(rt5025_irq_init);
+module_init(rt5025_irq_init);
 
 static void __exit rt5025_irq_exit(void)
 {
@@ -251,3 +251,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("IRQ driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-irq");
+MODULE_VERSION(RT5025_DRV_VER);
index e47b1d62a941f48ecd9cf2cdab4a49813dc72307..3b680eab4361af2344b21d11c16d05e0ff43a967 100644 (file)
@@ -27,6 +27,8 @@ struct rt5025_misc_info {
 static struct i2c_client *g_shdn;
 void rt5025_power_off(void)
 {
+       rt5025_reg_write(g_shdn, RT5025_CHENH_REG, 0x00);
+       rt5025_reg_write(g_shdn, RT5025_CHENL_REG, 0x80);
        rt5025_set_bits(g_shdn, RT5025_SHDNCTRL_REG, RT5025_SHDNCTRL_MASK);
 }
 EXPORT_SYMBOL(rt5025_power_off);
@@ -87,7 +89,7 @@ static int __init rt5025_misc_init(void)
 {
        return platform_driver_register(&rt5025_misc_driver);
 }
-subsys_initcall_sync(rt5025_misc_init);
+module_init(rt5025_misc_init);
 
 static void __exit rt5025_misc_exit(void)
 {
@@ -99,3 +101,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Misc driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-misc");
+MODULE_VERSION(RT5025_DRV_VER);
index 12d59c6f74b5390639ce735e9f2bd192356e6d12..20d512ae8576730a943dee9e8df6755393ea5b2a 100644 (file)
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-battery.h>
 
-#define VOLTAGE_ALERT 1
+#define VOLTAGE_ALERT 0
 #define TEMPERATURE_ALERT 0
 
 #define RT5025_CSV 0
 #define RT5025_B 1
-#define RT5025_TEST_WAKE_LOCK 1
+#define RT5025_TEST_WAKE_LOCK 0
 
 u8 irq_thres[LAST_TYPE];
 
+static int rt5025_battery_parameter_backup(struct rt5025_battery_info *);
+
 void rt5025_gauge_set_status(struct rt5025_battery_info *bi, int status)
 {
   bi->status = status;
   if (status == POWER_SUPPLY_STATUS_FULL)
+  {
        bi->tp_flag = true;
+       bi->last_tp_flag = true;
+  }
+  else
+       power_supply_changed(&bi->battery);
+  wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
+  schedule_delayed_work(&bi->monitor_work, 0);
 }
 EXPORT_SYMBOL(rt5025_gauge_set_status);
 
@@ -108,18 +117,18 @@ static void rt5025_gauge_alarm(struct alarm *alarm)
 {
        struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(alarm, struct rt5025_battery_info, wakeup_alarm);
 
-       wake_lock(&bi->monitor_wake_lock);
+       //wake_lock(&bi->monitor_wake_lock);
        schedule_delayed_work(&bi->monitor_work, 0);
 }
 
 static void rt5025_program_alarm(struct rt5025_battery_info *bi)
 {
        ktime_t low_interval = ktime_set(bi->update_time, 0);
-       ktime_t slack = ktime_set(20, 0);
+       //ktime_t slack = ktime_set(20, 0);
        ktime_t next;
 
        next = ktime_add(bi->last_poll, low_interval);
-       alarm_start_range(&bi->wakeup_alarm, next, ktime_add(next, slack));
+       //alarm_start_range(&bi->wakeup_alarm, next, ktime_add(next, slack));
 }
 
 #if 0
@@ -194,10 +203,23 @@ static void rt5025_get_vcell(struct rt5025_battery_info *bi)
 {
   u8 data[2];
        
+  if (bi->init_once)
+  {
+    rt5025_clr_bits(bi->client, 0x07, 0x10);
+    RTINFO("set_current switch off\n");
+    mdelay(1000);
+  }
+
   if (rt5025_read_reg(bi->client, RT5025_REG_VCELL_MSB, data, 2) < 0){
     printk(KERN_ERR "%s: Failed to read Voltage\n", __func__);
   }
 
+  if (bi->init_once)
+  {
+    rt5025_set_bits(bi->client, 0x07, 0x10);
+    RTINFO("set_current switch on\n");
+  }
+
   if (bi->avg_flag)
     bi->vcell = ((data[0] << 8) + data[1]) * 61 / 100;
   else 
@@ -227,6 +249,7 @@ static void rt5025_get_current(struct rt5025_battery_info *bi)
   u8 data[2];
   s32 temp;
   int sign = 0;
+  u8 curr_region;
 
   if (rt5025_read_reg(bi->client, RT5025_REG_CURRENT_MSB, data, 2) < 0) {
     printk(KERN_ERR "%s: Failed to read CURRENT\n", __func__);
@@ -274,8 +297,36 @@ static void rt5025_get_current(struct rt5025_battery_info *bi)
   else
          bi->curr = (bi->curr + temp) / 2;
 
+  if (bi->curr > -500)
+       curr_region = 0;
+  else if (bi->curr <= -500 && bi->curr > -1500)
+       curr_region = 1;
+  else
+       curr_region = 2;
+
+  if (curr_region != bi->edv_region)
+  {
+       switch (curr_region)
+       {
+               case 0:
+                       bi->empty_edv = rt5025_battery_param2[4].x;
+                       break;
+               case 1:
+                       bi->empty_edv = rt5025_battery_param2[4].x - 75;
+                       break;
+               case 2:
+                       bi->empty_edv = rt5025_battery_param2[4].x - 100 ;
+                       break;
+       }
+       bi->edv_region = curr_region;
+  }
+  RTINFO("empty_voltage=%d\n", bi->empty_edv);
+
   if(bi->curr > 0)
+  {
     bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
+    bi->last_tp_flag = false;
+  }
   else
     bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
   RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status);
@@ -291,6 +342,23 @@ static void rt5025_get_current(struct rt5025_battery_info *bi)
 #endif
 }
 
+static void rt5025_get_internal_temp(struct rt5025_battery_info *bi)
+{
+       u8 data[2];
+       s32 temp;
+       if (rt5025_read_reg(bi->client, RT5025_REG_INT_TEMPERATUE_MSB, data, 2) < 0){
+               printk(KERN_ERR "%s: Failed to read internal TEMPERATURE\n", __func__);
+       }
+
+       temp = ((data[0]&0x1F)<<8) + data[1];
+       temp *= 15625;
+       temp /= 100000;
+
+       temp = (data[0]&0x20)?-temp:temp;
+       bi->int_temp = temp;
+       RTINFO("internal temperature: %d\n", bi->int_temp);
+}
+       
 static void rt5025_get_external_temp(struct rt5025_battery_info *bi)
 {
   u8 data[2];
@@ -340,7 +408,7 @@ static void rt5025_get_external_temp(struct rt5025_battery_info *bi)
         bi->health = POWER_SUPPLY_HEALTH_GOOD;
         bi->temp_recover_cnt = 0;
        }
-       //RTINFO("external temperature: %d\n", bi->ext_temp);
+       RTINFO("external temperature: %d\n", bi->ext_temp);
 }
 
 static void rt5025_clear_cc(struct rt5025_battery_info *bi, operation_mode mode)
@@ -365,35 +433,41 @@ static void rt5025_get_chg_cc(struct rt5025_battery_info *bi)
 {
   u8 data[4];
   u32 qh_old,ql_old,qh_new,ql_new;
-  u32 cc_masec,offset;
+  u32 cc_masec,offset=0;
   
   if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
     pr_err("%s: Failed to read QCHG\n", __func__);
   }
   qh_old = (data[0]<<8) + data[1];
   ql_old = (data[2]<<8) + data[3];
+  RTINFO("qh_old=%d, ql_old=%d\n", qh_old, ql_old);
   
   if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
     pr_err("%s: Failed to read QCHG\n", __func__);
   }
   qh_new = (data[0]<<8) + data[1];
   ql_new = (data[2]<<8) + data[3];
+  RTINFO("qh_new=%d, ql_new=%d\n", qh_new, ql_new);
 
 #if RT5025_B
   if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
   }else if (qh_new == qh_old){
     if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
     }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+      //cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+     cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
   }    
   
+  if (!bi->init_once)
        offset = bi->curr_offset * bi->time_interval;
                          
   if (cc_masec > offset){
-               cc_masec = (cc_masec - offset) / 1000;
+               cc_masec = cc_masec - (offset / 1000);
        }
 #else          
   if (qh_new > qh_old){
@@ -421,7 +495,8 @@ static void rt5025_get_chg_cc(struct rt5025_battery_info *bi)
        RTINFO("chg_cc_mAsec: %d\n", cc_masec);
 #endif
 
-       bi->chg_cc = cc_masec;
+       //if (!bi->init_once)
+               bi->chg_cc = cc_masec;
        //bi->chg_cc = (cc_masec + bi->chg_cc_unuse) / 3600;
   //bi->chg_cc_unuse = (cc_masec + bi->chg_cc_unuse) % 3600;
   rt5025_clear_cc(bi, CHG);
@@ -447,19 +522,23 @@ static void rt5025_get_dchg_cc(struct rt5025_battery_info *bi)
   
 #if RT5025_B
   if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
   }else if (qh_new == qh_old){
     if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
     }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+     //cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+     cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
   }    
   
+  if (!bi->init_once)
        offset = bi->curr_offset * bi->time_interval;
                          
   if (cc_masec != 0){
-               cc_masec = (cc_masec + offset) / 1000;
+               cc_masec = cc_masec + (offset / 1000);
        }
 #else  
   if (qh_new > qh_old){
@@ -487,6 +566,11 @@ static void rt5025_get_dchg_cc(struct rt5025_battery_info *bi)
        RTINFO("dchg_cc_mAsec: %d\n", cc_masec);
 #endif
        bi->dchg_cc = cc_masec;
+       if (bi->last_tp_flag)
+               bi->cal_fcc += cc_masec;
+       else
+               bi->cal_fcc = 0;
+       RTINFO("bi->cal_fcc=%d, bi->last_tp_flag=%d\n", bi->cal_fcc, bi->last_tp_flag);
        //bi->dchg_cc = (cc_masec + bi->dchg_cc_unuse) / 3600;
   //bi->dchg_cc_unuse = (cc_masec + bi->dchg_cc_unuse) % 3600;
        rt5025_clear_cc(bi, DCHG);
@@ -649,7 +733,7 @@ static void rt5025_alert_init(struct rt5025_battery_info *bi)
        /* Set RT5025 gauge alert configuration */
        rt5025_alert_threshold_init(bi->client);
        /* Enable gauge alert function */
-       rt5025_alert_setting(bi, MINVOLT2,VOLTAGE_ALERT);       
+       //rt5025_alert_setting(bi, MINVOLT2,VOLTAGE_ALERT);     
 }
 
 void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, u8 irq_flag)
@@ -684,7 +768,8 @@ void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, u8 irq_flag)
                wake_lock_timeout(&bi->low_battery_wake_lock, msecs_to_jiffies(LOW_BAT_WAKE_LOK_TIME*MSEC_PER_SEC));
        }
        
-       wake_lock(&bi->monitor_wake_lock);
+       //wake_lock(&bi->monitor_wake_lock);
+       wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
        schedule_delayed_work(&bi->monitor_work, 0);
 }
 EXPORT_SYMBOL(rt5025_gauge_irq_handler);
@@ -732,6 +817,8 @@ static void rt5025_init_capacity(struct rt5025_battery_info *bi)
   bi->soc = bi->rm /36/bi->fcc_aging;
        bi->init_cap = false;
 
+  rt5025_battery_parameter_backup(bi);
+
   //pr_err("[rt5025] i=%d, delta_x=%d, delta_y=%d, slope=%d, const_term=%d\n", i, delta_x, delta_y, slope, const_term);
        RTINFO("voltage=%d, permille=%d, soc=%d, rm=%d\n", bi->vcell, bi->permille, bi->soc, bi->rm);
   return;              
@@ -739,7 +826,7 @@ static void rt5025_init_capacity(struct rt5025_battery_info *bi)
 
 static void rt5025_smooth_soc(struct rt5025_battery_info *bi)
 {
-       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) &&
+       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING || bi->tp_flag == 1) &&
            (bi->soc < 100))
        {
                bi->soc++;
@@ -781,8 +868,11 @@ static void rt5025_soc_irreversible(struct rt5025_battery_info *bi)
        else
                bi->init_once = false;
 
+       if (bi->pre_soc != bi->soc)
+               rt5025_battery_parameter_backup(bi);
+
        bi->pre_soc = bi->soc;
-//     RTINFO("pre_soc=%d, soc=%d, internal status=%d\n", bi->pre_soc,bi->soc,bi->internal_status);
+       RTINFO("pre_soc=%d, soc=%d, internal status=%d\n", bi->pre_soc,bi->soc,bi->internal_status);
 }
 
 static void rt5025_soc_lock(struct rt5025_battery_info *bi)
@@ -801,9 +891,14 @@ static void rt5025_soc_lock(struct rt5025_battery_info *bi)
   }
   else if ((bi->soc < 99) && (bi->tp_flag))
   {
-               bi->update_time = SMOOTH_POLL;
-               bi->smooth_flag = true;
-               rt5025_smooth_soc(bi);
+               if (!bi->last_suspend)
+               {
+                       bi->update_time = SMOOTH_POLL;
+                       bi->smooth_flag = true;
+                       rt5025_smooth_soc(bi);
+               }
+               else
+                       bi->last_suspend=false;
   }
   else
   {
@@ -824,9 +919,14 @@ static void rt5025_soc_lock(struct rt5025_battery_info *bi)
        }else if ((bi->soc > 1) &&
             (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
             (bi->edv_flag)){
-               bi->update_time = SMOOTH_POLL;
-               bi->smooth_flag = true;
-               rt5025_smooth_soc(bi);
+               if (!bi->last_suspend)
+               {
+                       bi->update_time = SMOOTH_POLL;
+                       bi->smooth_flag = true;
+                       rt5025_smooth_soc(bi);
+               }
+               else
+                       bi->last_suspend=false;
        }else{
                bi->edv_flag = false;
        }
@@ -892,18 +992,26 @@ static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
                rt5025_convert_masec_to_permille(bi);
                bi->update_time = NORMAL_POLL;
        }
+
+       if (bi->vcell <= bi->empty_edv)
+       {
+               if (bi->edv_cnt < 2)
+                       bi->edv_cnt++;
+       }
+       else
+               bi->edv_cnt=0;
        
-       if(rt5025_battery_param2[4].x < bi->vcell && bi->vcell <= rt5025_battery_param2[4].x+300)
+       if(bi->empty_edv < bi->vcell && bi->vcell <= bi->empty_edv+300)
        {
                bi->update_time = EDV_POLL;
                bi->edv_detection = true;
        }
-       else if((bi->vcell >= rt5025_battery_param2[4].x + 300 +EDV_HYS) && (bi->edv_detection == true))
+       else if((bi->vcell >= bi->empty_edv + 300 +EDV_HYS) && (bi->edv_detection == true))
        {
                 bi->update_time = NORMAL_POLL;
                 bi->edv_detection = false;              
        }
-       else if((bi->vcell <= rt5025_battery_param2[4].x) && (bi->min_volt2_alert == true))
+       else if((bi->vcell <= bi->empty_edv && bi->edv_cnt == 2)) //&& (bi->min_volt2_alert == true))
        {
                bi->edv_flag = true;
                bi->rm = 0;
@@ -911,7 +1019,7 @@ static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
                bi->edv_detection = false;
                bi->update_time = NORMAL_POLL;
        }
-       else if((bi->vcell > rt5025_battery_param2[4].x + EDV_HYS) && (bi->min_volt2_alert == true))
+       else if((bi->vcell > bi->empty_edv + EDV_HYS)) //&& (bi->min_volt2_alert == true))
        {
                bi->min_volt2_alert = false;
                bi->edv_flag = false;
@@ -954,7 +1062,7 @@ static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
   }*/
   if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) 
          bi->edv_flag = false;
-  else if (bi->status != POWER_SUPPLY_STATUS_FULL)
+  if (bi->status != POWER_SUPPLY_STATUS_FULL)
     bi->tp_flag = false;
 
 #if RT5025_CSV
@@ -968,6 +1076,7 @@ static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
   return;
 }
 
+#if 0
 static void rt5025_channel_cc(struct rt5025_battery_info *bi, bool enable)
 {
   u8 data[1];
@@ -986,6 +1095,7 @@ static void rt5025_channel_cc(struct rt5025_battery_info *bi, bool enable)
     printk(KERN_INFO "%s: failed to write channel\n", __func__);
   }
 }
+#endif
 
 #if 0
 static void rt5025_pretrim(struct rt5025_battery_info *bi)
@@ -1090,6 +1200,13 @@ static int rt5025_battery_parameter_backup(struct rt5025_battery_info *bi)
        //cycle_count
        data[0] = (bi->cycle_cnt)&0xff;
        rt5025_write_reg(bi->client, 0x2B, data, 1);
+       //soc
+       data[0] = (bi->soc)&0xff;
+       rt5025_write_reg(bi->client, 0x2C, data, 1);
+       //gauge_timer
+       data[0] = (bi->pre_gauge_timer>>8)&0xff;
+       data[1] = bi->pre_gauge_timer&0xff;
+       rt5025_write_reg(bi->client, 0x2D, data, 2);
        return 0;
 }
 
@@ -1102,14 +1219,20 @@ static int rt5025_battery_parameter_restore(struct rt5025_battery_info *bi)
        rt5025_read_reg(bi->client, 0x21, data, 2);
        bi->fcc = bi->fcc_aging = data[0]<<8 | data[1];
        //rm
-       rt5025_read_reg(bi->client, 0x23, data, 4);
-       bi->rm = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
+       //rt5025_read_reg(bi->client, 0x23, data, 4);
+       //bi->rm = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
        //acc_dchg_cap
        rt5025_read_reg(bi->client, 0x27, data, 4);
        bi->acc_dchg_cap = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
        //cycle_count
        rt5025_read_reg(bi->client, 0x2B, data, 1);
        bi->cycle_cnt = data[0];
+       //soc
+       rt5025_read_reg(bi->client, 0x2C, data, 1);
+       bi->soc = bi->pre_soc = data[0];
+       //pre_gauge_timer
+       rt5025_read_reg(bi->client, 0x2D, data, 2);
+       bi->pre_gauge_timer = bi->gauge_timer = (data[0]<<8) + data[1];
        
        return 0;
 }
@@ -1140,13 +1263,14 @@ static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
 static void rt5025_register_init(struct rt5025_battery_info *bi)
 {  
        u8 data[1];
-       
+
        /* enable the channel of current,qc,ain,vbat and vadc */
        if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
                pr_err("%s: failed to read channel\n", __func__);
        }
+       RTINFO("initial change enable=%02x\n", data[0]);
        data[0] = data[0] | CHANNEL_L_BIT_CADC_EN | CHANNEL_L_BIT_AINCH | \
-               CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN;
+               CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN | CHANNEL_L_BIT_INTEMPCH;
        if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
                pr_err("%s: failed to write channel\n", __func__);
        }
@@ -1179,15 +1303,18 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
   
        bi->acc_dchg_cap = 0;
        bi->cycle_cnt = 0;
+       bi->empty_edv = rt5025_battery_param2[4].x;
+       bi->edv_region = 0;
 
        // if has initial data, rewrite to the stored data
        if (rt5025_battery_parameter_initcheck(bi))
        {
                bi->init_cap = false;
                rt5025_battery_parameter_restore(bi);
-               bi->soc = bi->rm/36/bi->fcc_aging;
+               //bi->soc = bi->rm/36/bi->fcc_aging;
+               bi->rm = bi->soc*bi->fcc_aging*36;
        }
-  
+
        bi->update_time = NORMAL_POLL;
        bi->device_suspend = false;
        RTINFO("register initialized\n");
@@ -1401,7 +1528,8 @@ static void rt5025_update(struct rt5025_battery_info *bi)
   rt5025_get_vcell(bi);
   /* Update current */
   rt5025_get_current(bi);
-       
+  /* Update internal temperature */
+  rt5025_get_internal_temp(bi);        
   /* Update external temperature */
   rt5025_get_external_temp(bi);
   /* Read timer */
@@ -1457,7 +1585,7 @@ static void rt5025_update(struct rt5025_battery_info *bi)
        
 #if VOLTAGE_ALERT
        if ((bi->min_volt2_irq == false) &&
-                               (bi->vcell > (rt5025_battery_param2[4].x + EDV_HYS))){  
+                               (bi->vcell > (bi->empty_edv + EDV_HYS))){       
                rt5025_alert_setting(bi,MINVOLT2,true);                                         
        }
 #endif
@@ -1466,8 +1594,8 @@ static void rt5025_update(struct rt5025_battery_info *bi)
                bi->dchg_cc,bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag,bi->soc,
                bi->permille,bi->rm,bi->fcc,bi->smooth_flag,bi->acc_dchg_cap,bi->cycle_cnt,bi->update_time);
 #else
-  pr_info("[RT5025] update_time=%d\n",bi->update_time);
-  pr_info("\n");
+  RTINFO("[RT5025] update_time=%d\n",bi->update_time);
+  RTINFO("\n");
 #endif
 }
 
@@ -1476,8 +1604,10 @@ static void rt5025_update_work(struct work_struct *work)
        struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
        struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(delayed_work, struct rt5025_battery_info, monitor_work);
        unsigned long flags;
-       
-  rt5025_update(bi);
+
+       wake_lock(&bi->monitor_wake_lock);      
+       rt5025_update(bi);
+       power_supply_changed(&bi->battery);
   
        /* prevent suspend before starting the alarm */
        local_irq_save(flags);
@@ -1486,6 +1616,7 @@ static void rt5025_update_work(struct work_struct *work)
        local_irq_restore(flags);
 
        wake_unlock(&bi->monitor_wake_lock);
+       schedule_delayed_work(&bi->monitor_work, bi->update_time*HZ);
 }
 
 static enum power_supply_property rt5025_battery_props[] = {
@@ -1504,20 +1635,46 @@ static enum power_supply_property rt5025_battery_props[] = {
   #endif
 };
 
+static int rt5025_battery_sleepvth_setting(struct rt5025_battery_info* bi)
+{
+       u32 temp;
+       u8 vmax_th, vmin_th;
+       u8 vbat[2];
+       RTINFO("\n");
+       rt5025_read_reg(bi->client, RT5025_REG_VCELL_MSB, vbat, 2);
+       temp = ((vbat[0]<<8) + vbat[1])*61;
+       vmax_th = (temp+5000)/1953;
+       vmin_th = (temp-5000)/1953;
+
+       rt5025_write_reg(bi->client, RT5025_REG_VALRT_MAXTH, &vmax_th, 1);
+       rt5025_write_reg(bi->client, RT5025_REG_VALRT_MIN1TH, &vmin_th, 1);
+
+       RTINFO("vmax_th=0x%02x, vmin_th=0x%02x\n", vmax_th, vmin_th);
+       return 0;
+}
+
 static int rt5025_battery_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+       RTINFO("\n");
+       //rt5025_get_timer(bi);
        //bi->last_event = ktime_get();
        bi->last_event = current_kernel_time();
 
        //cy add for battery parameter backup
-       rt5025_battery_parameter_backup(bi);
+       //rt5025_battery_parameter_backup(bi);
 
-       rt5025_channel_cc(bi, false);
-       cancel_delayed_work(&bi->monitor_work);
-       rt5025_get_timer(bi);
+       //rt5025_channel_cc(bi, false);
+       cancel_delayed_work_sync(&bi->monitor_work);
+       //rt5025_update(bi);
        bi->device_suspend = true;
+       /* prevent suspend before starting the alarm */
        //bi->update_time = SUSPEND_POLL;
+       rt5025_alert_setting(bi,MAXVOLT, false);
+       rt5025_alert_setting(bi,MINVOLT1,false);
+       rt5025_battery_sleepvth_setting(bi);
+       rt5025_alert_setting(bi,MAXVOLT, true);
+       rt5025_alert_setting(bi,MINVOLT1,true);
        RTINFO("RM=%d\n",bi->rm);
        return 0;
 }
@@ -1539,11 +1696,11 @@ static int rt5025_battery_resume(struct platform_device *pdev)
        //bi->rm = bi->rm - (time_interval * SLEEP_CURRENT);
        //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm);  
 
-       rt5025_channel_cc(bi, true);
-       wake_lock(&bi->monitor_wake_lock);
-       schedule_delayed_work(&bi->monitor_work, 0);
+       //rt5025_channel_cc(bi, true);
+       bi->last_suspend = true;
        bi->device_suspend = false;
-       //RTINFO("\n");
+       schedule_delayed_work(&bi->monitor_work, 0);
+       RTINFO("\n");
        return 0;
 }
 
@@ -1580,6 +1737,7 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        
        wake_lock_init(&bi->monitor_wake_lock, WAKE_LOCK_SUSPEND, "rt-battery-monitor");
        wake_lock_init(&bi->low_battery_wake_lock, WAKE_LOCK_SUSPEND, "low_battery_wake_lock");
+       wake_lock_init(&bi->status_wake_lock, WAKE_LOCK_SUSPEND, "battery-status-changed");
 #if RT5025_TEST_WAKE_LOCK
        wake_lock_init(&bi->test_wake_lock, WAKE_LOCK_SUSPEND, "rt-test");
 #endif
@@ -1617,7 +1775,7 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        }
   
 
-       wake_lock(&bi->monitor_wake_lock);
+       //wake_lock(&bi->monitor_wake_lock);
 #if RT5025_TEST_WAKE_LOCK
        wake_lock(&bi->test_wake_lock);
 #endif
@@ -1638,8 +1796,12 @@ err_wake_lock:
 static void rt5025_battery_shutdown(struct platform_device *pdev)
 {
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
-
        RTINFO("\n");
+       if (bi->soc == 0 && bi->cal_fcc != 0 )
+       {
+               bi->fcc_aging = bi->cal_fcc/3600 - (bi->fcc -bi->fcc_aging);
+               RTINFO("bi->cal_fcc=%d\n", bi->cal_fcc);
+       }
        rt5025_battery_parameter_backup(bi);
 }
 
@@ -1673,3 +1835,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com");
 MODULE_DESCRIPTION("battery gauge driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-battery");
+MODULE_VERSION(RT5025_DRV_VER);
index fb5d2a7b7b5e1ee46188aaf8a83e2e9d703e043f..f9cf2588bd210cf67a9cdcfe82e159cc195f5b80 100644 (file)
@@ -99,7 +99,7 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
                        if (info->chip->battery_info)
                        {
                                if (info->chg_term == 0)
-                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_DISCHARGING);
+                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING);
                                else if (info->chg_term > 0)
                                {
                                        rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
@@ -189,6 +189,8 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
        old_acval = info->ac_online;
        old_usbval = info->usb_online;
        old_chgval = info->chg_stat;
+
+       mdelay(10);
        
        ret = rt5025_reg_read(info->i2c, RT5025_REG_CHGSTAT);
        if (ret<0)
@@ -218,10 +220,10 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
        
        if (new_acval || new_usbval)
        {
-               if (old_chgval != new_chgval)
-               {
+               //if (old_chgval != new_chgval)
+               //{
                        ret = rt5025_chgstat_changed(info, new_chgval);
-               }
+               //}
        }
        else
        {
@@ -234,7 +236,7 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
                        rt5025_notify_charging_cable(info->chip->jeita_info, JEITA_NO_CHARGE);
                #if 1
                if (info->chip->battery_info)
-                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_NOT_CHARGING);
+                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_DISCHARGING);
                #else
                if (info->event_callback)
                        info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
@@ -275,7 +277,7 @@ static void usb_detect_work_func(struct work_struct *work)
        struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
        struct rt5025_power_info *pi = (struct rt5025_power_info *)container_of(delayed_work, struct rt5025_power_info, usb_detect_work);
        
-       pr_info("rt5025: %s ++", __func__);
+       RTINFO("rt5025: %s ++", __func__);
 
        mutex_lock(&pi->var_lock);
        if (pi->ac_online)
@@ -286,19 +288,19 @@ static void usb_detect_work_func(struct work_struct *work)
        }
        else if (pi->usb_online)
        {
-               pr_info("%s: usb_cnt %d\n", __func__, pi->usb_cnt);
+               RTINFO("%s: usb_cnt %d\n", __func__, pi->usb_cnt);
                switch(dwc_vbus_status())
                {
                        case 2: // USB Wall charger
                                rt5025_set_charging_current(pi->i2c, 1000);
                                rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_USB_TA);
-                               pr_info("rt5025: detect usb wall charger\n");
+                               RTINFO("rt5025: detect usb wall charger\n");
                                break;
                        case 1: //normal USB
                        default:
                                rt5025_set_charging_current(pi->i2c, 500);
                                rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NORMAL_USB);
-                               pr_info("rt5025: detect normal usb\n");
+                               RTINFO("rt5025: detect normal usb\n");
                                break;
                }
                if (pi->usb_cnt++ < 60)
@@ -314,11 +316,12 @@ static void usb_detect_work_func(struct work_struct *work)
        }
        mutex_unlock(&pi->var_lock);
 
-       pr_info("rt5025: %s --", __func__);
+       RTINFO("rt5025: %s --", __func__);
 }
 
 static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct rt5025_power_data* pd)
 {
+       //unsigned char data;
        info->ac_online = 0;
        info->usb_online =0;
        //init charger buckck & charger current en to disable stat
@@ -327,15 +330,32 @@ static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct
        if (info->event_callback)
                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
        #endif
-       rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL4, RT5025_CHGRST_MASK);
-       udelay(200);
+       //rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL4, RT5025_CHGRST_MASK);
+       //udelay(200);
        //init register setting
        rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL2, pd->CHGControl2.val);
        rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL3, pd->CHGControl3.val);
        rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL4, pd->CHGControl4.val);
        rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL5, pd->CHGControl5.val);
        rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL6, pd->CHGControl6.val);
-       rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL7, pd->CHGControl7.val);
+       //rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL7, pd->CHGControl7.val);
+       rt5025_assign_bits(info->i2c, RT5025_REG_CHGCTL7, 0xEF, pd->CHGControl7.val);
+       rt5025_reg_write(info->i2c, 0xA9, 0x60 );
+       //Special buck setting
+       #if 0
+       //Buck 1
+       data = rt5025_reg_read(info->i2c, 0x47);
+       data ^=0xc2;
+       rt5025_reg_write(info->i2c, 0x47, data);
+       //Buck 2
+       data = rt5025_reg_read(info->i2c, 0x48);
+       data ^=0xc2;
+       rt5025_reg_write(info->i2c, 0x48, data);
+       //Buck 3
+       data = rt5025_reg_read(info->i2c, 0x49);
+       data ^=0xc2;
+       rt5025_reg_write(info->i2c, 0x49, data);
+       #endif  //#if 0
        
        rt5025_power_charge_detect(info);
 
@@ -407,6 +427,7 @@ static int rt5025_power_suspend(struct platform_device *pdev, pm_message_t state
        if (pi->event_callback)
                pi->event_callback->rt5025_gauge_suspend();
        #endif
+       RTINFO("\n");
        return 0;
 }
 
@@ -418,6 +439,7 @@ static int rt5025_power_resume(struct platform_device *pdev)
        if (pi->event_callback)
                pi->event_callback->rt5025_gauge_resume();
        #endif
+       RTINFO("\n");
        return 0;
 }
 
@@ -454,7 +476,7 @@ static int __init rt5025_power_init(void)
 {
        return platform_driver_register(&rt5025_power_driver);
 }
-device_initcall_sync(rt5025_power_init);
+late_initcall_sync(rt5025_power_init);
 
 static void __exit rt5025_power_exit(void)
 {
@@ -467,3 +489,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Power/Gauge driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-power");
+MODULE_VERSION(RT5025_DRV_VER);
index 5df1a363cfaf377acbdecb131e0720afb8a7b667..60609d5dbbec261e21832477c45454553a430835 100755 (executable)
@@ -22,7 +22,7 @@
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-swjeita.h>
 
-#define TEMP_TOLERANCE 10  // 'c*10 gap for tolerance
+#define TEMP_TOLERANCE 0  // 'c*10 gap for tolerance
 
 static int rt5025_set_charging_cc_switch (struct i2c_client *i2c, int onoff)
 {
@@ -50,7 +50,7 @@ static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value)
 
        ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data);
 
-       if (cur_value == 0)
+       if (cur_value < 500)
                rt5025_set_charging_cc_switch(i2c, 0);
        else
                rt5025_set_charging_cc_switch(i2c, 1);
@@ -166,6 +166,19 @@ static inline int rt5025_set_ainadc_onoff(struct rt5025_swjeita_info *swji, int
        return ret;
 }
 
+static inline int rt5025_set_intadc_onoff(struct rt5025_swjeita_info *swji, int enable)
+{
+       int ret;
+
+       RTINFO("enable = %d\n", enable);
+       if (enable)
+               ret = rt5025_set_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_INTEN_MASK);
+       else
+               ret = rt5025_clr_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_INTEN_MASK);
+
+       return ret;
+}
+
 static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
 {
        int ret = 0;
@@ -175,22 +188,22 @@ static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
        switch (index)
        {
                case 0:
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[0]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
                        break;
                case 1:
                        rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[0]);
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
                        break;
                case 2:
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[1]);
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[2]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[5]);
                        break;
                case 3:
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[4]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[7]);
                        break;
                case 4:
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[3]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[6]);
                        break;
        }
 
@@ -253,15 +266,18 @@ int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_typ
        switch (cable_type)
        {
                case JEITA_NORMAL_USB:
-                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
+                               - swji->dec_current);
                        rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
                        break;
                case JEITA_USB_TA:
-                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
+                               - swji->dec_current);
                        rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
                        break;
                case JEITA_AC_ADAPTER:
-                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
+                               - swji->dec_current);
                        rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
                        break;
                case JEITA_NO_CHARGE:
@@ -289,6 +305,62 @@ int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char e
 }
 EXPORT_SYMBOL(rt5025_swjeita_irq_handler);
 
+static void rt5025_get_internal_temp(struct rt5025_swjeita_info *swji)
+{
+       u8 data[2];
+       s32 temp;
+       if (rt5025_reg_block_read(swji->i2c, RT5025_REG_INTTEMP_MSB, 2, data) < 0){
+               pr_err("%s: Failed to read internal TEMPERATURE\n", __func__);
+       }
+
+       temp = ((data[0]&0x1F)<<8) + data[1];
+       temp *= 15625;
+       temp /= 100000;
+
+       temp = (data[0]&0x20)?-temp:temp;
+       swji->cur_inttemp = temp;
+
+       RTINFO("internal temperature: %d\n", temp);
+}
+       
+static void thermal_reg_work_func(struct work_struct *work)
+{
+       struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
+       struct rt5025_swjeita_info *swji = (struct rt5025_swjeita_info *)container_of(delayed_work, struct rt5025_swjeita_info, thermal_reg_work);
+       int therm_region;
+       
+       RTINFO("%s ++", __func__);
+       rt5025_get_internal_temp(swji);
+       if (swji->cur_inttemp < 800)
+               therm_region = 0;
+       else if (swji->cur_inttemp >= 800 && swji->cur_inttemp < 1000)
+               therm_region = 1;
+       else
+               therm_region = 2;
+
+       if (therm_region != swji->cur_therm_region)
+       {
+               switch (therm_region)
+               {
+                       case 0:
+                               swji->dec_current = 0;
+                               break;
+                       case 1:
+                               swji->dec_current = 300;
+                               break;
+                       case 2:
+                               swji->dec_current = 1000;
+                               break;
+               }
+               swji->cur_therm_region = therm_region;
+               rt5025_notify_charging_cable(swji, swji->cur_cable);
+       }
+
+       schedule_delayed_work(&swji->thermal_reg_work, 5*HZ);
+
+       RTINFO("%s --", __func__);
+}
+
 static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
 {
        struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -315,7 +387,7 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
                pdata->jeita_data->temp_cv[ret][1], pdata->jeita_data->temp_cv[ret][2], \
                pdata->jeita_data->temp_cv[ret][3], pdata->jeita_data->temp_cv[ret][4]);
        }
-       for (ret=0; ret<4; ret++)
+       for (ret=0; ret<8; ret++)
        {
                RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]);
        }
@@ -330,11 +402,14 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
        swji->temp_scalar = pdata->jeita_data->temp_scalar;
        swji->temp_cc = pdata->jeita_data->temp_cc;
        swji->temp_cv = pdata->jeita_data->temp_cv;
+       INIT_DELAYED_WORK(&swji->thermal_reg_work, thermal_reg_work_func);
        platform_set_drvdata(pdev, swji);
 
        rt5025_set_ainadc_onoff(swji, 1);
+       rt5025_set_intadc_onoff(swji, 1);
        mdelay(100);
        rt5025_notify_charging_cable(swji, swji->cur_cable);
+       schedule_delayed_work(&swji->thermal_reg_work, 1*HZ);
 
        chip->jeita_info = swji;
        RTINFO("rt5025-swjeita driver is successfully loaded\n");
@@ -353,8 +428,11 @@ static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
 static int rt5025_swjeita_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
-       
+       cancel_delayed_work_sync(&swji->thermal_reg_work);
+       swji->cur_therm_region = swji->dec_current = 0;
+       rt5025_notify_charging_cable(swji, swji->cur_cable);
        swji->suspend = 1;
+       RTINFO("\n");
        return 0;
 }
 
@@ -363,6 +441,8 @@ static int rt5025_swjeita_resume(struct platform_device *pdev)
        struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
 
        swji->suspend = 0;
+       schedule_delayed_work(&swji->thermal_reg_work, 0);
+       RTINFO("\n");
        return 0;
 }
 
@@ -395,3 +475,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Swjeita driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-swjeita");
+MODULE_VERSION(RT5025_DRV_VER);
index 98b0d1b98c5ec4f8f49734fe3a0fe670023741a2..46f7c7a0bec51bd868e7216cae0290e14977ebce 100755 (executable)
@@ -462,3 +462,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Regulator driver for RT5025");
 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-regulator");
+MODULE_VERSION(RT5025_DRV_VER);
index dbd7e4e99d6019cd3f57311b23846537c223ae46..7bb506bf66229f0cedb656a03bfe87e95e7bd242 100755 (executable)
@@ -18,6 +18,8 @@
 #define RT5025_PWRONCTRL_REG   0x19
 #define RT5025_SHDNCTRL_REG    0x1A
 #define RT5025_PWROFFEN_REG    0x1B
+#define RT5025_CHENH_REG       0x62
+#define RT5025_CHENL_REG       0x63
 
 #define RT5025_SHDNCTRL_MASK   0x80
 #define RT5025_VSYSOFF_MASK    0xE0
index d3b790becfa7449c47a4b0b687bd5f74f253e493..bec9cb055b166dabd4e2a8e2c1cddf451678dda6 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/android_alarm.h>
 
 #define RT5025_DEVICE_NAME "RT5025"
+#define RT5025_DRV_VER    "1.0.2_R"
 
 enum {
        RT5025_RSTDELAY1_100MS,
@@ -410,20 +411,6 @@ struct rt5025_event_callback {
        #endif
 };
 
-struct rt5025_platform_data {
-       struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
-       struct rt5025_power_data* power_data;
-       struct rt5025_gpio_data* gpio_data;
-       struct rt5025_misc_data* misc_data;
-       struct rt5025_irq_data* irq_data;
-       struct rt5025_jeita_data* jeita_data;
-       struct rt5025_event_callback *cb;
-       int (*pre_init)(struct rt5025_chip *rt5025_chip);
-       /** Called after subdevices are set up */
-       int (*post_init)(void);
-       int intr_pin;
-};
-
 struct rt5025_power_info {
        struct i2c_client       *i2c;
        struct device           *dev;
@@ -443,13 +430,17 @@ struct rt5025_power_info {
 struct rt5025_swjeita_info {
        struct i2c_client *i2c;
        struct rt5025_chip *chip;
+       struct delayed_work thermal_reg_work;
        int *temp;
        u8 *temp_scalar;
        int (*temp_cc)[5];
        int (*temp_cv)[5];
+       int dec_current;
        int cur_section;
+       int cur_therm_region;
        int cur_cable;
        int cur_temp;
+       int cur_inttemp;
        int init_once;
        int suspend;
 };
@@ -464,6 +455,7 @@ struct rt5025_battery_info {
        struct delayed_work monitor_work;
        struct wake_lock monitor_wake_lock;
        struct wake_lock low_battery_wake_lock;
+       struct wake_lock status_wake_lock;
 //#if RT5025_TEST_WAKE_LOCK
        struct wake_lock test_wake_lock;
 //#endif
@@ -510,6 +502,8 @@ struct rt5025_battery_info {
   u16 curr_offset;
   /* AIN voltage */
   u16 ain_volt;
+  /* battery internal temperature */
+  s16 int_temp;
   /* battery external temperature */
   s16 ext_temp;
   /* charge coulomb counter */
@@ -583,9 +577,14 @@ struct rt5025_battery_info {
   
   u16 gauge_timer;
   s16 curr_raw;
+  u32 empty_edv;
+  u8  edv_region;
 
   bool init_once;
   bool device_suspend;
+  bool last_suspend;
+  bool last_tp_flag;
+  u32 cal_fcc;
   u8 test_temp;
 };
 
@@ -602,6 +601,20 @@ struct rt5025_chip {
        struct mutex io_lock;
 };
 
+struct rt5025_platform_data {
+       struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
+       struct rt5025_power_data* power_data;
+       struct rt5025_gpio_data* gpio_data;
+       struct rt5025_misc_data* misc_data;
+       struct rt5025_irq_data* irq_data;
+       struct rt5025_jeita_data* jeita_data;
+       struct rt5025_event_callback *cb;
+       int (*pre_init)(struct rt5025_chip *rt5025_chip);
+       /** Called after subdevices are set up */
+       int (*post_init)(void);
+       int intr_pin;
+};
+
 #ifdef CONFIG_MFD_RT5025_MISC
 extern void rt5025_power_off(void);
 #endif /* CONFIG_MFD_RT5025_MISC */
diff --git a/include/linux/power/rockchip-general-bat.h b/include/linux/power/rockchip-general-bat.h
new file mode 100755 (executable)
index 0000000..352be48
--- /dev/null
@@ -0,0 +1,26 @@
+battery_graph_prop rt5025_battery_param1[] =
+{
+  {4190, 1000},
+  {4120, 980},
+  {4037, 890},
+  {3970, 800},
+  {3914, 710},
+  {3835, 580},
+  {3796, 490},
+  {3773, 400},
+  {3736, 240},
+  {3697, 140},
+  {3665, 70},
+  {3651, 50},
+  {3545, 20},
+  {3400, 0},   
+};
+
+battery_graph_prop rt5025_battery_param2[] =
+{
+  {450,14},
+  {250, 0},
+  {50,-78},
+  {50,  10},
+  {3400, 3671},
+};
index cbb92ac32e7dfefe1028c06d85b686fd49b053f5..6ac5757059f640d477787b73210e89bc7ae7319c 100755 (executable)
@@ -13,8 +13,8 @@
 #ifndef __LINUX_RT5025_BATTERY_H
 #define __LINUX_RT5025_BATTERY_H
 
-#define ROCKCHIP_BATTERY_6200MAH
-#undef ROCKCHIP_BATTERY_2100MAH
+#undef ROCKCHIP_BATTERY_6900MAH
+#undef ROCKCHIP_BATTERY_4000MAH
 
 #define RT5025_REG_IRQ_CTL             0x50
 #define RT5025_REG_IRQ_FLAG            0x51
@@ -25,8 +25,8 @@
 #define RT5025_REG_TALRT_MINTH         0x57
 #define RT5025_REG_VCELL_MSB           0x58
 #define RT5025_REG_VCELL_LSB           0x59
-#define RT5025_REG_INT_TEMPERATUE_MSB  0x5B
-#define RT5025_REG_INT_TEMPERATUE_LSB  0x5C
+#define RT5025_REG_INT_TEMPERATUE_MSB  0x5A
+#define RT5025_REG_INT_TEMPERATUE_LSB  0x5B
 #define RT5025_REG_EXT_TEMPERATUE_MSB  0x5E
 #define RT5025_REG_EXT_TEMPERATUE_LSB  0x5F
 #define RT5025_REG_TIMER               0x60
@@ -66,8 +66,8 @@
 
 #define NORMAL_POLL  30       /* 30 sec */
 #define TP_POLL      5       /* 5 sec */
-#define EDV_POLL     1       /* 1 sec */
-#define SMOOTH_POLL  5      /* 5 sec */
+#define EDV_POLL     5       /* 1 sec */
+#define SMOOTH_POLL  20      /* 5 sec */
 #define SUSPEND_POLL (30*60) /* 30 min */
 #define INIT_POLL    1
 #define LOW_BAT_WAKE_LOK_TIME 120
@@ -112,10 +112,10 @@ typedef enum {
        LAST_TYPE,
 }alert_type;
 
-#if defined(ROCKCHIP_BATTERY_6200MAH)
-#include <linux/power/rockchip-6200ma-bat.h>
-#elif defined(ROCKCHIP_BATTERY_2100MAH)
-#include <linux/power/rockchip-2100ma-bat.h>
+#if defined(ROCKCHIP_BATTERY_6900MAH)
+#include <linux/power/rockchip-6900ma-bat.h>
+#elif defined(ROCKCHIP_BATTERY_4000MAH)
+#include <linux/power/rockchip-4000ma-bat.h>
 #else
 #include <linux/power/rockchip-general-bat.h>
 #endif
index 0f6d2470e2dc38643f689670828ba77adf127e52..50bdde02cabf5f34f0625c5d798e07bb3289a357 100755 (executable)
@@ -31,9 +31,9 @@
 #define RT5025_CHGSTAT_SHIFT 4
 #define RT5025_CHGSTAT_UNKNOWN 0x04
 
-#define RT5025_CHG_ACONLINE   0x02
-#define RT5025_CHG_ACSHIFT    1
-#define RT5025_CHG_USBONLINE  0x01
-#define RT5025_CHG_USBSHIFT   0
+#define RT5025_CHG_ACONLINE   0x01
+#define RT5025_CHG_ACSHIFT    0
+#define RT5025_CHG_USBONLINE  0x02
+#define RT5025_CHG_USBSHIFT   1
 
 #endif /* #ifndef __LINUX_RT5025_POWER_H */
index e2e432cf9d8e72250736aca71044c45a2d2af603..4c876a916bf9c9e93cb2d1b8a6c6adda2882a486 100755 (executable)
@@ -21,6 +21,7 @@
 #define RT5025_REG_IRQCTL      0x50
 #define RT5025_REG_TALRTMAX    0x56
 #define RT5025_REG_TALRTMIN    0x57
+#define RT5025_REG_INTTEMP_MSB 0x5A
 
 #define RT5025_CHGCCEN_MASK    0x10
 #define RT5025_CHGICC_SHIFT    3
@@ -28,6 +29,7 @@
 #define RT5025_CHGCV_SHIFT     2
 #define RT5025_CHGCV_MASK      0xFC
 #define RT5025_AINEN_MASK      0x04
+#define RT5025_INTEN_MASK      0x40
 #define RT5025_TMXEN_MASK      0x20
 #define RT5025_TMNEN_MASK      0x10