X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fpower%2Frk818_battery.c;h=52c623710a1164cd241bcacd1dd861cf63e7953e;hb=7f46fa83192f3c741864265016d1bdbf73228b5e;hp=ceb28ec4e9b77c51ef2e4b7dedf01007d76ef5dc;hpb=d4f8267697549cd7bd9fdae389b507ba1824e4b8;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/power/rk818_battery.c b/drivers/power/rk818_battery.c index ceb28ec4e9b7..52c623710a11 100644 --- a/drivers/power/rk818_battery.c +++ b/drivers/power/rk818_battery.c @@ -53,6 +53,8 @@ #if defined(CONFIG_X86_INTEL_SOFIA) #include +#else +#include #endif #include "rk818_battery.h" @@ -149,6 +151,10 @@ module_param_named(dbg_level, dbg_enable, int, 0644); #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%*/ @@ -195,6 +201,7 @@ struct rk81x_battery { int irq; int ac_online; int usb_online; + int otg_online; int psy_status; int current_avg; int current_offset; @@ -282,10 +289,12 @@ struct rk81x_battery { int s2r; /*suspend to resume*/ struct workqueue_struct *wq; struct delayed_work battery_monitor_work; - struct delayed_work charge_check_work; + struct delayed_work otg_check_work; struct delayed_work usb_phy_delay_work; struct delayed_work chrg_term_mode_switch_work; - int charge_otg; + struct delayed_work ac_usb_check_work; + struct delayed_work dc_det_check_work; + enum bc_port_type charge_otg; int ma; struct wake_lock resume_wake_lock; @@ -595,7 +604,7 @@ static void rk81x_bat_capacity_init(struct rk81x_battery *di, u32 capacity) } 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); } @@ -920,7 +929,7 @@ static uint16_t rk81x_bat_get_ocv_vol(struct rk81x_battery *di) 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]; @@ -943,9 +952,9 @@ static int rk81x_bat_get_vol(struct rk81x_battery *di) 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) @@ -1094,7 +1103,7 @@ static bool rk81x_bat_zero_current_calib(struct rk81x_battery *di) 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; } @@ -1130,7 +1139,7 @@ static bool rk81x_bat_zero_current_calib(struct rk81x_battery *di) 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); } @@ -1732,152 +1741,122 @@ static void rk81x_bat_set_chrg_current(struct rk81x_battery *di, } #if defined(CONFIG_ARCH_ROCKCHIP) -/* -* There are three ways to detect dc_adp: -* 1. hardware only support dc_adp: by reg VB_MOD_REG of rk818, -* do not care about whether define dc_det_pin or not; -* 2. define de_det_pin: check gpio level; -* 3. support usb_adp and dc_adp: by VB_MOD_REG and usb interface. -* case that: gpio invalid or not define. -*/ -static enum charger_type rk81x_bat_get_dc_state(struct rk81x_battery *di) -{ - enum charger_type charger_type; - u8 buf; - int ret; - rk81x_bat_read(di, VB_MOD_REG, &buf, 1); - - /*only HW_ADP_TYPE_DC: det by rk818 is easily and will be successful*/ - if (!rk81x_bat_support_adp_type(HW_ADP_TYPE_USB)) { - if ((buf & PLUG_IN_STS) != 0) - charger_type = DC_CHARGER; - else - charger_type = NO_CHARGER; - - return charger_type; - } - - /*det by gpio level*/ - if (gpio_is_valid(di->dc_det_pin)) { - ret = gpio_request(di->dc_det_pin, "rk818_dc_det"); - if (ret < 0) { - pr_err("Failed to request gpio %d with ret:""%d\n", - di->dc_det_pin, ret); - return NO_CHARGER; - } +static void rk81x_bat_set_charger_param(struct rk81x_battery *di, + enum charger_type charger_type) +{ + rk81x_bat_set_chrg_current(di, charger_type); + rk81x_bat_set_power_supply_state(di, charger_type); - gpio_direction_input(di->dc_det_pin); - ret = gpio_get_value(di->dc_det_pin); - if (ret == di->dc_det_level) - charger_type = DC_CHARGER; - else - charger_type = NO_CHARGER; + switch (charger_type) { + case NO_CHARGER: + power_supply_changed(&di->bat); + break; + case USB_CHARGER: + case AC_CHARGER: + power_supply_changed(&di->usb); + break; + case DC_CHARGER: + power_supply_changed(&di->ac); + break; + default: + break; + } +} - gpio_free(di->dc_det_pin); - DBG("**********rk818 dc_det_pin=%d\n", ret); +static enum charger_type rk81x_bat_get_dc_state(struct rk81x_battery *di) +{ + int ret; + enum charger_type charger_type = NO_CHARGER; - return charger_type; + if (di->fg_drv_mode == TEST_POWER_MODE) { + charger_type = DC_CHARGER; + goto out; + } + /* + if (di->otg_online) + goto out; + */ + if (!gpio_is_valid(di->dc_det_pin)) + goto out; - /*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(); - if (charger_type == 0) - charger_type = DC_CHARGER; - else - charger_type = NO_CHARGER; - } + ret = gpio_request(di->dc_det_pin, "rk818_dc_det"); + if (ret < 0) { + pr_err("Failed to request gpio %d with ret:""%d\n", + di->dc_det_pin, ret); + goto out; } + gpio_direction_input(di->dc_det_pin); + ret = gpio_get_value(di->dc_det_pin); + if (ret == di->dc_det_level) + charger_type = DC_CHARGER; + else + charger_type = NO_CHARGER; + gpio_free(di->dc_det_pin); +out: return charger_type; } -static enum charger_type rk81x_bat_get_usbac_state(struct rk81x_battery *di) +static void rk81x_battery_dc_delay_work(struct work_struct *work) { enum charger_type charger_type; - int usb_id, gadget_flag; + struct rk81x_battery *di = container_of(work, + struct rk81x_battery, dc_det_check_work.work); + + charger_type = rk81x_bat_get_dc_state(di); + + if (charger_type == DC_CHARGER) + rk81x_bat_set_charger_param(di, DC_CHARGER); + else/*NO_CHARGER: maybe usb charger still plugin*/ + queue_delayed_work(di->wq, + &di->ac_usb_check_work, + msecs_to_jiffies(10)); +} - usb_id = dwc_otg_check_dpdm(); +static void rk81x_battery_acusb_delay_work(struct work_struct *work) +{ + u8 buf; + int gadget_flag, usb_id; + struct rk81x_battery *di = container_of(work, + struct rk81x_battery, ac_usb_check_work.work); + + rk81x_bat_read(di, VB_MOD_REG, &buf, 1); + usb_id = dwc_otg_check_dpdm(0); switch (usb_id) { case 0: - charger_type = NO_CHARGER; + if ((buf & PLUG_IN_STS) != 0) + rk81x_bat_set_charger_param(di, DC_CHARGER); + else + rk81x_bat_set_charger_param(di, NO_CHARGER); break; case 1: case 3: - charger_type = USB_CHARGER; + rk81x_bat_set_charger_param(di, USB_CHARGER); break; case 2: - charger_type = AC_CHARGER; + rk81x_bat_set_charger_param(di, AC_CHARGER); break; default: - charger_type = NO_CHARGER; + break; } - - DBG("<%s>. DWC_OTG = %d\n", __func__, usb_id); - if (charger_type == USB_CHARGER) { + /*check unstanderd charger*/ + if (usb_id == 1 || usb_id == 3) { gadget_flag = get_gadget_connect_flag(); - DBG("<%s>. gadget_flag=%d, check_cnt=%d\n", - __func__, gadget_flag, di->check_count); - if (0 == gadget_flag) { - if (++di->check_count >= 5) { - charger_type = AC_CHARGER; - DBG("<%s>. turn to AC_CHARGER, check_cnt=%d\n", - __func__, di->check_count); + di->check_count++; + if (di->check_count >= 5) { + di->check_count = 0; + rk81x_bat_set_charger_param(di, AC_CHARGER); } else { - charger_type = USB_CHARGER; + queue_delayed_work(di->wq, + &di->ac_usb_check_work, + msecs_to_jiffies(1000)); } - } else { - charger_type = USB_CHARGER; + } else {/*confirm: USB_CHARGER*/ di->check_count = 0; } - } else { - di->check_count = 0; } - - return charger_type; -} - -/* - * when support HW_ADP_TYPE_DUAL, and at the moment that usb_adp - * and dc_adp are plugined in together, the dc_apt has high priority. - * so we check dc_apt first and return rigth away if it's found. - */ -static enum charger_type rk81x_bat_get_adp_type(struct rk81x_battery *di) -{ - u8 buf; - enum charger_type charger_type = NO_CHARGER; - - /*check by ic hardware: this check make check work safer*/ - rk81x_bat_read(di, VB_MOD_REG, &buf, 1); - if ((buf & PLUG_IN_STS) == 0) - return NO_CHARGER; - - /*check DC first*/ - if (rk81x_bat_support_adp_type(HW_ADP_TYPE_DC)) { - charger_type = rk81x_bat_get_dc_state(di); - if (charger_type == DC_CHARGER) - return charger_type; - } - - /*HW_ADP_TYPE_USB*/ - charger_type = rk81x_bat_get_usbac_state(di); - - return charger_type; -} - -static void rk81x_bat_status_check(struct rk81x_battery *di) -{ - static enum charger_type old_charger_type = DUAL_CHARGER; - enum charger_type charger_type; - - charger_type = rk81x_bat_get_adp_type(di); - if (charger_type == old_charger_type) - return; - rk81x_bat_set_chrg_current(di, charger_type); - rk81x_bat_set_power_supply_state(di, charger_type); - old_charger_type = charger_type; } #endif @@ -2333,21 +2312,6 @@ static void rk81x_bat_charger_init(struct rk81x_battery *di) rk81x_bat_write(di, GGCON, &ggcon, 1); } -void rk81x_charge_disable_open_otg(struct rk81x_battery *di) -{ - int value = di->charge_otg; - - if (value) { - 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 { - 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); - } -} - static void rk81x_bat_fg_init(struct rk81x_battery *di) { u8 pcb_offset; @@ -2958,7 +2922,7 @@ static void rk81x_bat_finish_chrg(struct rk81x_battery *di) 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; @@ -3370,7 +3334,7 @@ static int rk81x_bat_sleep_dischrg(struct rk81x_battery *di) 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; @@ -3495,7 +3459,6 @@ static void rk81x_bat_check_reboot(struct rk81x_battery *di) { u8 rsoc = di->rsoc; u8 dsoc = di->dsoc; - u8 status = di->psy_status; u8 cnt; int unit_time; int smooth_time; @@ -3510,8 +3473,7 @@ static void rk81x_bat_check_reboot(struct rk81x_battery *di) __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; @@ -3520,10 +3482,9 @@ static void rk81x_bat_check_reboot(struct rk81x_battery *di) 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) @@ -3587,9 +3548,6 @@ static void rk81x_bat_update_info(struct rk81x_battery *di) rk81x_bat_update_calib_param(di); if (di->chrg_status == CC_OR_CV) di->enter_finish = true; -#if defined(CONFIG_ARCH_ROCKCHIP) - rk81x_bat_status_check(di);/* ac_online, usb_online, status*/ -#endif if (!rk81x_chrg_online(di) && di->s2r) return; @@ -3719,13 +3677,41 @@ static void rk81x_battery_work(struct work_struct *work) msecs_to_jiffies(ms)); } -static void rk81x_battery_charge_check_work(struct work_struct *work) +#if defined(CONFIG_ARCH_ROCKCHIP) +static void rk81x_battery_otg_delay_work(struct work_struct *work) { struct rk81x_battery *di = container_of(work, - struct rk81x_battery, charge_check_work.work); + struct rk81x_battery, otg_check_work.work); + + enum bc_port_type event = di->charge_otg; + + /* do not touch CHRG_CTRL_REG1[7]: CHRG_EN, hardware can + * recognize otg plugin and will auto ajust this bit + */ + switch (event) { + case USB_OTG_POWER_ON: + dev_info(di->dev, "charge disable, otg enable\n"); + di->otg_online = ONLINE; + /*rk81x_bat_set_charger_param(di, NO_CHARGER);*/ + rk81x_bat_set_bit(di, NT_STS_MSK_REG2, PLUG_IN_INT); + rk81x_bat_set_bit(di, NT_STS_MSK_REG2, PLUG_OUT_INT); + rk818_set_bits(di->rk818, DCDC_EN_REG, OTG_EN_MASK, OTG_EN); + break; - DBG("rk81x_battery_charge_check_work\n"); - rk81x_charge_disable_open_otg(di); + case USB_OTG_POWER_OFF: + dev_info(di->dev, "charge enable, otg disable\n"); + di->otg_online = OFFLINE; + rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_IN_INT); + rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, PLUG_OUT_INT); + rk818_set_bits(di->rk818, DCDC_EN_REG, OTG_EN_MASK, OTG_DIS); + /*maybe dc still plugin*/ + queue_delayed_work(di->wq, &di->dc_det_check_work, + msecs_to_jiffies(10)); + break; + + default: + break; + } } static BLOCKING_NOTIFIER_HEAD(battery_chain_head); @@ -3749,49 +3735,50 @@ int battery_notifier_call_chain(unsigned long val) } 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) +static int rk81x_bat_usb_notifier_call(struct notifier_block *nb, + unsigned long event, void *data) { + enum charger_type charger_type; struct rk81x_battery *di = container_of(nb, struct rk81x_battery, battery_nb); + if (di->fg_drv_mode == TEST_POWER_MODE) + return NOTIFY_OK; + + /*if dc is pluging, ignore usb*/ + charger_type = rk81x_bat_get_dc_state(di); + if ((charger_type == DC_CHARGER) && + (event != USB_OTG_POWER_OFF) && + (event != USB_OTG_POWER_ON)) + return NOTIFY_OK; + 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)); + case USB_BC_TYPE_DISCNT:/*maybe dc still plugin*/ + queue_delayed_work(di->wq, &di->dc_det_check_work, + msecs_to_jiffies(10)); break; - case 1: - di->charge_otg = 1; - 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"); + case USB_BC_TYPE_SDP: + case USB_BC_TYPE_CDP:/*nonstandard charger*/ + case USB_BC_TYPE_DCP:/*standard charger*/ + queue_delayed_work(di->wq, &di->ac_usb_check_work, + msecs_to_jiffies(10)); break; - case 2: - poweron_lowerpoer_handle(di); + case USB_OTG_POWER_ON:/*otg on*/ + di->charge_otg = USB_OTG_POWER_ON; + queue_delayed_work(di->wq, &di->otg_check_work, + msecs_to_jiffies(10)); + break; + case USB_OTG_POWER_OFF:/*otg off*/ + di->charge_otg = USB_OTG_POWER_OFF; + queue_delayed_work(di->wq, &di->otg_check_work, + msecs_to_jiffies(10)); break; default: return NOTIFY_OK; } return NOTIFY_OK; } - +#endif static irqreturn_t rk81x_vbat_lo_irq(int irq, void *bat) { pr_info("\n------- %s:lower power warning!\n", __func__); @@ -3827,6 +3814,11 @@ static irqreturn_t rk81x_vbat_charge_ok(int irq, void *bat) static irqreturn_t rk81x_vbat_dc_det(int irq, void *bat) { + struct rk81x_battery *di = (struct rk81x_battery *)bat; + + queue_delayed_work(di->wq, + &di->dc_det_check_work, + msecs_to_jiffies(10)); rk_send_wakeup_key(); return IRQ_HANDLED; @@ -3896,8 +3888,13 @@ static void rk81x_bat_irq_init(struct rk81x_battery *di) 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; @@ -3924,19 +3921,29 @@ static void rk81x_bat_dc_det_init(struct rk81x_battery *di, int ret; di->dc_det_pin = of_get_named_gpio_flags(np, "dc_det_gpio", 0, &flags); - if (di->dc_det_pin == -EPROBE_DEFER) + if (di->dc_det_pin == -EPROBE_DEFER) { dev_err(dev, "dc_det_gpio error\n"); - if (gpio_is_valid(di->dc_det_pin)) + return; + } + + 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, - "rk81x_dc_det", NULL); + 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, + "rk81x_dc_det", di); + if (ret != 0) { + dev_err(di->dev, "rk818_dc_det_irq request failed!\n"); + goto err; + } + enable_irq_wake(di->dc_det_irq); + } - if (ret != 0) - dev_err(di->dev, "rk818_dc_det_irq request failed!\n"); - enable_irq_wake(di->dc_det_irq); + return; +err: + gpio_free(di->dc_det_pin); } static int rk81x_bat_get_suspend_sec(struct rk81x_battery *di) @@ -4097,8 +4104,8 @@ static int rk81x_bat_parse_dt(struct rk81x_battery *di) support_usb_adp = 1; } - if (support_dc_adp) - rk81x_bat_dc_det_init(di, np); + /*if (support_dc_adp)*/ + rk81x_bat_dc_det_init(di, np); cell_cfg->ocv = ocv_cfg; pdata->cell_cfg = cell_cfg; @@ -4196,11 +4203,20 @@ static int rk81x_battery_probe(struct platform_device *pdev) queue_delayed_work(di->wq, &di->battery_monitor_work, msecs_to_jiffies(TIMER_MS_COUNTS * 5)); - 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); +#if defined(CONFIG_ARCH_ROCKCHIP) + INIT_DELAYED_WORK(&di->otg_check_work, + rk81x_battery_otg_delay_work); + INIT_DELAYED_WORK(&di->ac_usb_check_work, + rk81x_battery_acusb_delay_work); + INIT_DELAYED_WORK(&di->dc_det_check_work, + rk81x_battery_dc_delay_work); + /*power on check*/ + queue_delayed_work(di->wq, &di->dc_det_check_work, + msecs_to_jiffies(TIMER_MS_COUNTS * 5)); + di->battery_nb.notifier_call = rk81x_bat_usb_notifier_call; + 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; @@ -4211,8 +4227,10 @@ static int rk81x_battery_suspend(struct platform_device *dev, { struct rk81x_battery *di = platform_get_drvdata(dev); - di->slp_psy_status = rk81x_chrg_online(di); + /*while otg and dc both plugin*/ + rk81x_bat_set_bit(di, NT_STS_MSK_REG2, CHRG_CVTLMT_INT); + di->slp_psy_status = rk81x_chrg_online(di); di->chrg_status = rk81x_bat_get_chrg_status(di); di->slp_chrg_status = rk81x_bat_get_chrg_status(di); di->suspend_charge_current = rk81x_bat_get_avg_current(di); @@ -4249,11 +4267,21 @@ static int rk81x_battery_resume(struct platform_device *dev) int delta_time; int time_step; int delta_soc; + int vol; + + /*while otg and dc both plugin*/ + rk81x_bat_clr_bit(di, NT_STS_MSK_REG2, CHRG_CVTLMT_INT); 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); @@ -4287,6 +4315,7 @@ static int rk81x_battery_resume(struct platform_device *dev) 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 */ @@ -4311,6 +4340,8 @@ static void rk81x_battery_shutdown(struct platform_device *dev) 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