diff options
author | Tao Huang <huangtao@rock-chips.com> | 2018-11-02 15:31:20 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2018-11-02 15:31:20 +0800 |
commit | cf0099827eb6e79f7a535507819440225c10e99e (patch) | |
tree | 05c881998b8a87c9946802e4581f7a4372d4e489 /drivers/power | |
parent | 955c9802a55cae649f47212f3cb0d4e829f3397d (diff) |
drivers: remove unused rt5025 drivers
Change-Id: Iee99365df115f30399737705d3c6b773a0f2cb34
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/rt5025-battery.c | 1861 | ||||
-rwxr-xr-x | drivers/power/rt5025-charger.c | 1224 | ||||
-rwxr-xr-x | drivers/power/rt5025-power.c | 566 | ||||
-rwxr-xr-x | drivers/power/rt5025-swjeita.c | 494 |
4 files changed, 0 insertions, 4145 deletions
diff --git a/drivers/power/rt5025-battery.c b/drivers/power/rt5025-battery.c deleted file mode 100644 index 8403b1da02d1..000000000000 --- a/drivers/power/rt5025-battery.c +++ /dev/null @@ -1,1861 +0,0 @@ -/* drivers/power/rt5025-battery.c - * I2C Driver for Richtek RT5025 PMIC - * Multi function device - multi functional baseband PMIC Battery part - * - * Copyright (C) 2014 Richtek Technology Corp. - * Author: Nick Hung <nick_hung@richtek.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/power_supply.h> -#include <linux/slab.h> -#include <linux/wakelock.h> -#include <linux/workqueue.h> -#include <linux/jiffies.h> -#include <linux/timer.h> -#include <linux/alarmtimer.h> -#include <linux/mfd/rt5025.h> -#include <linux/power/rt5025-battery.h> - - -#define VOLTAGE_ALERT 0 -#define TEMPERATURE_ALERT 0 - -#define RT5025_CSV 0 -#define RT5025_B 1 -#define RT5025_TEST_WAKE_LOCK 0 - -u8 irq_thres[LAST_TYPE]; - -static unsigned char gauge_init_regval[] = { - 0xFF, /*REG 0x53*/ - 0x00, /*REG 0x54*/ - 0x00, /*REG 0x55*/ - 0xFF, /*REG 0x56*/ - 0x00, /*REG 0x57*/ -}; - -static u16 crctab16[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78, -}; - -static int rt5025_battery_parameter_backup(struct rt5025_battery_info *); -static void rt5025_get_external_temp(struct rt5025_battery_info *); -static void rt5025_get_internal_temp(struct rt5025_battery_info *); -static void rt5025_get_vcell(struct rt5025_battery_info *); -static void rt5025_get_current(struct rt5025_battery_info *); -static void rt5025_temp_comp(struct rt5025_battery_info *); - -/* 20140415 CY */ -static int rt5025_read_reg(struct i2c_client *client, - u8 reg, u8 *data, u8 len) -{ - return rt5025_reg_block_read(client, reg, len, data); -} - -static int rt5025_write_reg(struct i2c_client *client, - u8 reg, u8 *data, u8 len) -{ - return rt5025_reg_block_write(client, reg, len, data); -} - -static void rt5025_set_battery_led(struct rt5025_battery_info *bi, int status) -{ - switch (status) { - case POWER_SUPPLY_STATUS_CHARGING: - break; - case POWER_SUPPLY_STATUS_DISCHARGING: - break; - case POWER_SUPPLY_STATUS_FULL: - break; - default: - break; - } -} - -static int rt5025_set_property(struct power_supply *psy, - enum power_supply_property psp, - const union power_supply_propval *val) -{ - struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent); - int rc = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - if (val->intval == POWER_SUPPLY_STATUS_FULL) { - bi->tp_flag = true; - pr_info("%s: Battery is full \n", __func__); - } else { - mutex_lock(&bi->status_change_lock); - bi->status = val->intval; - if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING) - bi->tp_flag = false; - rt5025_set_battery_led(bi, bi->status); - mutex_unlock(&bi->status_change_lock); - } - wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ); - schedule_delayed_work(&bi->monitor_work, msecs_to_jiffies(100)); - break; - case POWER_SUPPLY_PROP_PRESENT: - bi->batt_present = val->intval; - break; - default: - rc = -EINVAL; - break; - } - return rc; -} - -static int rt5025_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent); - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = bi->status; - /*val->intval = POWER_SUPPLY_STATUS_CHARGING;*/ - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = bi->health; - /*If there's no battery, always show battery health to good.*/ - if (!bi->present || !bi->batt_present) - val->intval = POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = bi->present; - break; - case POWER_SUPPLY_PROP_TEMP: - if (val->intval == 23) { - rt5025_get_external_temp(bi); - val->intval = bi->ext_temp; - } else { - /*If there's no battery, always show battery temperature to 25'c.*/ - if (!bi->present || !bi->batt_present) - val->intval = 250; - else - val->intval = bi->ext_temp; - } - break; - case POWER_SUPPLY_PROP_TEMP_AMBIENT: - rt5025_get_internal_temp(bi); - val->intval = bi->int_temp; - break; - case POWER_SUPPLY_PROP_ONLINE: - val->intval = bi->online; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - rt5025_get_vcell(bi); - val->intval = bi->vcell * 1000; /*uv*/ - break; - case POWER_SUPPLY_PROP_CURRENT_NOW: - rt5025_get_current(bi); - val->intval = bi->curr * 1000; /*uA*/ - break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = bi->soc; - if (val->intval > 100) - val->intval = 100; - /*If there's no battery, always show capacity to 50*/ - if (!bi->present || !bi->batt_present) - val->intval = 50; - break; - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; - break; - default: - return -EINVAL; - } - return 0; -} - -static void rt5025_get_vcell(struct rt5025_battery_info *bi) -{ - u8 data[2]; - - if (rt5025_read_reg(bi->client, RT5025_REG_VBATSH, data, 2) < 0) - pr_err("%s: Failed to read Voltage\n", __func__); - - if (bi->avg_flag) - bi->vcell = ((data[0] << 8) + data[1]) * 61 / 100; - else - bi->vcell = - (bi->vcell + ((data[0] << 8) + data[1]) * 61 / 100) / 2; -#if RT5025_B - - /*b. Remove current offset compensation; 2013/12/17*/ - bi->curr_offset = 0; - /*bi->curr_offset = (15444 * bi->vcell - 27444000) / 10000;*/ - -#else - if (37 * bi->vcell > 92000) - bi->curr_offset = (37 * bi->vcell - 92000) / 1000; - else - bi->curr_offset = 0; -#endif - -#if RT5025_CSV - /* if (!bi->avg_flag)*/ - /* pr_info("%d,%d,", bi->vcell, bi->curr_offset);*/ -#else - if (bi->avg_flag) - RTINFO("vcell_pre: %d, offset: %d\n", bi->vcell, bi->curr_offset); - else - RTINFO("vcell_avg: %d, offset: %d\n", bi->vcell, bi->curr_offset); -#endif -} - -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_CURRH, data, 2) < 0) - pr_err("%s: Failed to read CURRENT\n", __func__); - -#if RT5025_B - temp = (data[0] << 8) | data[1]; - bi->curr_raw = ((temp & 0x7FFF) * 3125) / 10000; - - if (data[0] & (1 << 7)) { - sign = 1; - temp = (((temp & 0x7FFF) * 3125) / 10 + bi->curr_offset) / 1000; - } else { - if ((temp * 3125) / 10 > bi->curr_offset) - temp = ((temp * 3125) / 10 - bi->curr_offset) / 1000; - } - if (temp < DEADBAND) - temp = 0; - if (sign) { - temp *= -1; - bi->curr_raw *= -1; - } -#else - temp = (data[0] << 8) | data[1]; - if (data[0] & (1 << 7)) { - sign = 1; - temp = temp & 0x7FFF; - if (temp > bi->curr_offset) - temp = temp - bi->curr_offset; - } else { - temp = temp + bi->curr_offset; - } - temp = (temp * 37375) / 100000; /*Unit: 0.3125mA*/ - if (temp < DEADBAND) - temp = 0; - if (sign) - temp *= -1; -#endif - - if (bi->avg_flag) - bi->curr = temp; - 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; - /*b. add fcc update flag; 2013/12/18*/ - bi->fcc_update_flag = true; - } else { - bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING; - } - RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status); - -#if RT5025_CSV - /*if (!bi->avg_flag)*/ - /*pr_info("%d,",bi->curr);*/ -#else - if (bi->avg_flag) - RTINFO("current_pre: %d\n", bi->curr); - else - RTINFO("current_avg: %d\n", bi->curr); -#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_INTEMPH, data, 2) < 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; - 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]; - s32 temp; - - if (rt5025_read_reg(bi->client, RT5025_REG_AINH, data, 2) < 0) - pr_err("%s: Failed to read TEMPERATURE\n", __func__); - bi->ain_volt = (data[0] * 256 + data[1]) * 61 / 100; - if (bi->ain_volt < 1150) - bi->present = 1; - else - bi->present = 0; - - temp = (bi->ain_volt * (-91738) + 81521000) / 100000; - bi->ext_temp = (int)temp; - /*test bi->ext_temp = 250;*/ - - if (bi->ext_temp >= HIGH_TEMP_THRES) { - if (bi->health != POWER_SUPPLY_HEALTH_OVERHEAT) - bi->temp_high_cnt++; - } else if (bi->ext_temp <= HIGH_TEMP_RECOVER - && bi->ext_temp >= LOW_TEMP_RECOVER) { - if (bi->health == POWER_SUPPLY_HEALTH_OVERHEAT - || bi->health == POWER_SUPPLY_HEALTH_COLD) - bi->temp_recover_cnt++; - } else if (bi->ext_temp <= LOW_TEMP_THRES) { - if (bi->health != POWER_SUPPLY_HEALTH_COLD) - bi->temp_low_cnt++; - } else { - bi->temp_high_cnt = 0; - bi->temp_low_cnt = 0; - bi->temp_recover_cnt = 0; - } - - if (bi->temp_high_cnt >= TEMP_ABNORMAL_COUNT) { - bi->health = POWER_SUPPLY_HEALTH_OVERHEAT; - bi->temp_high_cnt = 0; - } else if (bi->temp_low_cnt >= TEMP_ABNORMAL_COUNT) { - bi->health = POWER_SUPPLY_HEALTH_COLD; - bi->temp_low_cnt = 0; - } else if (bi->temp_recover_cnt >= TEMP_ABNORMAL_COUNT) { - bi->health = POWER_SUPPLY_HEALTH_GOOD; - bi->temp_recover_cnt = 0; - } - RTINFO("external temperature: %d\n", bi->ext_temp); -} - -static void rt5025_clear_cc(struct rt5025_battery_info *bi, operation_mode mode) -{ - u8 data[2]; - - if (rt5025_read_reg(bi->client, RT5025_REG_CHANNELH, data, 2) < 0) - pr_err("%s: failed to read channel\n", __func__); - - if (mode == CHG) - data[0] = data[0] | CHANNEL_H_BIT_CLRQCHG; - else - data[0] = data[0] | CHANNEL_H_BIT_CLRQDCHG; - - if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELH, data, 2) < 0) - pr_err("%s: failed to write channel\n", __func__); -} - -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 = 0; - - if (rt5025_read_reg(bi->client, RT5025_REG_QCHGHH, 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_QCHGHH, 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*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*328558+(qh_new*1824+ql_new*50134)/10000; - } else { - /*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); -#else - if (qh_new > qh_old) { - cc_masec = (((qh_new << 16) + ql_new) * 5996) / 1000; - } else if (qh_new == qh_old) { - if (ql_new >= ql_old) - cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000; - else - cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000; - } - - offset = (bi->curr_offset * bi->time_interval * 37375) / 100000; - - if (cc_masec != 0) - cc_masec = cc_masec - offset; -#endif - if (cc_masec < (DEADBAND * bi->time_interval)) - cc_masec = 0; - -#if RT5025_CSV -#else - RTINFO("chg_cc_mAsec: %d\n", cc_masec); -#endif - - /*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); -} - -static void rt5025_get_dchg_cc(struct rt5025_battery_info *bi) -{ - u8 data[4]; - u32 qh_old, ql_old, qh_new, ql_new; - u32 cc_masec, offset = 0; - - if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGHH, data, 4) < 0) - pr_err("%s: Failed to read QDCHG\n", - __func__); - - qh_old = (data[0] << 8) + data[1]; - ql_old = (data[2] << 8) + data[3]; - - if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGHH, data, 4) < 0) - pr_err("%s: Failed to read QDCHG\n", - __func__); - - qh_new = (data[0] << 8) + data[1]; - ql_new = (data[2] << 8) + data[3]; - -#if RT5025_B - if (qh_new > qh_old) { - /*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*328558+(qh_new*1824+ql_new*50134)/10000; - } else { - /*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); -#else - if (qh_new > qh_old) { - cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000; - } else if (qh_new == qh_old) { - if (ql_new >= ql_old) - cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000; - else - cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000; - } - - offset = (bi->curr_offset * bi->time_interval * 37375) / 100000; - - if (cc_masec > offset) - cc_masec = cc_masec - offset; -#endif - if (cc_masec < (DEADBAND * bi->time_interval)) - cc_masec = 0; - -#if RT5025_CSV -#else - RTINFO("dchg_cc_mAsec: %d\n", cc_masec); -#endif - bi->dchg_cc = cc_masec; - /*b. add fcc update flag; 2013/12/18*/ - if ((bi->last_tp_flag) && (bi->fcc_update_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); - -} - -static void rt5025_cycle_count(struct rt5025_battery_info *bi) -{ - bi->acc_dchg_cap += bi->dchg_cc; - if (bi->acc_dchg_cap >= (bi->dc * 3600)) { - bi->cycle_cnt++; - bi->acc_dchg_cap -= (bi->dc * 3600); - } -} - -static void rt5025_get_irq_flag(struct rt5025_battery_info *bi, u8 flag) -{ - bi->irq_flag = flag; - /*RTINFO("IRQ_FLG 0x%x\n", bi->irq_flag);*/ -} - -static void rt5025_get_timer(struct rt5025_battery_info *bi) -{ - u8 data[2]; - - if (rt5025_read_reg(bi->client, RT5025_REG_TIMERH, data, 2) < 0) - pr_err("%s: Failed to read Timer\n", __func__); - - bi->gauge_timer = (data[0] << 8) + data[1]; - if (!bi->device_suspend) { - if (bi->gauge_timer > bi->pre_gauge_timer) - bi->time_interval = bi->gauge_timer - bi->pre_gauge_timer; - else - bi->time_interval = 65536 - bi->pre_gauge_timer + bi->gauge_timer; - } - - bi->pre_gauge_timer = bi->gauge_timer; -#if RT5025_CSV - /*pr_info("%d,%d,", bi->gauge_timer,bi->time_interval);*/ -#else - RTINFO("timer %d , interval %d\n", bi->gauge_timer, bi->time_interval); -#endif -} - -static void rt5025_alert_setting(struct rt5025_battery_info *bi, - alert_type type, bool enable) -{ - u8 data[1]; - - if (rt5025_read_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0) - pr_err("%s: Failed to read CONFIG\n", __func__); - - if (enable) { - switch (type) { - case MAXTEMP: - data[0] |= IRQ_CTL_BIT_TMX; - /*Enable max temperature alert*/ - bi->max_temp_irq = true; - /*RTDBG("Enable min temperature alert");*/ - break; - case MINTEMP: - data[0] |= IRQ_CTL_BIT_TMN; - /*Enable min temperature alert*/ - bi->min_temp_irq = true; - /*RTDBG("Enable max temperature alert");*/ - break; - case MAXVOLT: - data[0] |= IRQ_CTL_BIT_VMX; - /*Enable max voltage alert*/ - bi->max_volt_irq = true; - /*RTDBG("Enable max voltage alert");*/ - break; - case MINVOLT1: - data[0] |= IRQ_CTL_BIT_VMN1; - /*Enable min1 voltage alert*/ - bi->min_volt1_irq = true; - /*RTDBG("Enable min1 voltage alert");*/ - break; - case MINVOLT2: - data[0] |= IRQ_CTL_BIT_VMN2; - /*Enable min2 voltage alert*/ - bi->min_volt2_irq = true; - /*RTDBG("Enable min2 voltage alert");*/ - break; - default: - break; - } - } else { - switch (type) { - case MAXTEMP: - data[0] = data[0] & ~IRQ_CTL_BIT_TMX; - /*Disable max temperature alert*/ - bi->max_temp_irq = false; - /*RTDBG("Disable min temperature alert");*/ - break; - case MINTEMP: - data[0] = data[0] & ~IRQ_CTL_BIT_TMN; - /*Disable min temperature alert*/ - bi->min_temp_irq = false; - /*RTDBG("Disable max temperature alert");*/ - break; - case MAXVOLT: - data[0] = data[0] & ~IRQ_CTL_BIT_VMX; - /*Disable max voltage alert*/ - bi->max_volt_irq = false; - /*RTDBG("Disable max voltage alert");*/ - break; - case MINVOLT1: - data[0] = data[0] & ~IRQ_CTL_BIT_VMN1; - /*Disable min1 voltage alert*/ - bi->min_volt1_irq = false; - /*RTDBG("Disable min1 voltage alert");*/ - break; - case MINVOLT2: - data[0] = data[0] & ~IRQ_CTL_BIT_VMN2; - /*Disable min2 voltage alert*/ - bi->min_volt2_irq = false; - /*RTDBG("Disable min2 voltage alert");*/ - break; - default: - break; - } - } - if (rt5025_write_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0) - pr_err("%s: failed to write IRQ control\n", __func__); -} - -static void rt5025_alert_threshold_init(struct i2c_client *client) -{ - u8 data[1]; - - /* VALRT MAX threshold setting */ - data[0] = irq_thres[MAXVOLT]; - if (rt5025_write_reg(client, RT5025_REG_VALRTMAX, data, 1) < 0) - pr_err("%s: failed to write VALRT MAX threshold\n", - __func__); - /* VALRT MIN1 threshold setting */ - data[0] = irq_thres[MINVOLT1]; - if (rt5025_write_reg(client, RT5025_REG_VALRTMIN1, data, 1) < 0) - pr_err("%s: failed to write VALRT MIN1 threshold\n", - __func__); - /* VALRT MIN2 threshold setting */ - data[0] = irq_thres[MINVOLT2]; - if (rt5025_write_reg(client, RT5025_REG_VALRTMIN2, data, 1) < 0) - pr_err("%s: failed to write VALRT MIN2 threshold\n", - __func__); -} - -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); -} - -void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, - unsigned int irq_flag) -{ - rt5025_get_irq_flag(bi, irq_flag); - - if ((bi->irq_flag) & IRQ_FLG_BIT_TMX) { - /*printk(KERN_INFO "[RT5025]: Min temperature IRQ received\n");*/ - rt5025_alert_setting(bi, MAXTEMP, false); - bi->max_temp_irq = false; - } - if ((bi->irq_flag) & IRQ_FLG_BIT_TMN) { - /*printk(KERN_INFO "[RT5025]: Max temperature IRQ received\n");*/ - rt5025_alert_setting(bi, MINTEMP, false); - bi->min_temp_irq = false; - } - if ((bi->irq_flag) & IRQ_FLG_BIT_VMX) { - /*printk(KERN_INFO "[RT5025]: Max voltage IRQ received\n");*/ - rt5025_alert_setting(bi, MAXVOLT, false); - bi->max_volt_irq = false; - } - if ((bi->irq_flag) & IRQ_FLG_BIT_VMN1) { - /*printk(KERN_INFO "[RT5025]: Min voltage1 IRQ received\n");*/ - rt5025_alert_setting(bi, MINVOLT1, false); - bi->min_volt1_irq = false; - } - if ((bi->irq_flag) & IRQ_FLG_BIT_VMN2) { - /*printk(KERN_INFO "[RT5025]: Min voltage2 IRQ received\n");*/ - rt5025_alert_setting(bi, MINVOLT2, false); - bi->min_volt2_irq = false; - bi->min_volt2_alert = true; - wake_lock_timeout(&bi->low_battery_wake_lock, - msecs_to_jiffies(LOW_BAT_WAKE_LOK_TIME * - MSEC_PER_SEC)); - } -} -EXPORT_SYMBOL(rt5025_gauge_irq_handler); - -static void rt5025_convert_masec_to_permille(struct rt5025_battery_info *bi) -{ - bi->permille = bi->rm / 3600 * 1000 / bi->fcc; - RTINFO("permille=%d\n", bi->permille); - /*return;*/ -} - -static void rt5025_convert_permille_to_masec(struct rt5025_battery_info *bi) -{ - bi->rm = bi->permille * bi->fcc / 1000 * 3600; - /*return;*/ -} - -static void rt5025_init_capacity(struct rt5025_battery_info *bi) -{ - int i = 1; - int size; - int slope, const_term; - int delta_y, delta_x; - - size = ARRAY_SIZE(rt5025_battery_param1); - while ((bi->vcell < rt5025_battery_param1[i].x) && - (i < (size - 1))) { - i++; - } - - delta_x = rt5025_battery_param1[i-1].x - rt5025_battery_param1[i].x; - delta_y = (rt5025_battery_param1[i-1].y - rt5025_battery_param1[i].y); - - slope = delta_y * 1000 / delta_x; - - const_term = (rt5025_battery_param1[i].y) - ((rt5025_battery_param1[i].x * slope) / 1000); - - if (bi->vcell >= rt5025_battery_param1[0].x) - bi->permille = rt5025_battery_param1[0].y; - else if (bi->vcell <= rt5025_battery_param1[size-1].x) - bi->permille = rt5025_battery_param1[size-1].y; - else - bi->permille = (bi->vcell * slope) / 1000 + const_term; - rt5025_convert_permille_to_masec(bi); - bi->soc = bi->rm / 36 / bi->fcc_aging; - bi->init_cap = false; - - rt5025_battery_parameter_backup(bi); - - RTINFO("voltage=%d, permille=%d, soc=%d, rm=%d\n", - bi->vcell, bi->permille, bi->soc, bi->rm); - /*return;*/ -} - -static void rt5025_smooth_soc(struct rt5025_battery_info *bi) -{ - if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING || bi->tp_flag) && - (bi->soc < 100)) { - if (bi->last_suspend == true) { - bi->soc = 100; - bi->last_suspend = false; - } else { - bi->soc++; - } - bi->rm = bi->fcc * bi->soc * 36; - rt5025_convert_masec_to_permille(bi); - - if (bi->soc == 100) { - /*fcc update in soc smooth 100%.*/ - if (bi->cal_soc_offset != 0) { - bi->fcc_aging -= bi->cal_soc_offset; - if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) { - bi->fcc = bi->fcc_aging; - bi->rm = bi->fcc * bi->soc * 36; - } else { - rt5025_temp_comp(bi); - } - bi->cal_soc_offset = 0; - } - wake_unlock(&bi->smooth100_wake_lock); - bi->last_tp = true; - bi->tp_flag = false; - bi->pre_soc = bi->soc; - - /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/ - bi->last_tp_flag = true; - mutex_lock(&bi->status_change_lock); - if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) { - bi->status = POWER_SUPPLY_STATUS_FULL; - rt5025_set_battery_led(bi, bi->status); - } - mutex_unlock(&bi->status_change_lock); - } - } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) && - (bi->soc > 0)) { - if (bi->last_suspend == true) { - bi->soc = 0; - bi->last_suspend = false; - } else { - bi->soc--; - } - bi->rm = bi->fcc * bi->soc * 36; - rt5025_convert_masec_to_permille(bi); - if (bi->soc == 0) - wake_unlock(&bi->smooth0_wake_lock); - } else { - bi->smooth_flag = false; - bi->update_time = NORMAL_POLL; - } -} - - -static void rt5025_soc_irreversible(struct rt5025_battery_info *bi) -{ - if (!bi->init_once) { - if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) { - if (bi->soc < bi->pre_soc) - bi->soc = bi->pre_soc; - } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) && - (bi->tp_flag == 0)) { - if (bi->soc > bi->pre_soc) - bi->soc = bi->pre_soc; - } - } 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); -} - -static void rt5025_soc_lock(struct rt5025_battery_info *bi) -{ - /*lock 99%*/ - u16 eoc_fcc_new = 0; - - RTINFO("internal status=%d, tp_flag=%d, soc=%d, soc99_lock_cnt=%d\n", - bi->internal_status, bi->tp_flag, bi->soc, - bi->soc99_lock_cnt); - RTINFO("init_once=%d, rm=%d, soc=%d\n", - bi->init_once, bi->rm, bi->soc); - - if (bi->soc >= 99) { - if (bi->soc99_lock_cnt >= 3600) { - bi->soc = 100; - bi->permille = 1000; - /*eoc fcc update function: when flag is true, update FCC.*/ - if (bi->cal_eoc_fcc != 0) { - /*eoc fcc update function: fcc update limitation 3%*/ - eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc / 3600; - if (eoc_fcc_new > ((bi->fcc_aging * 103) / 100)) - bi->fcc_aging = (bi->fcc_aging * 103) / 100; - else - bi->fcc_aging = eoc_fcc_new; - - if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) { - bi->fcc = bi->fcc_aging; - bi->rm = bi->fcc * bi->permille * 36 / 10; - } else { - rt5025_temp_comp(bi); - } - bi->cal_eoc_fcc = 0; - } - wake_unlock(&bi->full_battery_wake_lock); - bi->soc99_lock_cnt = 0; - bi->last_tp = true; - bi->tp_flag = false; - bi->pre_soc = bi->soc; - /*b. add fcc update flag; 2013/12/18*/ - bi->fcc_update_flag = false; - - /*a. When SOC = 100, report battery status is full; 2013/12/17 - bi->status = POWER_SUPPLY_STATUS_FULL; - */ - } else if (bi->tp_flag) { - RTINFO("before_eoc_fcc_new=%d\n", eoc_fcc_new); - RTINFO("before_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc); - RTINFO("before_fcc_aging=%d\n", bi->fcc_aging); - bi->soc = 100; - bi->permille = 1000; - if (bi->cal_eoc_fcc != 0) { - /*fcc update in eoc occurs. */ - eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc/3600; - if (eoc_fcc_new > ((bi->fcc_aging*103)/100)) - bi->fcc_aging = (bi->fcc_aging*103)/100; - else - bi->fcc_aging = eoc_fcc_new; - - RTINFO("after_eoc_fcc_new=%d\n", eoc_fcc_new); - RTINFO("after_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc); - RTINFO("after_fcc_aging=%d\n", bi->fcc_aging); - if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) { - bi->fcc = bi->fcc_aging; - bi->rm = bi->fcc * bi->permille * 36 / 10; - } else { - rt5025_temp_comp(bi); - } - bi->cal_eoc_fcc = 0; - } else if (bi->cal_soc_offset != 0) { - bi->fcc_aging -= bi->cal_soc_offset; - if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) { - bi->fcc = bi->fcc_aging; - bi->rm = bi->fcc * bi->permille * 36 / 10; - } else { - rt5025_temp_comp(bi); - } - bi->cal_soc_offset = 0; - } - - wake_unlock(&bi->full_battery_wake_lock); - bi->soc99_lock_cnt = 0; - bi->last_tp = true; - bi->tp_flag = false; - bi->pre_soc = bi->soc; - - /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/ - bi->last_tp_flag = true; - - mutex_lock(&bi->status_change_lock); - if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) { - bi->status = POWER_SUPPLY_STATUS_FULL; - rt5025_set_battery_led(bi, bi->status); - } - mutex_unlock(&bi->status_change_lock); - } else if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) && - (bi->last_tp == false)) { - bi->soc = 99; - bi->pre_soc = 99; - bi->soc99_lock_cnt += bi->time_interval; - } - } else if ((bi->soc < 99) && (bi->tp_flag)) { - /*calculate soc offset */ - if (bi->cal_soc_offset == 0) { - bi->cal_soc_offset = bi->fcc*3600 - bi->rm; - if (bi->cal_soc_offset > (bi->fcc_aging*3/100)) - bi->cal_soc_offset = bi->fcc_aging*3/100; - } - wake_lock(&bi->smooth100_wake_lock); - bi->update_time = SMOOTH_POLL; - bi->smooth_flag = true; - rt5025_smooth_soc(bi); - } else { - wake_unlock(&bi->smooth100_wake_lock); - bi->tp_flag = false; - bi->soc99_lock_cnt = 0; - } - /* a. When SOC = 100, report battery status is full; 2013/12/17 - /// a. judge charging status to check battery full condition; 2013/12/18*/ - if ((bi->soc == 100) && - (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)) { - mutex_lock(&bi->status_change_lock); - if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) { - bi->status = POWER_SUPPLY_STATUS_FULL; - rt5025_set_battery_led(bi, bi->status); - } - mutex_unlock(&bi->status_change_lock); - } - - /*lock 1% */ - if ((bi->soc <= 1) && - (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)) { - if (bi->edv_flag) { - bi->soc = 0; - } else { - if (bi->rm <= 0) { - bi->soc1_lock_cnt += bi->time_interval; - if (bi->soc1_lock_cnt >= 600) { - bi->soc = 0; - bi->soc1_lock_cnt = 0; - } else { - bi->soc = 1; - bi->pre_soc = 1; - } - } else { - bi->soc = 1; - bi->pre_soc = 1; - bi->soc1_lock_cnt = 0; - } - } - } else if ((bi->soc > 1) && - (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) && - (bi->edv_flag)) { - wake_lock(&bi->smooth0_wake_lock); - bi->update_time = SMOOTH_POLL; - bi->smooth_flag = true; - rt5025_smooth_soc(bi); - } else { - bi->edv_flag = false; - wake_unlock(&bi->smooth0_wake_lock); - } - RTINFO("cal_soc_offset=%d\n", bi->cal_soc_offset); -} - -static void rt5025_get_soc(struct rt5025_battery_info *bi) -{ - if (bi->smooth_flag) { - bi->smooth_flag = false; - bi->update_time = NORMAL_POLL; - } - RTINFO("before rm=%d\n", bi->rm); - if ((!bi->tp_flag) && (!bi->edv_flag)) { - bi->rm = (bi->rm + bi->chg_cc) > bi->dchg_cc ? - bi->rm + bi->chg_cc - bi->dchg_cc : 0; - if (bi->rm > (bi->fcc * 3600)) - bi->rm = bi->fcc * 3600; - - /* accumulate coulomb counter when rm = fcc and enable flag = true.*/ - if (bi->rm == (bi->fcc * 3600)) - bi->cal_eoc_fcc += (bi->chg_cc - bi->dchg_cc); - else - bi->cal_eoc_fcc = 0; - - RTINFO("cal_eoc_fcc=%d\n", bi->cal_eoc_fcc); - rt5025_convert_masec_to_permille(bi); - /*a. When SOC = 100, report battery status is full; 2113/12/17*/ - bi->soc = DIV_ROUND_UP(bi->permille, 10); - } -#if RT5025_CSV - bi->temp_soc = bi->soc; - /*pr_info("%d", bi->soc);*/ -#else - RTINFO("after rm=%d\n", bi->rm); - RTINFO("temp_soc=%d\n", bi->soc); -#endif -#if RT5025_CSV - RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n", - bi->soc, bi->permille, bi->rm, - bi->fcc, bi->smooth_flag); - /*pr_info("%d,%d,%d,%d,%d", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);*/ -#else - RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n", - bi->soc, bi->permille, bi->rm, - bi->fcc, bi->smooth_flag); -#endif - /*return;*/ -} - -static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi) -{ - - if (bi->tp_flag == true) { - bi->rm = bi->fcc * 3600; - 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 (bi->empty_edv < bi->vcell && bi->vcell <= bi->empty_edv + 300) { - bi->update_time = EDV_POLL; - 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 <= bi->empty_edv && bi->edv_cnt == 2)) { - bi->edv_flag = true; - bi->rm = 0; - rt5025_convert_masec_to_permille(bi); - bi->edv_detection = false; - bi->update_time = NORMAL_POLL; - } else if ((bi->vcell > bi->empty_edv + EDV_HYS)) { - bi->min_volt2_alert = false; - bi->edv_flag = false; - } - - if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) - bi->edv_flag = false; - -#if RT5025_CSV -#else - RTINFO("tp_cnt=%d, tp_flag=%d, edv_detection=%d, edv_cnt=%d, edv_flag=%d\n", - bi->tp_cnt, bi->tp_flag, bi->edv_detection, - bi->edv_cnt, bi->edv_flag); -#endif - - /* return;*/ -} - -static u16 get_crc16_value(u8 *data, int size) -{ - u16 fcs = 0xffff; - int len = size; - int i = 0; - u16 temp = 0; - - while (len > 0) { - fcs = (u16)((fcs >> 8) ^ crctab16[(fcs ^ data[i]) & 0xff]); - len--; - i++; - } - temp = (u16)~fcs; - return temp; -} - -static int IsCrc16Good(u8 *data, int size) -{ - u16 fcs = 0xffff; - int len = size; - int i = 0; - - while (len > 0) { - fcs = (u16)((fcs >> 8) ^ crctab16[((fcs ^ data[i]) & 0xff)]); - len--; - i++; - } - return (fcs == 0xf0b8); -} - -static int rt5025_battery_parameter_backup(struct rt5025_battery_info *bi) -{ - u16 crc_value = 0; - u8 data[15] = {0}; - - RTINFO("\n"); - /*backup fcc_aging, rm, cycle_count, acc_dchg_cap*/ - /*fcc_aging*/ - data[0] = (bi->fcc_aging >> 8) & 0xff; - data[1] = (bi->fcc_aging) & 0xff; - /*acc_dchg_cap*/ - data[2] = (bi->acc_dchg_cap >> 24) & 0xff; - data[3] = (bi->acc_dchg_cap >> 16) & 0xff; - data[4] = (bi->acc_dchg_cap >> 8) & 0xff; - data[5] = (bi->acc_dchg_cap) & 0xff; - /*cycle_count*/ - data[6] = (bi->cycle_cnt) & 0xff; - /*soc*/ - data[7] = (bi->permille >> 8) & 0xff; - data[8] = (bi->permille) & 0xff; - /*gauge_timer*/ - data[9] = (bi->pre_gauge_timer >> 8) & 0xff; - data[10] = bi->pre_gauge_timer & 0xff; - /*CRC value*/ - crc_value = get_crc16_value(data, 13); - data[13] = crc_value & 0xff; - data[14] = (crc_value >> 8) & 0xff; - rt5025_write_reg(bi->client, RT5025_REG_RESV1, data, 15); - return 0; -} - -static int rt5025_battery_parameter_restore(struct rt5025_battery_info *bi) -{ - u8 data[15]; - - RTINFO("\n"); - rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15); - /*restore fcc_aging, rm ,cycle_count, acc_dchg_cap*/ - /*fcc_aging*/ - bi->fcc = bi->fcc_aging = data[0] << 8 | data[1]; - /*acc_dchg_cap*/ - bi->acc_dchg_cap = data[2] << 24 | data[3] << 16 | data[4] << 8 | data[5]; - /*cycle_count*/ - bi->cycle_cnt = data[6]; - /*soc*/ - bi->permille = data[7] << 8 | data[8]; - /*pre_gauge_timer*/ - bi->pre_gauge_timer = bi->gauge_timer = (data[9] << 8) + data[10]; - - return 0; -} - -/*return value; 1-> initialized, 0-> no initial value*/ -static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi) -{ - u8 data[15] = {0}; - int ret = 0; - - if (rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15) < 0) { - pr_err("%s: check initial value error\n", __func__); - return 0; - } else { - ret = IsCrc16Good(data, 15); - } - RTINFO("initial check = %d\n", ret); - - return ret; -} - -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_CHANNELL, 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_INTEMPCH; - if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELL, data, 1) < 0) - pr_err("%s: failed to write channel\n", __func__); - - /* set the alert threshold value */ - irq_thres[MINVOLT2] = VALRTMIN2_VALUE; - irq_thres[VOLT_RLS] = VRLS_VALUE; - - bi->chg_cc_unuse = 0; - bi->dchg_cc_unuse = 0; - bi->pre_gauge_timer = 0; - bi->online = 1; - bi->batt_present = 1; - bi->status = bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING; - bi->health = POWER_SUPPLY_HEALTH_GOOD; - - bi->init_cap = true; - bi->avg_flag = true; - - bi->fcc_aging = rt5025_battery_param2[4].y; - bi->fcc = rt5025_battery_param2[4].y; - bi->dc = rt5025_battery_param2[4].y; - bi->rm = 0; - - bi->edv_cnt = 0; - bi->edv_flag = false; - bi->edv_detection = false; - bi->init_once = true; - - bi->tp_cnt = 0; - bi->tp_flag = false; - - bi->acc_dchg_cap = 0; - bi->cycle_cnt = 0; - bi->empty_edv = rt5025_battery_param2[4].x; - bi->edv_region = 0; - bi->soc1_lock_cnt = 0; - /*eoc fcc update function: initial variable. */ - bi->cal_eoc_fcc = 0; - bi->cal_soc_offset = 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->rm = bi->permille*bi->fcc_aging * 36 / 10; - } - - bi->update_time = NORMAL_POLL; - bi->device_suspend = false; - RTINFO("register initialized\n"); -} - -static void rt5025_soc_aging(struct rt5025_battery_info *bi) -{ - if (bi->cycle_cnt >= rt5025_battery_param2[3].x) { - bi->fcc_aging = bi->fcc_aging * (1000 - rt5025_battery_param2[3].y) / 1000; - bi->rm = bi->rm * (1000 - rt5025_battery_param2[3].y) / 1000; - bi->cycle_cnt -= rt5025_battery_param2[3].x; - } - RTINFO("fcc_aging=%d, rm=%d, cycle_cnt=%d\n", - bi->fcc_aging, bi->rm, bi->cycle_cnt); -} - -static void rt5025_temp_comp(struct rt5025_battery_info *bi) -{ - int i = 1; - int size; - int slope, const_term; - int delta_y, delta_x; - - size = 3; - while ((bi->ext_temp < rt5025_battery_param2[i].x) && - (i < (size - 1))) { - i++; - } - - delta_x = rt5025_battery_param2[i-1].x - rt5025_battery_param2[i].x; - delta_y = (rt5025_battery_param2[i-1].y - rt5025_battery_param2[i].y); - - slope = delta_y * 1000 / delta_x; - - const_term = (rt5025_battery_param2[i].y) - ((rt5025_battery_param2[i].x * slope) / 1000); - - if (bi->ext_temp >= rt5025_battery_param2[0].x) - bi->tempcmp = rt5025_battery_param2[0].y; - else if (bi->ext_temp <= rt5025_battery_param2[size-1].x) - bi->tempcmp = rt5025_battery_param2[size-1].y; - else - bi->tempcmp = (bi->ext_temp * slope) / 1000 + const_term; - - bi->fcc = bi->fcc_aging + bi->fcc_aging * bi->tempcmp / 1000; - if (bi->fcc >= (bi->dc*3>>1)) - bi->fcc = bi->dc*3>>1; - if (bi->fcc <= (bi->dc>>1)) - bi->fcc = bi->dc>>1; - bi->rm = bi->fcc * bi->permille * 36 / 10; - RTINFO("tempcmp=%d, ext_temp=%d, fcc=%d, rm=%d\n", - bi->tempcmp, bi->ext_temp, bi->fcc, bi->rm); - /*return; */ -} - -static void rt5025_soc_temp_comp(struct rt5025_battery_info *bi) -{ - RTINFO("soc->%d++\n", bi->soc); - bi->temp_range_0_5 = 0; - bi->temp_range_5_10 = 0; - bi->temp_range_10_15 = 0; - bi->temp_range_15_20 = 0; - bi->temp_range_20_30 = 0; - bi->temp_range_30_35 = 0; - bi->temp_range_35_40 = 0; - bi->temp_range_40_45 = 0; - bi->temp_range_45_50 = 0; - - if (bi->ext_temp < 50) - bi->temp_range_0_5 = 1; - else if (50 <= bi->ext_temp && bi->ext_temp < 100) - bi->temp_range_5_10 = 1; - else if (100 <= bi->ext_temp && bi->ext_temp < 150) - bi->temp_range_10_15 = 1; - else if (150 <= bi->ext_temp && bi->ext_temp < 200) - bi->temp_range_15_20 = 1; - else if (200 <= bi->ext_temp && bi->ext_temp <= 300) - bi->temp_range_20_30 = 1; - else if (300 < bi->ext_temp && bi->ext_temp <= 350) - bi->temp_range_30_35 = 1; - else if (350 < bi->ext_temp && bi->ext_temp <= 400) - bi->temp_range_35_40 = 1; - else if (400 < bi->ext_temp && bi->ext_temp <= 450) - bi->temp_range_40_45 = 1; - else if (450 < bi->ext_temp) - bi->temp_range_45_50 = 1; - - if ((bi->temp_range_0_5 == 1) && (bi->range_0_5_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 1; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_5_10 == 1) - && (bi->range_5_10_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 1; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_10_15 == 1) - && (bi->range_10_15_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 1; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_15_20 == 1) - && (bi->range_15_20_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 1; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_20_30 == 1) - && (bi->range_20_30_done == 0)) { - bi->fcc = bi->fcc_aging; - bi->rm = bi->fcc * bi->permille * 36 / 10; - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 1; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_30_35 == 1) - && (bi->range_30_35_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 1; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_35_40 == 1) - && (bi->range_35_40_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 1; - bi->range_40_45_done = 0; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_40_45 == 1) - && (bi->range_40_45_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 1; - bi->range_45_50_done = 0; - } else if ((bi->temp_range_45_50 == 1) - && (bi->range_45_50_done == 0)) { - rt5025_temp_comp(bi); - bi->range_0_5_done = 0; - bi->range_5_10_done = 0; - bi->range_10_15_done = 0; - bi->range_15_20_done = 0; - bi->range_20_30_done = 0; - bi->range_30_35_done = 0; - bi->range_35_40_done = 0; - bi->range_40_45_done = 0; - bi->range_45_50_done = 1; - } - RTINFO("soc->%d--\n", bi->soc); -} - -static void rt5025_update(struct rt5025_battery_info *bi) -{ - int batt_type = 1; - /* Update voltage */ - 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 */ - rt5025_get_timer(bi); - /* Update chg cc */ - rt5025_get_chg_cc(bi); - /* Update dchg cc */ - rt5025_get_dchg_cc(bi); - /* Update cycle count check */ - rt5025_cycle_count(bi); - /* Calculate cycle count */ - rt5025_soc_aging(bi); - /* calculate initial soc */ - if (bi->init_cap) { - rt5025_init_capacity(bi); - #if RT5025_CSV - pr_info("vcell,offset,current,timer,interval,QCHG,QDCHG,tp_cnt,tp_flag,edv_det,edv_cnt,edv_flag,soc,permille,RM,FCC,smooth_flag,acc_QD,cycle,update_time\n"); - #endif - } - - /* Relearn SOC */ - rt5025_soc_relearn_check(bi); - /* SOC_Temp_Comp*/ - rt5025_soc_temp_comp(bi); - /* Update SOC */ - rt5025_get_soc(bi); - - /* SOC Control Process */ - rt5025_soc_lock(bi); - rt5025_soc_irreversible(bi); - - if (bi->soc <= 99) - bi->last_tp = false; - - if (rt5025_battery_param1[0].x >= 4250) - batt_type = 0; - else if (rt5025_battery_param1[0].x >= 4100) - batt_type = 1; - - switch (batt_type) { - case 0: - if ((bi->vcell >= 4250) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)) - wake_lock(&bi->full_battery_wake_lock); - else - wake_unlock(&bi->full_battery_wake_lock); - break; - case 1: - default: - if ((bi->vcell >= 4100) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)) - wake_lock(&bi->full_battery_wake_lock); - else - wake_unlock(&bi->full_battery_wake_lock); - break; - } - - /* Update RTTF or RTTE */ - -#if TEMPERATURE_ALERT - if ((bi->max_temp_irq == false) && - (((irq_thres[MAXTEMP] * IRQ_THRES_UNIT) / 100 - bi->ain_volt) > irq_thres[TEMP_RLS])) { - rt5025_alert_setting(bi, MAXTEMP, true); - } else if ((bi->min_temp_irq == false) && - ((bi->ain_volt - (irq_thres[MINTEMP] * IRQ_THRES_UNIT) / 100) > irq_thres[TEMP_RLS])) { - rt5025_alert_setting(bi, MINTEMP, true); - } -#endif - -#if VOLTAGE_ALERT - if ((bi->min_volt2_irq == false) && - (bi->vcell > (bi->empty_edv + EDV_HYS))) - rt5025_alert_setting(bi, MINVOLT2, true); -#endif - bi->last_suspend = false; -#if RT5025_CSV - printk(KERN_INFO "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - bi->vcell, bi->curr_offset, bi->curr, bi->gauge_timer, - bi->time_interval, bi->chg_cc, 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 - RTINFO("[RT5025] update_time=%d\n", bi->update_time); - RTINFO("\n"); -#endif -} - -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); - - wake_lock(&bi->monitor_wake_lock); - rt5025_update(bi); - if (bi->soc != bi->last_soc) { - power_supply_changed(&bi->battery); - bi->last_soc = bi->soc; - } - - wake_unlock(&bi->monitor_wake_lock); - if (!bi->device_suspend) - schedule_delayed_work(&bi->monitor_work, bi->update_time*HZ); -} - -static enum power_supply_property rt5025_battery_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_TEMP_AMBIENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TECHNOLOGY, -#if 0 - POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, - POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, -#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_VBATSH, 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_VALRTMAX, &vmax_th, 1); - rt5025_write_reg(bi->client, RT5025_REG_VALRTMIN1, &vmin_th, 1); - - RTINFO("vmax_th=0x%02x, vmin_th=0x%02x\n", vmax_th, vmin_th); - return 0; -} - -static int rt5025_gauge_reginit(struct i2c_client *client) -{ - rt5025_reg_block_write(client, RT5025_REG_VALRTMAX, - 5, gauge_init_regval); - rt5025_reg_write(client, RT5025_REG_IRQCTL, 0x00); - rt5025_reg_read(client, RT5025_REG_IRQFLG); - RTINFO("\n"); - 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_channel_cc(bi, false); - //rt5025_update(bi);*/ - bi->device_suspend = true; - cancel_delayed_work_sync(&bi->monitor_work); - /* 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); - if (bi->status == POWER_SUPPLY_STATUS_CHARGING) - rt5025_alert_setting(bi, MAXVOLT, true); - else if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING) - rt5025_alert_setting(bi, MINVOLT1, true); - RTINFO("RM=%d\n", bi->rm); - return 0; -} - -static int rt5025_battery_resume(struct platform_device *pdev) -{ - struct rt5025_battery_info *bi = platform_get_drvdata(pdev); - - /*ktime_t now; - //struct timespec now = current_kernel_time(); - //struct timeval tv; - //long time_interval; - - //now = ktime_get(); - //tv = ktime_to_timeval(ktime_sub(now, bi->last_event)); - //RTINFO("Sleep time = %d\n",(u32)tv.tv_sec); - //bi->rm = bi->rm - ((u32)tv.tv_sec * SLEEP_CURRENT); - - //time_interval = now.tv_sec - bi->last_event.tv_sec; - //bi->rm = bi->rm - (time_interval * SLEEP_CURRENT); - //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm); - - //rt5025_channel_cc(bi, true);*/ - bi->last_suspend = true; - bi->device_suspend = false; - schedule_delayed_work(&bi->monitor_work, 0); - RTINFO("\n"); - return 0; -} - -static int rt5025_battery_remove(struct platform_device *pdev) -{ - struct rt5025_battery_info *bi = platform_get_drvdata(pdev); - - power_supply_unregister(&bi->battery); - cancel_delayed_work(&bi->monitor_work); - wake_lock_destroy(&bi->monitor_wake_lock); - RTINFO("\n"); - return 0; -} - -static int rt5025_battery_probe(struct platform_device *pdev) -{ - struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct rt5025_battery_info *bi; - int ret; - - bi = devm_kzalloc(&pdev->dev, sizeof(*bi), GFP_KERNEL); - if (!bi) - return -ENOMEM; - - bi->client = chip->i2c; - - INIT_DELAYED_WORK(&bi->monitor_work, rt5025_update_work); - - 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"); - wake_lock_init(&bi->smooth100_wake_lock, - WAKE_LOCK_SUSPEND, "smooth100_soc_wake_lock"); - wake_lock_init(&bi->smooth0_wake_lock, - WAKE_LOCK_SUSPEND, "smooth0_soc_wake_lock"); - wake_lock_init(&bi->full_battery_wake_lock, - WAKE_LOCK_SUSPEND, "full_battery_wake_lock"); -#if RT5025_TEST_WAKE_LOCK - wake_lock_init(&bi->test_wake_lock, WAKE_LOCK_SUSPEND, "rt-test"); -#endif - mutex_init(&bi->status_change_lock); - /* Write trimed data */ - /*rt5025_pretrim(client);*/ - rt5025_gauge_reginit(bi->client); - /* enable channel */ - rt5025_register_init(bi); - /* enable gauge IRQ */ - rt5025_alert_init(bi); - - /* register callback functions */ - /* - chip->cb.rt5025_gauge_irq_handler = rt5025_irq_handler; - chip->cb.rt5025_gauge_set_status = rt5025_set_status; - chip->cb.rt5025_gauge_set_online = rt5025_set_online; - chip->cb.rt5025_gauge_suspend = rt5025_gauge_suspend; - chip->cb.rt5025_gauge_resume = rt5025_gauge_resume; - chip->cb.rt5025_gauge_remove = rt5025_gauge_remove; - rt5025_register_gauge_callbacks(&chip->cb); - */ - - platform_set_drvdata(pdev, bi); - - bi->battery.name = RT_BATT_NAME; - bi->battery.type = POWER_SUPPLY_TYPE_BATTERY; - bi->battery.set_property = rt5025_set_property; - bi->battery.get_property = rt5025_get_property; - bi->battery.properties = rt5025_battery_props; - bi->battery.num_properties = ARRAY_SIZE(rt5025_battery_props); - - ret = power_supply_register(&pdev->dev, &bi->battery); - if (ret) { - pr_err("[RT5025] power supply register failed\n"); - goto err_wake_lock; - } - - /*wake_lock(&bi->monitor_wake_lock);*/ -#if RT5025_TEST_WAKE_LOCK - wake_lock(&bi->test_wake_lock); -#endif - schedule_delayed_work(&bi->monitor_work, INIT_POLL*HZ); - chip->battery_info = bi; - - pr_info("rt5025-battery driver is successfully loaded\n"); - - return 0; -err_wake_lock: - wake_lock_destroy(&bi->monitor_wake_lock); - return ret; -} - -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) { - /*d. FCC update limitation +/-3%; 2013/12/27 - //bi->fcc_aging = bi->cal_fcc/3600 - (bi->fcc -bi->fcc_aging);*/ - u16 fcc_new = 0; - - fcc_new = bi->cal_fcc / 3600 - (bi->fcc - bi->fcc_aging); - if (fcc_new > ((bi->fcc_aging * 103) / 100)) - bi->fcc_aging = (bi->fcc_aging * 103) / 100; - else if (fcc_new < ((bi->fcc_aging * 97) / 100)) - bi->fcc_aging = (bi->fcc_aging * 97) / 100; - else - bi->fcc_aging = fcc_new; - - RTINFO("bi->cal_fcc=%d\n", bi->cal_fcc); - } - rt5025_battery_parameter_backup(bi); - RTINFO("\n"); -} - -static struct of_device_id rt_match_table[] = { - { .compatible = "rt,rt5025-battery",}, - {}, -}; - -static struct platform_driver rt5025_battery_driver = { - .driver = { - .name = RT5025_DEV_NAME "-battery", - .owner = THIS_MODULE, - .of_match_table = rt_match_table, - }, - .probe = rt5025_battery_probe, - .remove = rt5025_battery_remove, - .shutdown = rt5025_battery_shutdown, - .suspend = rt5025_battery_suspend, - .resume = rt5025_battery_resume, -}; - -static int rt5025_battery_init(void) -{ - return platform_driver_register(&rt5025_battery_driver); -} -fs_initcall_sync(rt5025_battery_init); - -static void rt5025_battery_exit(void) -{ - platform_driver_unregister(&rt5025_battery_driver); -} -module_exit(rt5025_battery_exit); - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com>"); -MODULE_DESCRIPTION("battery gauge driver for RT5025"); -MODULE_ALIAS("platform:" RT5025_DEV_NAME "-battery"); -MODULE_VERSION(RT5025_DRV_VER); diff --git a/drivers/power/rt5025-charger.c b/drivers/power/rt5025-charger.c deleted file mode 100755 index d7aee678401a..000000000000 --- a/drivers/power/rt5025-charger.c +++ /dev/null @@ -1,1224 +0,0 @@ -/* - * drivers/power/rt5025-charger.c - * Driver for Richtek RT5025 PMIC Charger driver - * - * Copyright (C) 2014 Richtek Technology Corp. - * cy_huang <cy_huang@richtek.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/version.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/of.h> -#include <linux/power_supply.h> -#include <linux/workqueue.h> -#include <linux/delay.h> -#ifdef CONFIG_HAS_EARLYSUSPEND -#include <linux/earlysuspend.h> -#endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */ - -#include <linux/mfd/rt5025.h> -#include <linux/power/rt5025-charger.h> -#ifdef CONFIG_RT_POWER -#include <linux/power/rt-power.h> -#endif /* #ifdef CONFIG_RT_POWER */ - -static unsigned char chg_init_regval[] = { - 0x12, /*REG 0x02*/ - 0x8C, /*REG 0x03*/ - 0x03, /*REG 0x04*/ - 0x20, /*REG 0x05*/ - 0x14, /*REG 0x06*/ - 0x40, /*REG 0x07*/ - 0xDA, /*REG 0x30*/ - 0xDA, /*REG 0x32*/ - 0x43, /*REG 0x34*/ -}; - -static char *rtdef_chg_name = "rt-charger"; - -static char *rt_charger_supply_list[] = { - "none", -}; - -static enum power_supply_property rt_charger_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_CHARGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, - POWER_SUPPLY_PROP_CURRENT_AVG, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, -}; - -static void rt_charger_set_batt_status(struct rt5025_charger_info *ci); - -static int rt_charger_get_property(struct power_supply *psy, enum power_supply_property psp, \ - union power_supply_propval *val) -{ - struct rt5025_charger_info *ci = dev_get_drvdata(psy->dev->parent); - int ret = 0; - int regval = 0; - #ifdef CONFIG_BATTERY_RT5025 - struct power_supply *bat_psy = power_supply_get_by_name(RT_BATT_NAME); - union power_supply_propval pval; - #endif - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = ci->online; - break; - case POWER_SUPPLY_PROP_STATUS: - val->intval = ci->chg_status; - break; - case POWER_SUPPLY_PROP_PRESENT: - regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL7); - if (regval < 0) { - ret = -EINVAL; - } else { - if (regval & RT5025_CHGCEN_MASK) - val->intval = 1; - else - val->intval = 0; - } - break; - case POWER_SUPPLY_PROP_TEMP: - val->intval = 0; - #ifdef CONFIG_BATTERY_RT5025 - if (bat_psy) { - ret = bat_psy->get_property(bat_psy, POWER_SUPPLY_PROP_TEMP_AMBIENT,\ - &pval); - if (ret < 0) - dev_err(ci->dev, "get ic temp fail\n"); - else - val->intval = pval.intval; - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - break; - case POWER_SUPPLY_PROP_CHARGE_NOW: - val->intval = ci->charger_cable; - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = 2000; - break; - case POWER_SUPPLY_PROP_CURRENT_AVG: - regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL4); - if (regval < 0) { - ret = -EINVAL; - } else { - regval &= RT5025_CHGAICR_MASK; - regval >>= RT5025_CHGAICR_SHFT; - switch (regval) { - case 0: - val->intval = 100; - break; - case 1: - val->intval = 500; - break; - case 2: - val->intval = 1000; - break; - case 3: - val->intval = 0; - break; - default: - ret = -EINVAL; - break; - } - } - break; - case POWER_SUPPLY_PROP_CURRENT_NOW: - regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL4); - if (regval < 0) { - ret = -EINVAL; - } else { - regval &= RT5025_CHGICC_MASK; - regval >>= RT5025_CHGICC_SHFT; - val->intval = 500 + regval * 100; - } - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL3); - if (regval < 0) { - ret = -EINVAL; - } else { - regval &= RT5025_CHGCV_MASK; - regval >>= RT5025_CHGCV_SHFT; - val->intval = regval * 20 + 3500; - } - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = 3500; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = 4440; - break; - default: - ret = -EINVAL; - } - return ret; -} - -static int rt_charger_set_property(struct power_supply *psy, enum power_supply_property psp, \ - const union power_supply_propval *val) -{ - struct rt5025_charger_info *ci = dev_get_drvdata(psy->dev->parent); - int ret = 0; - int regval = 0; - RTINFO("prop = %d, val->intval = %d\n", psp, val->intval); - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - ci->online = val->intval; - if (ci->online) { - if (ci->te_en) { - ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGTEEN_MASK); - /*charger workaround*/ - mdelay(150); - /*turn on recharge irq enable*/ - chg_init_regval[8] |= RT5025_CHRCHGI_MASK; - rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN3, chg_init_regval[8]); - /*turn on chterm irq enable*/ - chg_init_regval[7] |= RT5025_CHTERMI_MASK; - rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN2, chg_init_regval[7]); - } - ci->chg_status = POWER_SUPPLY_STATUS_CHARGING; - rt_charger_set_batt_status(ci); - } else { - if (ci->te_en) { - ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGTEEN_MASK); - /*charger workaround*/ - /*turn off chterm irq enable*/ - chg_init_regval[7] &= ~RT5025_CHTERMI_MASK; - rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN2, chg_init_regval[7]); - /*turn off recharge irq enable*/ - chg_init_regval[8] &= ~RT5025_CHRCHGI_MASK; - rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN3, chg_init_regval[8]); - } - ci->chg_status = POWER_SUPPLY_STATUS_DISCHARGING; - rt_charger_set_batt_status(ci); - } - break; - case POWER_SUPPLY_PROP_PRESENT: - if (ci->online && val->intval) { - int icc; - int battemp_icc; - int inttemp_icc; - union power_supply_propval pval; - - if (ci->charger_cable == POWER_SUPPLY_TYPE_MAINS) - battemp_icc = inttemp_icc = (ci->screen_on ?\ - ci->screenon_icc:ci->acchg_icc); - else if (ci->charger_cable == POWER_SUPPLY_TYPE_USB_DCP) - battemp_icc = inttemp_icc = (ci->screen_on ?\ - ci->screenon_icc:ci->usbtachg_icc); - else - battemp_icc = inttemp_icc = (ci->screen_on ?\ - ci->screenon_icc:ci->usbchg_icc); - if (ci->battemp_region == RT5025_BATTEMP_COLD ||\ - ci->battemp_region == RT5025_BATTEMP_HOT) - battemp_icc = 10; - else if (ci->battemp_region == RT5025_BATTEMP_COOL ||\ - ci->battemp_region == RT5025_BATTEMP_WARM) - battemp_icc /= 2; - - if (ci->inttemp_region == RT5025_INTTEMP_WARM) - inttemp_icc -= 300; - else if (ci->inttemp_region == RT5025_INTTEMP_HOT) - inttemp_icc -= 800; - - if (inttemp_icc < 0) - inttemp_icc = 10; - - icc = min(battemp_icc, inttemp_icc); - pval.intval = icc; - ret = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &pval); - if (ret < 0) - dev_err(ci->dev, "set final icc fail\n"); - } - break; - case POWER_SUPPLY_PROP_CHARGE_NOW: - ci->charger_cable = val->intval; - break; - case POWER_SUPPLY_PROP_CURRENT_AVG: - if (0 < val->intval && val->intval <= 100) - regval = 0; - else if (val->intval <= 500) - regval = 1; - else if (val->intval <= 1000) - regval = 2; - else - regval = 3; - if (!ci->batabs) - ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL4, \ - RT5025_CHGAICR_MASK, regval << RT5025_CHGAICR_SHFT); - break; - case POWER_SUPPLY_PROP_CURRENT_NOW: - if (val->intval < 0) { - ci->otg_en = 1; - regval = -1; - #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN - ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_VBUSHZ_MASK); - if (ret < 0) - dev_err(ci->dev, "set vbus hz fail\n"); - #else - ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBCEN_MASK); - if (ret < 0) - dev_err(ci->dev, "shutdown chg buck fail\n"); - #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */ - } else if (val->intval == 0) { - ci->otg_en = 0; - regval = -1; - #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN - ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_VBUSHZ_MASK); - if (ret < 0) - dev_err(ci->dev, "clear vbus hz fail\n"); - #else - ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBCEN_MASK); - if (ret < 0) - dev_err(ci->dev, "turnon chg buck fail\n"); - #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */ - } else if (val->intval > 0 && val->intval < 500) { - regval = 0; - } else if (val->intval > 2000) { - regval = 15; - } else { - regval = (val->intval - 500) / 100; - } - - if (regval >= 0) - ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, \ - regval<<RT5025_CHGICC_SHFT); - - if (val->intval > 0 && val->intval < 500) - rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK); - else - rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK); - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - if (val->intval < 3500) - regval = 0; - else if (val->intval > 4440) - regval = 0x3A; - else - regval = (val->intval - 3500) / 20; - ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, \ - regval << RT5025_CHGCV_SHFT); - break; - case POWER_SUPPLY_PROP_TEMP: - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - case POWER_SUPPLY_PROP_CURRENT_MAX: - case POWER_SUPPLY_PROP_STATUS: - default: - ret = -EINVAL; - } - return ret; -} - -#ifdef CONFIG_BATTERY_RT5025 -static int rt5025_set_tempalrt(struct rt5025_charger_info *ci) -{ - int rc = 0; - - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0x00); - if (ci->battemp_region == RT5025_BATTEMP_HOT) { - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[6]); - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMX_MASK, 0xFF); - } else if (ci->battemp_region == RT5025_BATTEMP_WARM) { - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[4]); - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[7]); - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF); - } else if (ci->battemp_region == RT5025_BATTEMP_NORMAL) { - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[2]); - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[5]); - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF); - } else if (ci->battemp_region == RT5025_BATTEMP_COOL) { - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[0]); - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[3]); - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF); - } else { - rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[1]); - rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\ - RT5025_TALRTMN_MASK, 0xFF); - } - return rc; -} -#endif /* #ifdef CONFIG_BATTERY_RT5025 */ - -static void rt_charger_set_batt_status(struct rt5025_charger_info *ci) -{ - #ifdef CONFIG_BATTERY_RT5025 - struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME); - union power_supply_propval pval; - int rc = 0; - - if (!psy) { - dev_err(ci->dev, "can't get battery supply\n"); - return; - } - pval.intval = ci->chg_status; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_STATUS, &pval); - if (rc < 0) - dev_err(ci->dev, "set battery status fail\n"); - power_supply_changed(psy); - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ -} - -static int rt_charger_check_battery_present(struct rt5025_charger_info *ci) -{ - int rc = 1; - #ifdef CONFIG_BATTERY_RT5025 - struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME); - union power_supply_propval pval; - - if (!psy) { - dev_err(ci->dev, "can't get battery supply\n"); - return rc; - } - rc = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval); - if (rc < 0) { - dev_err(ci->dev, "get battery voltage fail\n"); - } else { - if (pval.intval < (ci->chg_volt - 200) * 1000) - rc = 0; - else - rc = 1; - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - return rc; -} - -static void rt5025_batabs_irq_handler(void *info, int eventno) -{ - struct rt5025_charger_info *ci = info; - struct power_supply *psy = &ci->psy; - union power_supply_propval pval; - int rc = 0; - - #ifdef CONFIG_BATTERY_RT5025 - struct power_supply *bat_psy = power_supply_get_by_name(RT_BATT_NAME); - - pval.intval = 0; - if (!bat_psy) { - dev_err(ci->dev, "get rt-battery supply fail\n"); - } else { - rc = bat_psy->set_property(bat_psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - if (rc < 0) - dev_err(ci->dev, "set battery not present fail\n"); - power_supply_changed(bat_psy); - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - /*set aicr to disable*/ - pval.intval = 2000; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_AVG, &pval); - if (rc < 0) - dev_err(ci->dev, "set aicr to disable fail\n"); - /*set icc to 2000*/ - pval.intval = 2000; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &pval); - if (rc < 0) - dev_err(ci->dev, "set icc to 2000 fail\n"); - /*set online = 0, due to bat absense*/ - pval.intval = 0; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); - if (rc < 0) - dev_err(ci->dev, "set charger offline fail\n"); - ci->batabs = 1; - ci->te_en = 0; -} - -static void rt5025_acin_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_RT_POWER - struct rt5025_charger_info *ci = info; - #ifndef CONFIG_RT_SUPPORT_ACUSB_DUALIN - struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME); - #else - struct power_supply *psy = power_supply_get_by_name(RT_AC_NAME); - #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */ - union power_supply_propval pval; - int rc = 0; - - if (!psy) { - dev_err(ci->dev, "could not get psy supply\n"); - return; - } - pval.intval = 1; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); - if (rc < 0) - dev_err(ci->dev, "set ac online fail\n"); - power_supply_changed(psy); - dev_info(ci->dev, "%s\n", __func__); - #endif /* #ifdef CONFIG_RT_POWER */ -} - -static void rt5025_acout_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_RT_POWER - struct rt5025_charger_info *ci = info; - #ifndef CONFIG_RT_SUPPORT_ACUSB_DUALIN - struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME); - #else - struct power_supply *psy = power_supply_get_by_name(RT_AC_NAME); - #endif /* ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */ - union power_supply_propval pval; - int rc = 0; - - if (!psy) { - dev_err(ci->dev, "could not get rt-usb supply\n"); - return; - } - pval.intval = 0; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); - if (rc < 0) - dev_err(ci->dev, "set ac offline fail\n"); - power_supply_changed(psy); - dev_info(ci->dev, "%s\n", __func__); - #endif /* #ifdef CONFIG_RT_POWER */ -} - -static void rt5025_usbin_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_RT_POWER - struct rt5025_charger_info *ci = info; - struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME); - union power_supply_propval pval; - int rc = 0; - - if (!psy) { - dev_err(ci->dev, "could not get rt-usb supply\n"); - return; - } - if (!ci->otg_en) { - pval.intval = 1; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); - if (rc < 0) - dev_err(ci->dev, "set ac online fail\n"); - power_supply_changed(psy); - } - dev_info(ci->dev, "%s\n", __func__); - #endif /* #ifdef CONFIG_RT_POWER */ -} - -static void rt5025_usbout_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_RT_POWER - struct rt5025_charger_info *ci = info; - struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME); - union power_supply_propval pval; - int rc = 0; - - if (!psy) { - dev_err(ci->dev, "could not get rt-usb supply\n"); - return; - } - if (!ci->otg_en) { - pval.intval = 0; - rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); - if (rc < 0) - dev_err(ci->dev, "set ac offline fail\n"); - power_supply_changed(psy); - } - dev_info(ci->dev, "%s\n", __func__); - #endif /* #ifdef CONFIG_RT_POWER */ -} - -static void rt5025_talrtmax_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_BATTERY_RT5025 - struct rt5025_charger_info *ci = info; - union power_supply_propval pval; - int rc = 0; - - switch (ci->battemp_region) { - case RT5025_BATTEMP_COLD: - dev_warn(ci->dev, "cold than cold???\n"); - break; - case RT5025_BATTEMP_COOL: - dev_info(ci->dev, "cool-> cold\n"); - ci->battemp_region = RT5025_BATTEMP_COLD; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_NORMAL: - dev_info(ci->dev, "normal-> cool\n"); - ci->battemp_region = RT5025_BATTEMP_COOL; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_WARM: - dev_info(ci->dev, "warm-> normal\n"); - ci->battemp_region = RT5025_BATTEMP_NORMAL; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_HOT: - dev_info(ci->dev, "hot-> warm\n"); - ci->battemp_region = RT5025_BATTEMP_WARM; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - default: - break; - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ -} - -static void rt5025_talrtmin_irq_handler(void *info, int eventno) -{ - #ifdef CONFIG_BATTERY_RT5025 - struct rt5025_charger_info *ci = info; - union power_supply_propval pval; - int rc = 0; - - switch (ci->battemp_region) { - case RT5025_BATTEMP_COLD: - dev_info(ci->dev, "cold-> cool\n"); - ci->battemp_region = RT5025_BATTEMP_COOL; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_COOL: - dev_info(ci->dev, "cool-> normal\n"); - ci->battemp_region = RT5025_BATTEMP_NORMAL; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_NORMAL: - dev_info(ci->dev, "normal-> warm\n"); - ci->battemp_region = RT5025_BATTEMP_WARM; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, - POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_WARM: - dev_info(ci->dev, "warm-> hot\n"); - ci->battemp_region = RT5025_BATTEMP_HOT; - rt5025_set_tempalrt(ci); - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\ - &pval); - if (rc < 0) - dev_err(ci->dev, "set present fail\n"); - break; - case RT5025_BATTEMP_HOT: - dev_warn(ci->dev, "hot than hot???\n"); - break; - default: - break; - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ -} - -static void rt5025_general_irq_handler(void *info, int eventno) -{ - struct rt5025_charger_info *ci = info; - - RTINFO("eventno=%02d\n", eventno); - switch (eventno) { - case CHGEVENT_CHRCHGI: - if (!ci->online) { - dev_warn(ci->dev, "recharge false alarm\n"); - } else { - union power_supply_propval pval; - - dev_info(ci->dev, "recharge occur\n"); - ci->chg_status = POWER_SUPPLY_STATUS_CHARGING; - pval.intval = ci->chg_volt; - rt_charger_set_batt_status(ci); - ci->psy.set_property(&ci->psy, - POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval); - } - break; - case CHGEVENT_CHTERMI: - if (!ci->online) { - dev_warn(ci->dev, "eoc false alarm\n"); - } else { - if (rt_charger_check_battery_present(ci)) { - union power_supply_propval pval; - - if (ci->chg_status == POWER_SUPPLY_STATUS_FULL) - return; - dev_info(ci->dev, "eoc really occur\n"); - ci->chg_status = POWER_SUPPLY_STATUS_FULL; - rt_charger_set_batt_status(ci); - pval.intval = ci->chg_volt-50; - ci->psy.set_property(&ci->psy, - POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval); - } else { - dev_info(ci->dev, "no battery condition\n"); - rt5025_batabs_irq_handler(ci, eventno); - } - } - break; - case CHGEVENT_TALRTMAX: - #ifdef CONFIG_BATTERY_RT5025 - rt5025_set_tempalrt(ci); - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - break; - case CHGEVENT_TALRTMIN: - #ifdef CONFIG_BATTERY_RT5025 - rt5025_set_tempalrt(ci); - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - break; - default: - break; - } -} - -static rt_irq_handler rt_chgirq_handler[CHGEVENT_MAX] = { - [CHGEVENT_TIMEOUT_CC] = rt5025_general_irq_handler, - [CHGEVENT_TIMEOUT_PC] = rt5025_general_irq_handler, - [CHGEVENT_CHVSREGI] = rt5025_general_irq_handler, - [CHGEVENT_CHTREGI] = rt5025_general_irq_handler, - [CHGEVENT_CHRCHGI] = rt5025_general_irq_handler, - [CHGEVENT_CHTERMI] = rt5025_general_irq_handler, - [CHGEVENT_CHBATOVI] = rt5025_general_irq_handler, - [CHGEVENT_CHGOODI_INUSB] = rt5025_general_irq_handler, - [CHGEVENT_CHBADI_INUSB] = rt5025_general_irq_handler, - [CHGEVENT_CHSLPI_INUSB] = rt5025_usbout_irq_handler, - [CHGEVENT_CHGOODI_INAC] = rt5025_general_irq_handler, - [CHGEVENT_CHBADI_INAC] = rt5025_general_irq_handler, - [CHGEVENT_CHSLPI_INAC] = rt5025_acout_irq_handler, - [CHGEVENT_BATABS] = rt5025_batabs_irq_handler, - [CHGEVENT_INUSB_PLUGIN] = rt5025_usbin_irq_handler, - [CHGEVENT_INUSBOVP] = rt5025_general_irq_handler, - [CHGEVENT_INAC_PLUGIN] = rt5025_acin_irq_handler, - [CHGEVENT_INACOVP] = rt5025_general_irq_handler, - [CHGEVENT_TALRTMIN] = rt5025_talrtmin_irq_handler, - [CHGEVENT_TALRTMAX] = rt5025_talrtmax_irq_handler, -}; - -void rt5025_charger_irq_handler(struct rt5025_charger_info *ci, unsigned int irqevent) -{ - int i; - #ifdef CONFIG_BATTERY_RT5025 - unsigned int enable_irq_event = (RT5025_TALRTMX_MASK | RT5025_TALRTMN_MASK)<<24 | \ - (chg_init_regval[6] << 16) | (chg_init_regval[7] << 8) | chg_init_regval[8]; - #else - unsigned int enable_irq_event = (chg_init_regval[6] << 16) - | (chg_init_regval[7] << 8)| \ - chg_init_regval[8]; - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - unsigned int final_irq_event = irqevent&enable_irq_event; - - /*charger workaround (TE+RECHARGE)*/ - if (final_irq_event & (1 << CHGEVENT_CHTERMI) && \ - final_irq_event & (1 << CHGEVENT_CHRCHGI)) - final_irq_event &= ~((1 << CHGEVENT_CHTERMI) | (1 << CHGEVENT_CHRCHGI)); - i = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL1); - if (i < 0) { - dev_err(ci->dev, "read CHGCTL1 fail\n"); - i = 0; - } - /*acin+acout*/ - if (final_irq_event & (1 << CHGEVENT_INAC_PLUGIN) && \ - final_irq_event & (1 << CHGEVENT_CHSLPI_INAC)) { - if (i & RT5025_ACUSABLE_MASK) - final_irq_event &= ~(1<<CHGEVENT_CHSLPI_INAC); - else - final_irq_event &= ~(1<<CHGEVENT_INAC_PLUGIN); - } - /*usbin+usbout*/ - if (final_irq_event & (1 << CHGEVENT_INUSB_PLUGIN) && \ - final_irq_event & (1 << CHGEVENT_CHSLPI_INUSB)) { - if (i & RT5025_USBUSABLE_MASK) - final_irq_event &= ~(1 << CHGEVENT_CHSLPI_INUSB); - else - final_irq_event &= ~(1 << CHGEVENT_INUSB_PLUGIN); - } - for (i = 0; i < CHGEVENT_MAX; i++) { - if ((final_irq_event & (1 << i)) && rt_chgirq_handler[i]) - rt_chgirq_handler[i](ci, i); - } -} -EXPORT_SYMBOL(rt5025_charger_irq_handler); - -static void rt5025_tempmon_work(struct work_struct *work) -{ - struct rt5025_charger_info *ci = container_of(work, \ - struct rt5025_charger_info, tempmon_work.work); - #ifdef CONFIG_BATTERY_RT5025 - struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME); - union power_supply_propval pval; - int inttemp_region; - #endif - - RTINFO("\n"); - #ifdef CONFIG_BATTERY_RT5025 - if (!psy) { - dev_err(ci->dev, "could not get rt-battery psy\n"); - return; - } - if (!ci->init_once) { - /*battemp init*/ - int i = 0; - - pval.intval = 23; /* magic code*/ - psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &pval); - for (i = 3; i >= 0; i--) - if (pval.intval > ci->temp[i]) - break; - if (i == 3) - ci->battemp_region = RT5025_BATTEMP_HOT; - else if (i == 2) - ci->battemp_region = RT5025_BATTEMP_WARM; - else if (i == 1) - ci->battemp_region = RT5025_BATTEMP_NORMAL; - else if (i == 0) - ci->battemp_region = RT5025_BATTEMP_COOL; - else - ci->battemp_region = RT5025_BATTEMP_COLD; - rt5025_set_tempalrt(ci); - ci->init_once = 1; - } - - psy->get_property(psy, POWER_SUPPLY_PROP_TEMP_AMBIENT, &pval); - if (pval.intval > 1000) - inttemp_region = RT5025_INTTEMP_HOT; - else if (pval.intval > 750) - inttemp_region = RT5025_INTTEMP_WARM; - else - inttemp_region = RT5025_INTTEMP_NORMAL; - - if (inttemp_region != ci->inttemp_region) { - ci->inttemp_region = inttemp_region; - pval.intval = 1; - rt_charger_set_property(&ci->psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - } - #endif /* #ifdef CONFIG_BATTERY_RT5025 */ - if (!ci->suspend) - schedule_delayed_work(&ci->tempmon_work, 5*HZ); -} - -static int rt5025_charger_reginit(struct i2c_client *client) -{ - rt5025_reg_block_write(client, RT5025_REG_CHGCTL2, 6, chg_init_regval); - /*set all to be masked*/ - rt5025_reg_write(client, RT5025_REG_IRQEN1, 0x00); - rt5025_reg_write(client, RT5025_REG_IRQEN2, 0x00); - rt5025_reg_write(client, RT5025_REG_IRQEN3, 0x00); - /*just clear the old irq event*/ - rt5025_reg_read(client, RT5025_REG_IRQSTAT1); - rt5025_reg_read(client, RT5025_REG_IRQSTAT2); - rt5025_reg_read(client, RT5025_REG_IRQSTAT3); - /*set enable irqs as we want*/ - rt5025_reg_write(client, RT5025_REG_IRQEN1, chg_init_regval[6]); - rt5025_reg_write(client, RT5025_REG_IRQEN2, chg_init_regval[7]); - rt5025_reg_write(client, RT5025_REG_IRQEN3, chg_init_regval[8]); - RTINFO("\n"); - return 0; -} - -static int rt_parse_dt(struct rt5025_charger_info *ci, struct device *dev) -{ - #ifdef CONFIG_OF - struct device_node *np = dev->of_node; - u32 val; - - if (of_property_read_bool(np, "rt,te_en")) - ci->te_en = 1; - - if (of_property_read_u32(np, "rt,iprec", &val)) { - dev_info(dev, "no iprec property, use default value\n"); - } else{ - if (val > RT5025_IPREC_MAX) - val = RT5025_IPREC_MAX; - chg_init_regval[4] &= (~RT5025_CHGIPREC_MASK); - chg_init_regval[4] |= (val << RT5025_CHGIPREC_SHFT); - } - - if (of_property_read_u32(np, "rt,ieoc", &val)) { - dev_info(dev, "no ieoc property, use the default value\n"); - } else { - if (val > RT5025_IEOC_MAX) - val = RT5025_IEOC_MAX; - chg_init_regval[4] &= (~RT5025_CHGIEOC_MASK); - chg_init_regval[4] |= (val << RT5025_CHGIEOC_SHFT); - } - - if (of_property_read_u32(np, "rt,vprec", &val)) { - dev_info(dev, "no vprec property, use the default value\n"); - } else { - if (val > RT5025_VPREC_MAX) - val = RT5025_VPREC_MAX; - chg_init_regval[4] &= (~RT5025_CHGVPREC_MASK); - chg_init_regval[4] |= (val << RT5025_CHGVPREC_SHFT); - } - - if (of_property_read_u32(np, "rt,vdpm", &val)) { - dev_info(dev, "no vdpm property, use the default value\n"); - } else { - if (val > RT5025_VDPM_MAX) - val = RT5025_VDPM_MAX; - chg_init_regval[3] &= (~RT5025_CHGVDPM_MASK); - chg_init_regval[3] |= (val << RT5025_CHGVDPM_SHFT); - } - - if (of_property_read_u32(np, "rt,chg_volt", &val)) { - dev_info(dev, "no chg_volt property, use 4200 as the default value\n"); - ci->chg_volt = 4200; - } else { - ci->chg_volt = val; - } - - if (of_property_read_u32(np, "rt,acchg_icc", &val)) { - dev_info(dev, "no acchg_icc property, use 2000 as the default value\n"); - ci->acchg_icc = 2000; - } else { - ci->acchg_icc = val; - } - - if (of_property_read_u32(np, "rt,usbtachg_icc", &val)) { - dev_info(dev, "no usbtachg_icc property, use 2000 as the default value\n"); - ci->usbtachg_icc = 2000; - } else { - ci->usbtachg_icc = val; - } - - if (of_property_read_u32(np, "rt,usbchg_icc", &val)) { - dev_info(dev, "no usbchg_icc property, use 500 as the default value\n"); - ci->usbchg_icc = 500; - } else { - ci->usbchg_icc = val; - } - - if (of_property_read_u32(np, "rt,screenon_icc", &val)) { - dev_info(dev, "no screenon_icc property, use 500 as the default value\n"); - ci->screenon_icc = 500; - } else { - ci->screenon_icc = val; - } - - if (of_property_read_bool(np, "rt,screenon_adjust")) { - ci->screenon_adjust = 1; - ci->screen_on = 1; - } - - if (of_property_read_u32_array(np, "rt,temp", - ci->temp, 4)) { - dev_info(dev, "no temperature property, use default value\n"); - ci->temp[0] = 0; - ci->temp[1] = 150; - ci->temp[2] = 500; - ci->temp[3] = 600; - } - - if (of_property_read_u32_array(np, "rt,temp_scalar", - ci->temp_scalar, 8)) { - dev_info(dev, "no temp_scalar property, use default value\n"); - ci->temp_scalar[0] = 0x30; - ci->temp_scalar[1] = 0x2B; - ci->temp_scalar[2] = 0x28; - ci->temp_scalar[3] = 0x22; - ci->temp_scalar[4] = 0x15; - ci->temp_scalar[5] = 0x10; - ci->temp_scalar[6] = 0x10; - ci->temp_scalar[7] = 0x0D; - } - #endif /* #ifdef CONFIG_OF */ - rt5025_charger_reginit(ci->i2c); - RTINFO("\n"); - return 0; -} - -static int rt_parse_pdata(struct rt5025_charger_info *ci, struct device *dev) -{ - struct rt5025_charger_data *pdata = dev->platform_data; - int i = 0; - - if (pdata->te_en) - ci->te_en = 1; - - chg_init_regval[4] &= (~RT5025_CHGIPREC_MASK); - chg_init_regval[4] |= (pdata->iprec << RT5025_CHGIPREC_SHFT); - - chg_init_regval[4] &= (~RT5025_CHGIEOC_MASK); - chg_init_regval[4] |= (pdata->ieoc << RT5025_CHGIEOC_SHFT); - - chg_init_regval[4] &= (~RT5025_CHGVPREC_MASK); - chg_init_regval[4] |= (pdata->vprec << RT5025_CHGVPREC_SHFT); - - chg_init_regval[3] &= (~RT5025_CHGVDPM_MASK); - chg_init_regval[3] |= (pdata->vdpm << RT5025_CHGVDPM_SHFT); - - ci->chg_volt = pdata->chg_volt; - ci->acchg_icc = pdata->acchg_icc; - ci->usbtachg_icc = pdata->usbtachg_icc; - ci->usbchg_icc = pdata->usbchg_icc; - ci->screenon_icc = pdata->screenon_icc; - if (pdata->screenon_adjust) { - ci->screenon_adjust = 1; - /*default probe screen will on*/ - ci->screen_on = 1; - } - for (i = 0; i < 4; i++) - ci->temp[i] = pdata->temp[i]; - for (i = 0; i < 8; i++) - ci->temp_scalar[i] = pdata->temp_scalar[i]; - rt5025_charger_reginit(ci->i2c); - RTINFO("\n"); - return 0; -} - -#ifdef CONFIG_RT_POWER -static struct platform_device rt_power_dev = { - .name = "rt-power", - .id = -1, -}; -#endif /* #ifdef CONFIG_RT_POWER */ - -#ifdef CONFIG_HAS_EARLYSUSPEND -static void rt5025_charger_earlysuspend(struct early_suspend *handler) -{ - struct rt5025_charger_info *ci = container_of(handler, \ - struct rt5025_charger_info, early_suspend); - union power_supply_propval pval; - int rc = 0; - - if (ci->screenon_adjust) { - ci->screen_on = 0; - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - if (rc < 0) - dev_err(ci->dev, "set charger present property fail\n"); - } -} - -static void rt5025_charger_earlyresume(struct early_suspend *handler) -{ - struct rt5025_charger_info *ci = container_of(handler, \ - struct rt5025_charger_info, early_suspend); - union power_supply_propval pval; - int rc = 0; - - if (ci->screenon_adjust) { - ci->screen_on = 1; - pval.intval = 1; - rc = ci->psy.set_property(&ci->psy, - POWER_SUPPLY_PROP_PRESENT, &pval); - if (rc < 0) - dev_err(ci->dev, "set charger present property fail\n"); - } -} -#endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */ - -static int rt5025_charger_probe(struct platform_device *pdev) -{ - struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct rt5025_platform_data *pdata = - (pdev->dev.parent)->platform_data; - #ifdef CONFIG_RT_POWER - struct rt_power_data *rt_power_pdata; - #endif /* #ifdef CONFIG_RT_POWER */ - struct rt5025_charger_info *ci; - bool use_dt = pdev->dev.of_node; - int ret = 0; - - ci = devm_kzalloc(chip->dev, sizeof(struct rt5025_charger_info), GFP_KERNEL); - if (!ci) - return -ENOMEM; - - ci->i2c = chip->i2c; - ci->dev = &pdev->dev; - ci->chg_status = POWER_SUPPLY_STATUS_DISCHARGING; - ci->battemp_region = RT5025_BATTEMP_NORMAL; - ci->inttemp_region = RT5025_INTTEMP_NORMAL; - #ifdef CONFIG_RT_JEITA_REMOVE - ci->init_once = 1; - #endif /* #ifdef RT_JEITA_REMOVE */ - - if (use_dt) { - rt_parse_dt(ci, &pdev->dev); - } else { - if (!pdata) { - ret = -EINVAL; - goto out_dev; - } - pdev->dev.platform_data = pdata->chg_pdata; - rt_parse_pdata(ci, &pdev->dev); - } - INIT_DELAYED_WORK(&ci->tempmon_work, rt5025_tempmon_work); - - platform_set_drvdata(pdev, ci); - /*power supply register*/ - ci->psy.name = rtdef_chg_name; - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) - ci->psy.type = POWER_SUPPLY_TYPE_UNKNOWN; - #else - ci->psy.type = -1; - #endif /* #ifdef (LINUX_VERSION_CODE */ - ci->psy.supplied_to = rt_charger_supply_list; - ci->psy.properties = rt_charger_props; - ci->psy.num_properties = ARRAY_SIZE(rt_charger_props); - ci->psy.get_property = rt_charger_get_property; - ci->psy.set_property = rt_charger_set_property; - ret = power_supply_register(&pdev->dev, &ci->psy); - if (ret < 0) { - dev_err(&pdev->dev, "couldn't create power supply for rt-charger\n"); - goto out_dev; - } - - #ifdef CONFIG_HAS_EARLYSUSPEND - ci->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1; - ci->early_suspend.suspend = rt5025_charger_earlysuspend; - ci->early_suspend.resume = rt5025_charger_earlyresume; - register_early_suspend(&ci->early_suspend); - #endif /* CONFIG_HAS_EARLYSUSPEND */ - - #ifdef CONFIG_RT_POWER - rt_power_pdata = devm_kzalloc(&pdev->dev, - sizeof(*rt_power_pdata), GFP_KERNEL); - if (!rt_power_pdata) { - ret = -ENOMEM; - goto out_psy; - } - rt_power_pdata->chg_volt = ci->chg_volt; - rt_power_pdata->acchg_icc = ci->acchg_icc; - rt_power_pdata->usbtachg_icc = ci->usbtachg_icc; - rt_power_pdata->usbchg_icc = ci->usbchg_icc; - - rt_power_dev.dev.platform_data = rt_power_pdata; - rt_power_dev.dev.parent = &pdev->dev; - ret = platform_device_register(&rt_power_dev); - if (ret < 0) - goto out_psy; - #endif /* #ifdef CONFIG_RT_POWER */ - - chip->charger_info = ci; - schedule_delayed_work(&ci->tempmon_work, 1*HZ); - dev_info(&pdev->dev, "driver successfully loaded\n"); - return 0; -#ifdef CONFIG_RT_POWER -out_psy: -#endif /* #ifdef CONFIG_RT_POWER */ - #ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&ci->early_suspend); - #endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */ - power_supply_unregister(&ci->psy); -out_dev: - return ret; -} - -static int rt5025_charger_remove(struct platform_device *pdev) -{ - struct rt5025_charger_info *ci = platform_get_drvdata(pdev); - - power_supply_unregister(&ci->psy); - #ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&ci->early_suspend); - #endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */ - #ifdef CONFIG_RT_POWER - platform_device_unregister(&rt_power_dev); - #endif /* #ifdef CONFIG_RT_POWER */ - return 0; -} - -static int rt5025_charger_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct rt5025_charger_info *ci = platform_get_drvdata(pdev); - union power_supply_propval pval; - - ci->suspend = 1; - cancel_delayed_work_sync(&ci->tempmon_work); - /*force inttemp to normal temp*/ - ci->inttemp_region = RT5025_INTTEMP_NORMAL; - pval.intval = 1; - rt_charger_set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT, &pval); - return 0; -} - -static int rt5025_charger_resume(struct platform_device *pdev) -{ - struct rt5025_charger_info *ci = platform_get_drvdata(pdev); - - ci->suspend = 0; - schedule_delayed_work(&ci->tempmon_work, msecs_to_jiffies(50)); - return 0; -} - -static const struct of_device_id rt_match_table[] = { - { .compatible = "rt,rt5025-charger",}, - {}, -}; - -static struct platform_driver rt5025_charger_driver = { - .driver = { - .name = RT5025_DEV_NAME "-charger", - .owner = THIS_MODULE, - .of_match_table = rt_match_table, - }, - .probe = rt5025_charger_probe, - .remove = rt5025_charger_remove, - .suspend = rt5025_charger_suspend, - .resume = rt5025_charger_resume, -}; - -static int rt5025_charger_init(void) -{ - return platform_driver_register(&rt5025_charger_driver); -} -fs_initcall_sync(rt5025_charger_init); - -static void rt5025_charger_exit(void) -{ - platform_driver_unregister(&rt5025_charger_driver); -} - -module_exit(rt5025_charger_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>"); -MODULE_DESCRIPTION("Charger driver for RT5025"); -MODULE_ALIAS("platform:"RT5025_DEV_NAME "-charger"); -MODULE_VERSION(RT5025_DRV_VER); diff --git a/drivers/power/rt5025-power.c b/drivers/power/rt5025-power.c deleted file mode 100755 index 6d654d7bbe38..000000000000 --- a/drivers/power/rt5025-power.c +++ /dev/null @@ -1,566 +0,0 @@ -/* drivers/power/rt5025-power.c - * I2C Driver for Richtek RT5025 PMIC - * Multi function device - multi functional baseband PMIC Power part - * - * Copyright (C) 2013 - * Author: CY Huang <cy_huang@richtek.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/power_supply.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/version.h> -#include <linux/slab.h> -#include <linux/workqueue.h> -#include <linux/mfd/rt5025.h> -#include <linux/power/rt5025-power.h> -#include <linux/delay.h> - -static struct platform_device *dev_ptr; - - -static enum power_supply_property rt5025_adap_props[] = { - POWER_SUPPLY_PROP_ONLINE, -}; - -static char *rt5025_supply_list[] = { - "rt5025-battery", -}; - - -int rt5025_set_charging_current_switch (struct i2c_client *i2c, int onoff) -{ - int ret; - if (onoff) - ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK); - else - ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK); - return ret; -} -EXPORT_SYMBOL(rt5025_set_charging_current_switch); - -int rt5025_set_charging_buck(struct i2c_client *i2c, int onoff) -{ - int ret; - if (onoff) - ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - else - ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - return ret; -} -EXPORT_SYMBOL(rt5025_set_charging_buck); - -int rt5025_ext_set_charging_buck(int onoff) -{ - struct rt5025_power_info *pi = platform_get_drvdata(dev_ptr); - int ret; - if (onoff) - { - pi->otg_en = 0; - ret = rt5025_set_bits(pi->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - msleep(100); - } - else - { - pi->otg_en = 1; - ret = rt5025_clr_bits(pi->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - msleep(100); - } - return ret; -} -EXPORT_SYMBOL(rt5025_ext_set_charging_buck); - -int rt5025_charger_reset_and_reinit(struct rt5025_power_info *pi) -{ - struct rt5025_platform_data *pdata = pi->dev->parent->platform_data; - int ret; - - RTINFO("\n"); - - //do charger reset - ret = rt5025_reg_read(pi->i2c, RT5025_REG_CHGCTL4); - if (ret < 0) - return ret; - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL4, ret|RT5025_CHGRST_MASK); - mdelay(200); - - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL2, pdata->power_data->CHGControl2.val); - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL3, pdata->power_data->CHGControl3.val); - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL4, pdata->power_data->CHGControl4.val); - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL5, pdata->power_data->CHGControl5.val); - rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL6, pdata->power_data->CHGControl6.val); - //rt5025_reg_write(pi->i2c, RT5025_REG_CHGCTL7, pd->CHGControl7.val); - rt5025_assign_bits(pi->i2c, RT5025_REG_CHGCTL7, 0xEF, pdata->power_data->CHGControl7.val); - rt5025_reg_write(pi->i2c, 0xA9, 0x60 ); - return 0; -} -EXPORT_SYMBOL(rt5025_charger_reset_and_reinit); - -static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value) -{ - int ret = 0; - u8 data = 0; - - //ICC Setting - #if 0 - if (cur_value > 2000) - data |= 0x0f<<3; - else if (cur_value >= 500 && cur_value <= 2000) - { - data = (cur_value-500)/100; - data<<=3; - } - #endif - - //AICR Setting - if (cur_value > 1000) - data |= 0x03<<1; - else if (cur_value > 500 && cur_value <= 1000) - data |= 0x02<<1; - else if (cur_value > 100 && cur_value >= 500) - data |= 0x01<<1; - - rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGAICR_MASK, data); - return ret; -} - -static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_val) -{ - int ret = 0; - switch (new_val) - { - case 0x00: - #if 0 - rt5025_set_charging_current_switch(info->i2c, 1); - rt5025_set_charging_buck(info->i2c, 1); - #endif - info->chg_stat = 0x00; - #if 1 - if (info->chip->battery_info) - { - if (info->chg_term <= 1) - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING); - else if (info->chg_term == 2) - { - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL); - //info->chg_term = 0; - } - else if (info->chg_term > 2) - ; - } - #else - if (info->event_callback) - info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING); - #endif - break; - case 0x01: - //rt5025_set_charging_current_switch(info->i2c, 1); - info->chg_stat = 0x01; - #if 1 - if (info->chip->battery_info) - { - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING); - info->chg_term = 0; - } - #else - if (info->event_callback) - info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING); - #endif - break; - case 0x02: - #if 0 - rt5025_set_charging_current_switch(info->i2c, 0); - #endif - info->chg_stat = 0x02; - #if 1 - if (info->chip->battery_info) - { - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL); - info->chg_term = 0; - } - #else - if (info->event_callback) - info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_FULL); - #endif - break; - case 0x03: - #if 0 - rt5025_set_charging_buck(info->i2c, 0); - rt5025_set_charging_current_switch(info->i2c, 0); - #endif - info->chg_stat = 0x03; - #if 1 - if (info->chip->battery_info) - { - if (info->chg_term <= 1) - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING); - else if (info->chg_term == 2) - { - rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL); - //info->chg_term = 0; - } - else if (info->chg_term > 2) - ; - } - #else - if (info->event_callback) - info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING); - #endif - break; - default: - break; - } - return ret; -} - -#if 0 -int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info) -{ - if (info->event_callback) - info->event_callback->rt5025_gauge_irq_handler(); - return 0; -} -EXPORT_SYMBOL(rt5025_power_passirq_to_gauge); -#endif - -int rt5025_power_charge_detect(struct rt5025_power_info *info) -{ - int ret = 0; - unsigned char chgstatval = 0; - unsigned old_usbval, old_acval, old_chgval, new_usbval, new_acval, new_chgval; - - old_acval = info->ac_online; - old_usbval = info->usb_online; - old_chgval = info->chg_stat; - - mdelay(50); - - ret = rt5025_reg_read(info->i2c, RT5025_REG_CHGSTAT); - if (ret<0) - { - dev_err(info->dev, "read chg stat reg fail\n"); - return ret; - } - chgstatval = ret; - RTINFO("chgstat = 0x%02x\n", chgstatval); - - if (info->otg_en) - { - ret = rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - msleep(100); - } - - new_acval = (chgstatval&RT5025_CHG_ACONLINE)>>RT5025_CHG_ACSHIFT; - if (old_acval != new_acval) - { - info->ac_online = new_acval; - power_supply_changed(&info->ac); - } - - new_usbval = (info->otg_en? \ - 0:(chgstatval&RT5025_CHG_USBONLINE)>>RT5025_CHG_USBSHIFT); - if (old_usbval != new_usbval) - { - info->usb_online = new_usbval; - power_supply_changed(&info->usb); - } - - if (info->otg_en && new_acval == 0) - { - ret = rt5025_clr_bits(info->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK); - msleep(100); - } - - //if (old_acval != new_acval || old_usbval != new_usbval) - if (new_acval || new_usbval) - { - info->usb_cnt = 0; - schedule_delayed_work(&info->usb_detect_work, 0); //no delay - } - - new_chgval = (chgstatval&RT5025_CHGSTAT_MASK)>>RT5025_CHGSTAT_SHIFT; - - if (new_acval || new_usbval) - { - //if (old_chgval != new_chgval) - //{ - ret = rt5025_chgstat_changed(info, new_chgval); - //} - } - else - { - #if 0 - rt5025_set_charging_buck(info->i2c, 0); - rt5025_set_charging_current_switch(info->i2c, 0); - #endif - info->chg_stat = RT5025_CHGSTAT_UNKNOWN; - if (info->chip->jeita_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_DISCHARGING); - #else - if (info->event_callback) - info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING); - #endif - } - - return ret; -} -EXPORT_SYMBOL(rt5025_power_charge_detect); - -static int rt5025_adap_get_props(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct rt5025_power_info *info = dev_get_drvdata(psy->dev->parent); - switch(psp) - { - case POWER_SUPPLY_PROP_ONLINE: - if (psy->type == POWER_SUPPLY_TYPE_MAINS) - val->intval = info->ac_online; - else if (psy->type == POWER_SUPPLY_TYPE_USB) - val->intval = info->usb_online; - else - return -EINVAL; - break; - default: - return -EINVAL; - } - return 0; -} - - -extern int dwc_vbus_status(void); - - -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); - - RTINFO("rt5025: %s ++", __func__); - - mutex_lock(&pi->var_lock); - if (pi->ac_online) - { - rt5025_set_charging_current(pi->i2c, 2000); - rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_AC_ADAPTER); - pi->usb_cnt = 0; - } - else if (pi->usb_online) - { - 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, 2000); - rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_USB_TA); - RTINFO("rt5025: detect usb wall charger\n"); - break; - case 1: //normal USB - default: - rt5025_set_charging_current(pi->i2c, 2000); - rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NORMAL_USB); - RTINFO("rt5025: detect normal usb\n"); - break; - } - if (pi->usb_cnt++ < 60) - schedule_delayed_work(&pi->usb_detect_work, 1*HZ); - } - else - { - //default to prevent over current charging - rt5025_set_charging_current(pi->i2c, 500); - rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NO_CHARGE); - //reset usb_cnt; - pi->usb_cnt = 0; - } - mutex_unlock(&pi->var_lock); - - 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 - info->chg_stat = RT5025_CHGSTAT_UNKNOWN; - #if 0 - 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); - //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_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); - - return 0; -} - -static int __devinit rt5025_power_probe(struct platform_device *pdev) -{ - struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct rt5025_platform_data *pdata = chip->dev->platform_data; - struct rt5025_power_info *pi; - int ret = 0; - - pi = kzalloc(sizeof(*pi), GFP_KERNEL); - if (!pi) - return -ENOMEM; - - pi->i2c = chip->i2c; - pi->dev = &pdev->dev; - pi->chip = chip; - mutex_init(&pi->var_lock); - INIT_DELAYED_WORK(&pi->usb_detect_work, usb_detect_work_func); - - #if 0 - ret = rt5025_gauge_init(pi); - if (ret) - goto out; - #endif - - platform_set_drvdata(pdev, pi); - dev_ptr = pdev; - - pi->ac.name = "rt5025-dc"; - pi->ac.type = POWER_SUPPLY_TYPE_MAINS; - pi->ac.supplied_to = rt5025_supply_list; - pi->ac.properties = rt5025_adap_props; - pi->ac.num_properties = ARRAY_SIZE(rt5025_adap_props); - pi->ac.get_property = rt5025_adap_get_props; - ret = power_supply_register(&pdev->dev, &pi->ac); - if (ret) - goto out; - - pi->usb.name = "rt5025-usb"; - pi->usb.type = POWER_SUPPLY_TYPE_USB; - pi->ac.supplied_to = rt5025_supply_list; - pi->usb.properties = rt5025_adap_props; - pi->usb.num_properties = ARRAY_SIZE(rt5025_adap_props); - pi->usb.get_property = rt5025_adap_get_props; - ret = power_supply_register(&pdev->dev, &pi->usb); - if (ret) - goto out_usb; - - rt5025_init_charger(pi, pdata->power_data); - chip->power_info = pi; - - pr_info("rt5025-power driver is successfully loaded\n"); - - return ret; -out_usb: - power_supply_unregister(&pi->ac); -out: - kfree(pi); - - return ret; -} - -static int rt5025_power_suspend(struct platform_device *pdev, pm_message_t state) -{ - #if 0 - struct rt5025_power_info *pi = platform_get_drvdata(pdev); - - if (pi->event_callback) - pi->event_callback->rt5025_gauge_suspend(); - #endif - RTINFO("\n"); - return 0; -} - -static int rt5025_power_resume(struct platform_device *pdev) -{ - #if 0 - struct rt5025_power_info *pi = platform_get_drvdata(pdev); - - if (pi->event_callback) - pi->event_callback->rt5025_gauge_resume(); - #endif - RTINFO("\n"); - return 0; -} - -static int __devexit rt5025_power_remove(struct platform_device *pdev) -{ - struct rt5025_power_info *pi = platform_get_drvdata(pdev); - struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent); - - #if 0 - if (pi->event_callback) - pi->event_callback->rt5025_gauge_remove(); - #endif - power_supply_unregister(&pi->usb); - power_supply_unregister(&pi->ac); - chip->power_info = NULL; - kfree(pi); - RTINFO("\n"); - - return 0; -} - -static struct platform_driver rt5025_power_driver = -{ - .driver = { - .name = RT5025_DEVICE_NAME "-power", - .owner = THIS_MODULE, - }, - .probe = rt5025_power_probe, - .remove = __devexit_p(rt5025_power_remove), - .suspend = rt5025_power_suspend, - .resume = rt5025_power_resume, -}; - -static int __init rt5025_power_init(void) -{ - return platform_driver_register(&rt5025_power_driver); -} -late_initcall_sync(rt5025_power_init); - -static void __exit rt5025_power_exit(void) -{ - platform_driver_unregister(&rt5025_power_driver); -} -module_exit(rt5025_power_exit); - - -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); diff --git a/drivers/power/rt5025-swjeita.c b/drivers/power/rt5025-swjeita.c deleted file mode 100755 index 62041ad22cf2..000000000000 --- a/drivers/power/rt5025-swjeita.c +++ /dev/null @@ -1,494 +0,0 @@ -/* drivers/power/rt5025-swjeita.c - * swjeita Driver for Richtek RT5025 PMIC - * Multi function device - multi functional baseband PMIC swjeita part - * - * Copyright (C) 2013 - * Author: CY Huang <cy_huang@richtek.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/delay.h> - -#include <linux/mfd/rt5025.h> -#include <linux/power/rt5025-swjeita.h> - -#define TEMP_TOLERANCE 30 /*'c*10 gap for tolerance*/ - -static int rt5025_set_charging_cc_switch (struct i2c_client *i2c, int onoff) -{ - int ret; - - RTINFO("onoff = %d\n", onoff); - if (onoff) - ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK); - else - ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK); - return ret; -} - -static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value) -{ - int ret; - u8 data; - - RTINFO("current value = %d\n", cur_value); - if (cur_value < 500) - data = 0; - else if (cur_value > 2000) - data = 0xf << RT5025_CHGICC_SHIFT; - else - data = ((cur_value - 500) / 100) << RT5025_CHGICC_SHIFT; - - ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data); - - if (cur_value < 500) - rt5025_set_charging_cc_switch(i2c, 0); - else - rt5025_set_charging_cc_switch(i2c, 1); - - return ret; -} - -static int rt5025_set_charging_cv(struct i2c_client *i2c, int voltage) -{ - int ret; - u8 data; - - RTINFO("voltage = %d\n", voltage); - if (voltage < 3500) - data = 0; - else if (voltage > 4440) - data = 0x2f << RT5025_CHGCV_SHIFT; - else - data = ((voltage - 3500) / 20) << RT5025_CHGCV_SHIFT; - - ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, data); - return ret; -} - -static int rt5025_sel_external_temp_index(struct rt5025_swjeita_info *swji) -{ - int temp = swji->cur_temp; - int sect_index; - - RTINFO("\n"); - if (temp < swji->temp[0]) - sect_index = 0; - else if (temp >= swji->temp[0] && temp < swji->temp[1]) - sect_index = 1; - else if (temp >= swji->temp[1] && temp < swji->temp[2]) - sect_index = 2; - else if (temp >= swji->temp[2] && temp < swji->temp[3]) - sect_index = 3; - else if (temp >= swji->temp[3]) - sect_index = 4; - - RTINFO("sect_index = %d\n", sect_index); - return sect_index; -} - -static int rt5025_get_external_temp_index(struct rt5025_swjeita_info *swji) -{ - u8 data[2]; - long int temp; - int sect_index; - - RTINFO("\n"); - if (rt5025_reg_block_read(swji->i2c, RT5025_REG_AINH, 2, data) < 0) - pr_err("%s: failed to read ext_temp register\n", __func__); - - temp = (data[0] * 256 + data[1]) * 61 / 100; - temp = (temp * (-91738) + 81521000) / 100000; - - swji->cur_temp = temp; - - RTINFO("cur_section = %d, cur_temp = %d\n", swji->cur_section, swji->cur_temp); - - switch (swji->cur_section) { - case 0: - if (temp < swji->temp[0] + TEMP_TOLERANCE) - sect_index = rt5025_sel_external_temp_index(swji); - else - sect_index = swji->cur_section; - break; - case 1: - if (temp <= swji->temp[0] - TEMP_TOLERANCE || temp >= swji->temp[1] + TEMP_TOLERANCE) - sect_index = rt5025_sel_external_temp_index(swji); - else - sect_index = swji->cur_section; - break; - case 2: - if (temp <= swji->temp[1] - TEMP_TOLERANCE || temp >= swji->temp[2] + TEMP_TOLERANCE) - sect_index = rt5025_sel_external_temp_index(swji); - else - sect_index = swji->cur_section; - break; - case 3: - if (temp <= swji->temp[2] - TEMP_TOLERANCE || temp >= swji->temp[3] + TEMP_TOLERANCE) - sect_index = rt5025_sel_external_temp_index(swji); - else - sect_index = swji->cur_section; - break; - case 4: - if (temp <= swji->temp[3] - TEMP_TOLERANCE) - sect_index = rt5025_sel_external_temp_index(swji); - else - sect_index = swji->cur_section; - break; - default: - sect_index = swji->cur_section; - break; - } - RTINFO("sect_index = %d\n", sect_index); - return sect_index; -} - -static inline int rt5025_set_ainadc_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_AINEN_MASK); - else - ret = rt5025_clr_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_AINEN_MASK); - - 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; - - RTINFO("index = %d\n", index); - - switch (index) { - case 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[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[6]); - break; - } - - return ret; -} - -static int rt5025_exttemp_alert_switch(struct rt5025_swjeita_info *swji, int onoff) -{ - if (!onoff) { - rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK); - rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK); - } else { - switch (swji->cur_section) { - case 0: - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK); - break; - case 1: - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK); - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK); - break; - case 2: - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK); - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK); - break; - case 3: - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK); - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK); - break; - case 4: - rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK); - break; - } - } - - RTINFO("index=%d, onoff=%d\n", swji->cur_section, onoff); - return 0; -} - -int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_type) -{ - int sect_index; - int ret = 0; - - RTINFO("cable_type = %d\n", cable_type); - - rt5025_exttemp_alert_switch(swji, 0); - - sect_index = rt5025_get_external_temp_index(swji); - if (swji->cur_section != sect_index || swji->init_once == 0) { - rt5025_set_exttemp_alert(swji, sect_index); - swji->cur_section = sect_index; - swji->init_once = 1; - } - - switch (cable_type) { - case JEITA_NORMAL_USB: - 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]\ - - 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]\ - - swji->dec_current); - rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]); - break; - case JEITA_NO_CHARGE: - rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]); - rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]); - break; - } - swji->cur_cable = cable_type; - - rt5025_exttemp_alert_switch(swji, 1); - - return ret; -} -EXPORT_SYMBOL(rt5025_notify_charging_cable); - -int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char event) -{ - int ret = 0; - RTINFO("event = 0x%02x\n", event); - - if (event&(RT5025_TMXEN_MASK | RT5025_TMNEN_MASK)) - rt5025_notify_charging_cable(swji, swji->cur_cable); - - return ret; -} -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 = 0; - - RTINFO("%s ++", __func__); - rt5025_get_internal_temp(swji); - - #if 1 - switch (swji->cur_therm_region) { - case 0: - if (swji->cur_inttemp >= 820) - therm_region = 1; - else - therm_region = 0; - break; - case 1: - if (swji->cur_inttemp <= 780) - therm_region = 0; - else if (swji->cur_inttemp >= 1020) - therm_region = 2; - else - therm_region = 1; - break; - case 2: - if (swji->cur_inttemp <= 980) - therm_region = 1; - else - therm_region = 2; - break; - } - #else - 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; - #endif /* #if 1*/ - - 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 = 800; - break; - } - swji->cur_therm_region = therm_region; - rt5025_notify_charging_cable(swji, swji->cur_cable); - } - - if (!swji->suspend) - schedule_delayed_work(&swji->thermal_reg_work, 5*HZ); - - RTINFO("%s --", __func__); -} - -static int rt5025_swjeita_probe(struct platform_device *pdev) -{ - struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct rt5025_platform_data *pdata = chip->dev->platform_data; - struct rt5025_swjeita_info *swji; - int ret = 0; - - swji = kzalloc(sizeof(*swji), GFP_KERNEL); - if (!swji) - return -ENOMEM; - - #if 0 /* for debug pdata->jeita_data*/ - for (ret = 0; ret < 4; ret++) - RTINFO("jeita temp value %d\n", pdata->jeita_data->temp[ret]); - for (ret = 0; ret < 4; ret++) { - RTINFO("jeita temp_cc value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cc[ret][0], \ - pdata->jeita_data->temp_cc[ret][1], pdata->jeita_data->temp_cc[ret][2], \ - pdata->jeita_data->temp_cc[ret][3], pdata->jeita_data->temp_cc[ret][4]); - } - for (ret = 0; ret < 4; ret++) { - RTINFO("jeita temp_cv value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cv[ret][0], \ - 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 < 8; ret++) { - RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]); - } - ret = 0; - #endif /* #if 0 */ - - swji->i2c = chip->i2c; - swji->chip = chip; - swji->cur_section = 2; - /*initial as the normal temperature*/ - swji->cur_cable = JEITA_NO_CHARGE; - swji->temp = pdata->jeita_data->temp; - 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"); - return ret; -} - -static int rt5025_swjeita_remove(struct platform_device *pdev) -{ - struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev); - - swji->chip->jeita_info = NULL; - kfree(swji); - RTINFO("\n"); - return 0; -} - -static int rt5025_swjeita_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev); - - swji->suspend = 1; - cancel_delayed_work_sync(&swji->thermal_reg_work); - swji->cur_therm_region = swji->dec_current = 0; - rt5025_notify_charging_cable(swji, swji->cur_cable); - RTINFO("\n"); - return 0; -} - -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; -} - -static struct platform_driver rt5025_swjeita_driver = { - .driver = { - .name = RT5025_DEVICE_NAME "-swjeita", - .owner = THIS_MODULE, - }, - .probe = rt5025_swjeita_probe, - .remove = __devexit_p(rt5025_swjeita_remove), - .suspend = rt5025_swjeita_suspend, - .resume = rt5025_swjeita_resume, -}; - -static int rt5025_swjeita_init(void) -{ - return platform_driver_register(&rt5025_swjeita_driver); -} -module_init(rt5025_swjeita_init); - -static void rt5025_swjeita_exit(void) -{ - platform_driver_unregister(&rt5025_swjeita_driver); -} -module_exit(rt5025_swjeita_exit); - - -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); |