Merge branch 'develop-3.0' of ssh://10.10.10.29/rk/kernel into develop-3.0

This commit is contained in:
libing
2013-08-24 16:23:01 +08:00
17 changed files with 475 additions and 139 deletions

View 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 = {

View File

@@ -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[] = {
{

View File

@@ -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);

View 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);

View 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);

View 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);

View 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);

View File

@@ -28,20 +28,29 @@
#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);

View 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);

View File

@@ -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]);
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]);
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]);
break;
case 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[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);

View File

@@ -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);

View File

@@ -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

View 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 */

View File

@@ -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},
};

View File

@@ -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

View File

@@ -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 */

View File

@@ -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