From af0c7815fe39f7c1c5b8a4723051f98bbfa533be Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BC=A0=E6=99=B4?= Date: Sat, 24 Aug 2013 16:17:34 +0800 Subject: [PATCH] rk3188:pmu:rt5025:updata rt5025 drivers, modify some fg and charger bug --- arch/arm/mach-rk30/board-pmu-rt5025.c | 47 ++-- arch/arm/mach-rk30/board-rk3168-tb.c | 6 + drivers/gpio/rt5025-gpio.c | 1 + drivers/mfd/rt5025-debug.c | 14 ++ drivers/mfd/rt5025-i2c.c | 3 + drivers/mfd/rt5025-irq.c | 3 +- drivers/mfd/rt5025-misc.c | 5 +- drivers/power/rt5025-battery.c | 269 +++++++++++++++++---- drivers/power/rt5025-power.c | 51 ++-- drivers/power/rt5025-swjeita.c | 109 +++++++-- drivers/regulator/rt5025-regulator.c | 1 + include/linux/mfd/rt5025-misc.h | 2 + include/linux/mfd/rt5025.h | 41 ++-- include/linux/power/rockchip-general-bat.h | 26 ++ include/linux/power/rt5025-battery.h | 20 +- include/linux/power/rt5025-power.h | 8 +- include/linux/power/rt5025-swjeita.h | 2 + 17 files changed, 472 insertions(+), 136 deletions(-) create mode 100755 include/linux/power/rockchip-general-bat.h diff --git a/arch/arm/mach-rk30/board-pmu-rt5025.c b/arch/arm/mach-rk30/board-pmu-rt5025.c index 17b99fa43dbd..95dac82ea75d 100644 --- a/arch/arm/mach-rk30/board-pmu-rt5025.c +++ b/arch/arm/mach-rk30/board-pmu-rt5025.c @@ -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 = { diff --git a/arch/arm/mach-rk30/board-rk3168-tb.c b/arch/arm/mach-rk30/board-rk3168-tb.c index e6bf4c50e136..bd74a1bac58e 100755 --- a/arch/arm/mach-rk30/board-rk3168-tb.c +++ b/arch/arm/mach-rk30/board-rk3168-tb.c @@ -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[] = { { diff --git a/drivers/gpio/rt5025-gpio.c b/drivers/gpio/rt5025-gpio.c index e4636f959757..97bebcd597c1 100755 --- a/drivers/gpio/rt5025-gpio.c +++ b/drivers/gpio/rt5025-gpio.c @@ -232,3 +232,4 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("CY Huang 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 "); +MODULE_VERSION(RT5025_DRV_VER); diff --git a/drivers/mfd/rt5025-irq.c b/drivers/mfd/rt5025-irq.c index dcb15ecaf4de..161aefa787ce 100644 --- a/drivers/mfd/rt5025-irq.c +++ b/drivers/mfd/rt5025-irq.c @@ -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 #include -#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 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 #include -#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 #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 index 000000000000..352be48c8bb6 --- /dev/null +++ b/include/linux/power/rockchip-general-bat.h @@ -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}, +}; diff --git a/include/linux/power/rt5025-battery.h b/include/linux/power/rt5025-battery.h index cbb92ac32e7d..6ac5757059f6 100755 --- a/include/linux/power/rt5025-battery.h +++ b/include/linux/power/rt5025-battery.h @@ -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 -#elif defined(ROCKCHIP_BATTERY_2100MAH) -#include +#if defined(ROCKCHIP_BATTERY_6900MAH) +#include +#elif defined(ROCKCHIP_BATTERY_4000MAH) +#include #else #include #endif diff --git a/include/linux/power/rt5025-power.h b/include/linux/power/rt5025-power.h index 0f6d2470e2dc..50bdde02cabf 100755 --- a/include/linux/power/rt5025-power.h +++ b/include/linux/power/rt5025-power.h @@ -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 */ diff --git a/include/linux/power/rt5025-swjeita.h b/include/linux/power/rt5025-swjeita.h index e2e432cf9d8e..4c876a916bf9 100755 --- a/include/linux/power/rt5025-swjeita.h +++ b/include/linux/power/rt5025-swjeita.h @@ -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 -- 2.34.1