#if defined(CONFIG_X86_INTEL_SOFIA)
#include <linux/usb/phy-intel.h>
+#else
+#include <linux/power/rk_usbbc.h>
#endif
#include "rk818_battery.h"
#define DSOC_CHRG_FINISH_CURR 1100
#define SLP_CHRG_CURR 1000
#define SLP_DSOC_VOL_THRESD 3600
+/*if voltage is lower than this thresd,
+ we consider it as invalid
+ */
+#define INVALID_VOL_THRESD 2500
#define PWR_OFF_THRESD 3400
#define MIN_ZERO_ACCURACY 10 /*0.01%*/
struct delayed_work charge_check_work;
struct delayed_work usb_phy_delay_work;
struct delayed_work chrg_term_mode_switch_work;
- int charge_otg;
+ enum bc_port_type charge_otg;
int ma;
struct wake_lock resume_wake_lock;
} while (buf == 0);
- dev_info(di->dev, "update capacity :%d--remain_cap:%d\n",
+ dev_dbg(di->dev, "update capacity :%d--remain_cap:%d\n",
capacity, di->remain_capacity);
}
static int rk81x_bat_get_vol(struct rk81x_battery *di)
{
int ret;
- int voltage_now = 0;
+ int vol;
u8 buf;
int temp;
int val[3];
else
temp = val[2];
- voltage_now = di->voltage_k * temp / 1000 + di->voltage_b;
+ vol = di->voltage_k * temp / 1000 + di->voltage_b;
- return voltage_now;
+ return vol;
}
static bool is_rk81x_bat_relax_mode(struct rk81x_battery *di)
int ioffset;
u8 pcb_offset = 0;
u8 retry = 0;
- bool ret;
+ bool ret = true;
if ((di->chrg_status == CHARGE_FINISH) &&
(BASE_TO_MIN(di->power_on_base) >= 3) &&
for (retry = 0; retry < 5; retry++) {
adc_value = rk81x_bat_get_raw_adc_current(di);
if (!rk81x_chrg_online(di) || abs(adc_value) > 30) {
- dev_dbg(di->dev, "charger plugout\n");
+ dev_warn(di->dev, "charger plugout\n");
ret = true;
break;
}
ret = false;
break;
} else {
- dev_warn(di->dev, "ioffset cal failed\n");
+ dev_dbg(di->dev, "ioffset cal failed\n");
rk81x_bat_set_cal_offset(di, C0);
}
/*HW_ADP_TYPE_DUAL: det by rk818 and usb*/
} else if (rk81x_bat_support_adp_type(HW_ADP_TYPE_DUAL)) {
if ((buf & PLUG_IN_STS) != 0) {
- charger_type = dwc_otg_check_dpdm();
+ charger_type = dwc_otg_check_dpdm(0);
if (charger_type == 0)
charger_type = DC_CHARGER;
else
enum charger_type charger_type;
int usb_id, gadget_flag;
- usb_id = dwc_otg_check_dpdm();
+ usb_id = dwc_otg_check_dpdm(0);
switch (usb_id) {
case 0:
charger_type = NO_CHARGER;
return ma;
}
-
+#if 0
/*
* there is a timer inside rk81x to calc how long the battery is in charging
* state. rk81x will close PowerPath inside IC when timer reach, which will
rk81x_bat_write(di, CHRG_CTRL_REG3, &buf, 1);
dev_info(di->dev, "reset cccv charge timer\n");
}
+#endif
static void rk81x_bat_charger_init(struct rk81x_battery *di)
{
rk81x_bat_match_param(di, chrg_vol, chrg_ilim, chrg_cur);
finish_ma = rk81x_bat_select_finish_ma(di->fcc);
- rk81x_bat_init_chrg_timer(di);
+ /*rk81x_bat_init_chrg_timer(di);*/
rk81x_bat_read(di, THERMAL_REG, &thremal_reg, 1);
rk81x_bat_read(di, USB_CTRL_REG, &usb_ctrl_reg, 1);
chrg_ctrl_reg1 |= (CHRG_EN) | (di->chrg_v_lmt | di->chrg_i_cur);
chrg_ctrl_reg3 |= CHRG_TERM_DIG_SIGNAL;/* digital finish mode*/
+ chrg_ctrl_reg3 &= ~CHRG_TIMER_CCCV_EN;/*disable*/
+
chrg_ctrl_reg2 &= ~(0xc7);
chrg_ctrl_reg2 |= finish_ma | CHG_CCCV_6HOUR;
void rk81x_charge_disable_open_otg(struct rk81x_battery *di)
{
- int value = di->charge_otg;
+ enum bc_port_type event = di->charge_otg;
- if (value) {
+ switch (event) {
+ case USB_OTG_POWER_ON:
DBG("charge disable, enable OTG.\n");
rk818_set_bits(di->rk818, CHRG_CTRL_REG1, 1 << 7, 0 << 7);
rk818_set_bits(di->rk818, 0x23, 1 << 7, 1 << 7);
- } else {
+ break;
+
+ case USB_OTG_POWER_OFF:
DBG("charge enable, disable OTG.\n");
rk818_set_bits(di->rk818, 0x23, 1 << 7, 0 << 7);
rk818_set_bits(di->rk818, CHRG_CTRL_REG1, 1 << 7, 1 << 7);
+ break;
+
+ default:
+ break;
}
}
val = 0x30;
rk81x_bat_write(di, ADC_CTRL_REG, &val, 1);
- rk81x_bat_read(di, RK818_VB_MON_REG, &val, 1);
- if (val & PLUG_IN_STS)
- rk81x_bat_set_power_supply_state(di, USB_CHARGER);
rk81x_bat_gauge_enable(di);
/* get the volatege offset */
int voltage, voltage_old, voltage_now;
int i, rsoc;
int q_ocv, q_dead;
- int count_num, currentnow;
+ int count_num = 0;
+ int currentnow;
int ocv_soc, dead_soc;
int power_off_thresd = di->pdata->power_off_thresd;
static void rk81x_bat_emulator_dischrg(struct rk81x_battery *di)
{
- u32 temp, soc_time;
+ u32 temp, soc_time = 0;
unsigned long sec_unit;
if (!di->dischrg_emu_base)
*/
static void rk81x_bat_emulator_chrg(struct rk81x_battery *di)
{
- u32 soc_time, temp;
+ u32 soc_time = 0, temp;
int plus_soc;
unsigned long chrg_emu_sec;
static void rk81x_bat_finish_chrg(struct rk81x_battery *di)
{
unsigned long sec_finish;
- int soc_time, plus_soc;
+ int soc_time = 0, plus_soc;
int temp;
if (di->dsoc < 100) {
temp = di->fcc * 3600 / 100;
if (di->ac_online)
soc_time = temp / DSOC_CHRG_FINISH_CURR;
- else if (di->usb_online)
+ else
soc_time = temp / 450;
plus_soc = sec_finish / soc_time;
{
u32 *ocv_table = di->pdata->battery_ocv;
int delta_soc = di->rsoc - di->dsoc;
- int chrg_finish_vol = di->pdata->max_charger_voltagemV;
- if ((di->chrg_status == CHARGE_FINISH ||
- di->slp_chrg_status == CHARGE_FINISH) &&
- (di->voltage > chrg_finish_vol - 150)) {
+ if (di->chrg_status == CHARGE_FINISH ||
+ di->slp_chrg_status == CHARGE_FINISH) {
/*clear sleep charge status*/
di->slp_chrg_status = rk81x_bat_get_chrg_status(di);
di->chrg_emu_base = 0;
rk81x_bat_capacity_init(di, di->fcc);
rk81x_bat_capacity_init_post(di);
} else if ((di->ac_online == ONLINE && di->dsoc >= 90) &&
- ((di->current_avg > DSOC_CHRG_TERM_CURR) ||
- (di->voltage < ocv_table[18] + 20))) {
+ ((di->current_avg > DSOC_CHRG_TERM_CURR) ||
+ (di->voltage < ocv_table[18] + 20))) {
di->chrg_emu_base = 0;
di->chrg_normal_base = 0;
di->chrg_finish_base = 0;
static int rk81x_bat_sleep_dischrg(struct rk81x_battery *di)
{
- int delta_soc, temp_dsoc;
+ int delta_soc = 0;
+ int temp_dsoc;
unsigned long sleep_sec = di->suspend_time_sum;
int power_off_thresd = di->pdata->power_off_thresd;
static int rk81x_bat_sleep_chrg(struct rk81x_battery *di)
{
- int sleep_soc;
+ int sleep_soc = 0;
unsigned long sleep_sec;
sleep_sec = di->suspend_time_sum;
else if (old_charge_status != di->psy_status)
state_changed = true;
- if (di->dsoc >= 100 && rk81x_chrg_online(di))
- di->psy_status = POWER_SUPPLY_STATUS_FULL;
+ if (rk81x_chrg_online(di)) {
+ if (di->dsoc == 100)
+ di->psy_status = POWER_SUPPLY_STATUS_FULL;
+ else
+ di->psy_status = POWER_SUPPLY_STATUS_CHARGING;
+ }
if (state_changed) {
power_supply_changed(&di->bat);
}
}
+#if 0
static u8 rk81x_bat_get_cvcc_chrg_hour(struct rk81x_battery *di)
{
u8 hour, buf;
di->current_avg);
if (SEC_TO_MIN(di->chrg_time2full) > 60) {
- rk81x_bat_init_chrg_timer(di);
+ /*rk81x_bat_init_chrg_timer(di);*/
di->plug_in_base = get_runtime_sec();
DBG("%s: reset charge timer\n", __func__);
}
}
}
+#endif
/*
* in case that we will do reboot stress test, we need a special way
{
u8 rsoc = di->rsoc;
u8 dsoc = di->dsoc;
- u8 status = di->psy_status;
u8 cnt;
int unit_time;
int smooth_time;
__func__, cnt, unit_time, smooth_time,
BASE_TO_SEC(di->power_on_base), dsoc, rsoc);
- if (((status == POWER_SUPPLY_STATUS_CHARGING) ||
- (status == POWER_SUPPLY_STATUS_FULL)) &&
- (abs(di->current_avg) < 5)) {
+ if (di->current_avg >= 0 || di->chrg_status == CHARGE_FINISH) {
DBG("chrg, sm:%d, aim:%d\n", smooth_time, unit_time * 3 / 5);
if ((dsoc < rsoc - 1) && (smooth_time > unit_time * 3 / 5)) {
cnt = 0;
dsoc = 100;
rk81x_bat_save_dsoc(di, dsoc);
}
- } else {/*status == POWER_SUPPLY_STATUS_DISCHARGING*/
-
- DBG("dischrg, sm:%d, aim:%d\n", smooth_time, unit_time * 3/5);
- if ((dsoc > rsoc) && (smooth_time > unit_time * 3/5)) {
+ } else {
+ DBG("dischrg, sm:%d, aim:%d\n", smooth_time, unit_time * 3 / 5);
+ if ((dsoc > rsoc) && (smooth_time > unit_time * 3 / 5)) {
cnt = 0;
dsoc--;
if (dsoc <= 0)
di->relax_voltage = rk81x_bat_get_relax_vol(di);
di->est_ocv_vol = rk81x_bat_est_ocv_vol(di);
di->est_ocv_soc = rk81x_bat_est_ocv_soc(di);
- rk81x_bat_chrg_over_time_check(di);
+ /*rk81x_bat_chrg_over_time_check(di);*/
rk81x_bat_update_calib_param(di);
if (di->chrg_status == CC_OR_CV)
di->enter_finish = true;
}
EXPORT_SYMBOL_GPL(battery_notifier_call_chain);
-static void poweron_lowerpoer_handle(struct rk81x_battery *di)
-{
-#ifdef CONFIG_LOGO_LOWERPOWER_WARNING
- if ((di->dsoc <= 2) &&
- (di->psy_status == POWER_SUPPLY_STATUS_DISCHARGING)) {
- mdelay(1500);
- /* kernel_power_off(); */
- }
-#endif
-}
-
static int rk81x_bat_notifier_call(struct notifier_block *nb,
unsigned long event, void *data)
{
container_of(nb, struct rk81x_battery, battery_nb);
switch (event) {
- case 0:
- DBG(" CHARGE enable\n");
- di->charge_otg = 0;
- rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_IN_INT);
- rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_OUT_INT);
- queue_delayed_work(di->wq, &di->charge_check_work,
- msecs_to_jiffies(50));
- break;
- case 1:
- di->charge_otg = 1;
+ case USB_OTG_POWER_ON:
+ dev_info(di->dev, "charge disable, otg enable\n");
+ di->charge_otg = USB_OTG_POWER_ON;
rk81x_bat_set_bit(di, NT_STS_MSK_REG2, PLUG_IN_INT);
rk81x_bat_set_bit(di, NT_STS_MSK_REG2, PLUG_OUT_INT);
queue_delayed_work(di->wq, &di->charge_check_work,
msecs_to_jiffies(50));
- DBG("charge disable OTG enable\n");
break;
- case 2:
- poweron_lowerpoer_handle(di);
+
+ case USB_OTG_POWER_OFF:
+ dev_info(di->dev, "charge enable, otg disable\n");
+ di->charge_otg = USB_OTG_POWER_OFF;
+ rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_IN_INT);
+ rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_OUT_INT);
+ queue_delayed_work(di->wq, &di->charge_check_work,
+ msecs_to_jiffies(50));
break;
default:
return NOTIFY_OK;
static void rk81x_bat_info_init(struct rk81x_battery *di,
struct rk818 *chip)
{
+ u8 val;
unsigned long time_base = get_runtime_sec();
+ rk81x_bat_read(di, RK818_VB_MON_REG, &val, 1);
+ if (val & PLUG_IN_STS)
+ rk81x_bat_set_power_supply_state(di, USB_CHARGER);
+
di->cell.config = di->pdata->cell_cfg;
di->design_capacity = di->pdata->cell_cfg->design_capacity;
di->qmax = di->pdata->cell_cfg->design_qmax;
if (gpio_is_valid(di->dc_det_pin))
di->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW) ?
RK818_DC_IN : RK818_DC_OUT;
-
di->dc_det_irq = gpio_to_irq(di->dc_det_pin);
ret = request_irq(di->dc_det_irq, rk81x_vbat_dc_det,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
queue_delayed_work(di->wq, &di->battery_monitor_work,
msecs_to_jiffies(TIMER_MS_COUNTS * 5));
+#if defined(CONFIG_ARCH_ROCKCHIP)
INIT_DELAYED_WORK(&di->charge_check_work,
rk81x_battery_charge_check_work);
di->battery_nb.notifier_call = rk81x_bat_notifier_call;
- register_battery_notifier(&di->battery_nb);
-
+ rk_bc_detect_notifier_register(&di->battery_nb, &di->charge_otg);
+#endif
dev_info(di->dev, "battery driver version %s\n", DRIVER_VERSION);
return ret;
di->dischrg_normal_base = 0;
di->dischrg_emu_base = 0;
do_gettimeofday(&di->suspend_rtc_base);
+
if (!rk81x_chrg_online(di)) {
di->chrg_save_sec += rk81x_bat_save_chrg_sec(di);
di->chrg_normal_base = 0;
int delta_time;
int time_step;
int delta_soc;
+ int vol;
di->discharge_smooth_status = true;
di->charge_smooth_status = true;
di->s2r = 1;
- di->voltage = rk81x_bat_get_vol(di);
+ vol = rk81x_bat_get_vol(di);
+ if (vol < INVALID_VOL_THRESD) {
+ dev_err(di->dev, "invalid voltage :%d", vol);
+ vol = di->voltage;
+ dbg_enable = 1;
+ }
+ di->voltage = vol;
di->current_avg = rk81x_bat_get_avg_current(di);
di->relax_voltage = rk81x_bat_get_relax_vol(di);
di->est_ocv_vol = rk81x_bat_est_ocv_vol(di);
delta_time = rk81x_bat_get_suspend_sec(di);
di->suspend_time_sum += delta_time;
#if defined(CONFIG_ARCH_ROCKCHIP)
- di->remain_capacity= rk81x_bat_get_realtime_capacity(di);
+ di->remain_capacity = rk81x_bat_get_realtime_capacity(di);
#endif
if (di->slp_psy_status) {
if ((!rk81x_chrg_online(di) && di->voltage <= pwroff_thresd) ||
rk81x_chrg_online(di))
wake_lock_timeout(&di->resume_wake_lock, 5 * HZ);
+
/*
* do not modify the g_base_sec
*/
struct rk81x_battery *di = platform_get_drvdata(dev);
cancel_delayed_work_sync(&di->battery_monitor_work);
+ rk_bc_detect_notifier_unregister(&di->battery_nb);
+
if (BASE_TO_MIN(di->power_on_base) <= REBOOT_INTER_MIN)
rk81x_bat_check_reboot(di);
else