| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * Copyright (C) 2018-2020 Oplus. All rights reserved. |
| */ |
| #include <linux/delay.h> |
| #include <linux/proc_fs.h> |
| #include <linux/uaccess.h> |
| #include <linux/math64.h> |
| |
| #include "oplus_charger.h" |
| #include "oplus_vooc.h" |
| #include "oplus_gauge.h" |
| #include "oplus_adapter.h" |
| #include "oplus_debug_info.h" |
| |
| #define VOOC_NOTIFY_FAST_PRESENT 0x52 |
| #define VOOC_NOTIFY_FAST_ABSENT 0x54 |
| #define VOOC_NOTIFY_ALLOW_READING_IIC 0x58 |
| #define VOOC_NOTIFY_NORMAL_TEMP_FULL 0x5a |
| #define VOOC_NOTIFY_LOW_TEMP_FULL 0x53 |
| #define VOOC_NOTIFY_DATA_UNKNOWN 0x55 |
| #define VOOC_NOTIFY_FIRMWARE_UPDATE 0x56 |
| #define VOOC_NOTIFY_BAD_CONNECTED 0x59 |
| #define VOOC_NOTIFY_TEMP_OVER 0x5c |
| #define VOOC_NOTIFY_ADAPTER_FW_UPDATE 0x5b |
| #define VOOC_NOTIFY_BTB_TEMP_OVER 0x5d |
| #define VOOC_NOTIFY_ADAPTER_MODEL_FACTORY 0x5e |
| |
| #define VOOC_TEMP_RANGE_THD 10 |
| #define VBAT_TEMP_STRATEGY_HYS 3 /*0.3degC*/ |
| #define VBAT_TEMP_STRATEGY_INVALID -10 |
| |
| extern int charger_abnormal_log; |
| extern int enable_charger_log; |
| #define vooc_xlog_printk(num, fmt, ...) \ |
| do { \ |
| if (enable_charger_log >= (int)num) { \ |
| printk(KERN_NOTICE pr_fmt("[OPLUS_CHG][%s]"fmt), __func__, ##__VA_ARGS__);\ |
| } \ |
| } while (0) |
| |
| |
| static struct oplus_vooc_chip *g_vooc_chip = NULL; |
| bool __attribute__((weak)) oplus_get_fg_i2c_err_occured(void) |
| { |
| return false; |
| } |
| |
| void __attribute__((weak)) oplus_set_fg_i2c_err_occured(bool i2c_err) |
| { |
| return; |
| } |
| int __attribute__((weak)) request_firmware_select(const struct firmware **firmware_p, |
| const char *name, struct device *device) |
| { |
| return 1; |
| } |
| int __attribute__((weak)) register_devinfo(char *name, struct manufacture_info *info) |
| { |
| return 1; |
| } |
| static int oplus_vooc_convert_fast_chg_type(int fast_chg_type); |
| |
| static bool oplus_vooc_is_battemp_exit(void) |
| { |
| int temp; |
| bool high_temp = false, low_temp = false; |
| bool status = false; |
| |
| temp = oplus_chg_match_temp_for_chging(); |
| if((g_vooc_chip->vooc_batt_over_high_temp != -EINVAL) && (g_vooc_chip->vooc_batt_over_low_temp != -EINVAL)){ |
| high_temp = (temp > g_vooc_chip->vooc_batt_over_high_temp); |
| low_temp = (temp < g_vooc_chip->vooc_batt_over_low_temp); |
| status = (g_vooc_chip->fastchg_batt_temp_status == BAT_TEMP_EXIT); |
| |
| return ((high_temp || low_temp) && status); |
| }else |
| return false; |
| } |
| |
| void oplus_vooc_battery_update(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| /* |
| if (!chip) { |
| chg_err(" g_vooc_chip is NULL\n"); |
| return ; |
| } |
| */ |
| if (!chip->batt_psy) { |
| chip->batt_psy = power_supply_get_by_name("battery"); |
| } |
| if (chip->batt_psy) { |
| power_supply_changed(chip->batt_psy); |
| } |
| } |
| |
| void oplus_vooc_switch_mode(int mode) |
| { |
| if (!g_vooc_chip) { |
| chg_err(" g_vooc_chip is NULL\n"); |
| } else { |
| g_vooc_chip->vops->set_switch_mode(g_vooc_chip, mode); |
| } |
| } |
| |
| static void oplus_vooc_awake_init(struct oplus_vooc_chip *chip) |
| { |
| if (!chip) { |
| return; |
| } |
| |
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) |
| wake_lock_init(&chip->vooc_wake_lock, WAKE_LOCK_SUSPEND, "vooc_wake_lock"); |
| #elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 102) && LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 999)) |
| chip->vooc_ws = wakeup_source_register("vooc_wake_lock"); |
| #else |
| chip->vooc_ws = wakeup_source_register(NULL, "vooc_wake_lock"); |
| #endif |
| } |
| |
| static void oplus_vooc_set_awake(struct oplus_vooc_chip *chip, bool awake) |
| { |
| static bool pm_flag = false; |
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) |
| if(!chip) { |
| return; |
| } |
| if (awake && !pm_flag) { |
| pm_flag = true; |
| wake_lock(&chip->vooc_wake_lock); |
| } else if (!awake && pm_flag) { |
| wake_unlock(&chip->vooc_wake_lock); |
| pm_flag = false; |
| } |
| #else |
| if (!chip || !chip->vooc_ws) { |
| return; |
| } |
| if (awake && !pm_flag) { |
| pm_flag = true; |
| __pm_stay_awake(chip->vooc_ws); |
| } else if (!awake && pm_flag) { |
| __pm_relax(chip->vooc_ws); |
| pm_flag = false; |
| } |
| #endif |
| } |
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) |
| static void oplus_vooc_watchdog(unsigned long data) |
| #else |
| static void oplus_vooc_watchdog(struct timer_list *unused) |
| #endif |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| |
| if (!chip) { |
| chg_err(" g_vooc_chip is NULL\n"); |
| return; |
| } |
| chg_err("watchdog bark: cannot receive mcu data\n"); |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_ing = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_low_temp_full = false; |
| chip->btb_temp_over = false; |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| charger_abnormal_log = CRITICAL_LOG_VOOC_WATCHDOG; |
| schedule_work(&chip->vooc_watchdog_work); |
| } |
| |
| static void oplus_vooc_init_watchdog_timer(struct oplus_vooc_chip *chip) |
| { |
| if (!chip) { |
| chg_err("oplus_vooc_chip is not ready\n"); |
| return; |
| } |
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) |
| init_timer(&chip->watchdog); |
| chip->watchdog.data = (unsigned long)chip; |
| chip->watchdog.function = oplus_vooc_watchdog; |
| #else |
| timer_setup(&chip->watchdog, oplus_vooc_watchdog, 0); |
| #endif |
| } |
| |
| static void oplus_vooc_del_watchdog_timer(struct oplus_vooc_chip *chip) |
| { |
| if (!chip) { |
| chg_err("oplus_vooc_chip is not ready\n"); |
| return; |
| } |
| del_timer(&chip->watchdog); |
| } |
| |
| static void oplus_vooc_setup_watchdog_timer(struct oplus_vooc_chip *chip, unsigned int ms) |
| { |
| if (!chip) { |
| chg_err("oplus_vooc_chip is not ready\n"); |
| return; |
| } |
| #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) |
| mod_timer(&chip->watchdog, jiffies+msecs_to_jiffies(25000)); |
| #else |
| del_timer(&chip->watchdog); |
| chip->watchdog.expires = jiffies + msecs_to_jiffies(ms); |
| add_timer(&chip->watchdog); |
| #endif |
| } |
| |
| static void check_charger_out_work_func(struct work_struct *work) |
| { |
| struct delayed_work *dwork = to_delayed_work(work); |
| struct oplus_vooc_chip *chip = container_of(dwork, struct oplus_vooc_chip, check_charger_out_work); |
| int chg_vol = 0; |
| |
| chg_vol = oplus_chg_get_charger_voltage(); |
| if (chg_vol >= 0 && chg_vol < 2000) { |
| chip->vops->reset_fastchg_after_usbout(chip); |
| oplus_chg_clear_chargerid_info(); |
| oplus_vooc_battery_update(); |
| oplus_vooc_reset_temp_range(chip); |
| vooc_xlog_printk(CHG_LOG_CRTI, "charger out, chg_vol:%d\n", chg_vol); |
| } |
| } |
| |
| static void vooc_watchdog_work_func(struct work_struct *work) |
| { |
| struct oplus_vooc_chip *chip = container_of(work, |
| struct oplus_vooc_chip, vooc_watchdog_work); |
| |
| oplus_chg_set_chargerid_switch_val(0); |
| oplus_chg_clear_chargerid_info(); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_chg_set_charger_type_unknown(); |
| oplus_vooc_set_awake(chip, false); |
| oplus_vooc_reset_temp_range(chip); |
| } |
| |
| static void oplus_vooc_check_charger_out(struct oplus_vooc_chip *chip) |
| { |
| vooc_xlog_printk(CHG_LOG_CRTI, " call\n"); |
| schedule_delayed_work(&chip->check_charger_out_work, |
| round_jiffies_relative(msecs_to_jiffies(3000))); |
| } |
| |
| int multistepCurrent[] = {1500, 2000, 3000, 4000, 5000, 6000}; |
| |
| #define VOOC_TEMP_OVER_COUNTS 2 |
| |
| static int oplus_vooc_set_current_1_temp_normal_range(struct oplus_vooc_chip *chip, int vbat_temp_cur, int temp_trend) |
| { |
| static int ret = 0; |
| |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| |
| if ((chip->vooc_batt_over_high_temp != -EINVAL |
| && vbat_temp_cur > chip->vooc_batt_over_high_temp) || |
| (chip->vooc_batt_over_low_temp != -EINVAL |
| && vbat_temp_cur < chip->vooc_batt_over_low_temp)) { /* over temp */ |
| chip->vooc_strategy_change_count++; |
| if (chip->vooc_strategy_change_count >= VOOC_TEMP_OVER_COUNTS) { |
| chip->vooc_strategy_change_count = 0; |
| chip->fastchg_batt_temp_status = BAT_TEMP_EXIT; |
| ret = chip->vooc_over_high_or_low_current; |
| vooc_xlog_printk(CHG_LOG_CRTI,"the battery over temp (%d)\n", vbat_temp_cur); |
| return ret; |
| } |
| } |
| |
| switch (temp_trend) { |
| case TEMP_STRATEGY_NONE: |
| break; |
| case TEMP_STRATEGY_HIGH: |
| if (vbat_temp_cur > chip->vooc_strategy1_batt_high_temp2) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH2; |
| ret = chip->vooc_strategy1_high_current2; |
| } else if (vbat_temp_cur > chip->vooc_strategy1_batt_high_temp1) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH1; |
| ret = chip->vooc_strategy1_high_current1; |
| } else if (vbat_temp_cur > chip->vooc_strategy1_batt_high_temp0) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH0; |
| ret = chip->vooc_strategy1_high_current0; |
| } else if (vbat_temp_cur >= chip->vooc_normal_low_temp) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| ret = chip->vooc_strategy_normal_current; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_normal_low_temp += VOOC_TEMP_RANGE_THD; |
| } |
| break; |
| case TEMP_STRATEGY_LOW: |
| if (vbat_temp_cur < chip->vooc_normal_low_temp) { |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_current; |
| } else if (vbat_temp_cur < chip->vooc_strategy1_batt_low_temp0) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LOW0; |
| ret = chip->vooc_strategy1_low_current0; |
| } else if (vbat_temp_cur < chip->vooc_strategy1_batt_low_temp1) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LOW1; |
| ret = chip->vooc_strategy1_low_current1; |
| } else if (vbat_temp_cur < chip->vooc_strategy1_batt_low_temp2) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LOW2; |
| ret = chip->vooc_strategy1_low_current2; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LOW_OVER; |
| } |
| break; |
| default: |
| break; |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, "the ret: %d, the temp =%d, status = %d, temp_trend = %d\r\n", ret, vbat_temp_cur, chip->fastchg_batt_temp_status, temp_trend); |
| return ret; |
| } |
| |
| static int oplus_vooc_set_current_temp_low_normal_range(struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| |
| if (vbat_temp_cur < chip->vooc_normal_low_temp |
| && vbat_temp_cur >= chip->vooc_little_cool_temp) { /*16C<=T<25C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_low_current; |
| } else { |
| if (vbat_temp_cur >= chip->vooc_normal_low_temp) { |
| chip->vooc_normal_low_temp -= VOOC_TEMP_RANGE_THD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| ret = chip->vooc_strategy_normal_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COOL; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COOL; |
| ret = chip->vooc_strategy_normal_little_cool_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_little_cool_temp += VOOC_TEMP_RANGE_THD; |
| } |
| } |
| |
| return ret; |
| } |
| |
| static int oplus_vooc_set_current_temp_little_cool_range(struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| |
| if (vbat_temp_cur < chip->vooc_little_cool_temp |
| && vbat_temp_cur >= chip->vooc_cool_temp) {/*12C<=T<16C*/ |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COOL; |
| ret = chip->vooc_strategy_normal_little_cool_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COOL; |
| } else { |
| if (vbat_temp_cur >= chip->vooc_little_cool_temp) { |
| chip->vooc_little_cool_temp -= VOOC_TEMP_RANGE_THD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_low_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_COOL; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_COOL; |
| ret = chip->vooc_strategy_normal_cool_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_cool_temp += VOOC_TEMP_RANGE_THD; |
| } |
| } |
| |
| return ret; |
| } |
| |
| static int oplus_vooc_set_current_temp_cool_range(struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| if (chip->vooc_batt_over_high_temp != -EINVAL |
| && vbat_temp_cur < chip->vooc_batt_over_low_temp) { |
| chip->vooc_strategy_change_count++; |
| if (chip->vooc_strategy_change_count >= VOOC_TEMP_OVER_COUNTS) { |
| chip->vooc_strategy_change_count = 0; |
| chip->fastchg_batt_temp_status = BAT_TEMP_EXIT; |
| ret = chip->vooc_over_high_or_low_current; |
| } |
| } else if (vbat_temp_cur < chip->vooc_cool_temp |
| && vbat_temp_cur >= chip->vooc_little_cold_temp) {/*5C <=T<12C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_COOL; |
| chip->fastchg_batt_temp_status = BAT_TEMP_COOL; |
| ret = chip->vooc_strategy_normal_cool_current; |
| } else { |
| if (vbat_temp_cur >= chip->vooc_cool_temp) { |
| chip->vooc_cool_temp -= VOOC_TEMP_RANGE_THD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COOL; |
| ret = chip->vooc_strategy_normal_little_cool_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COOL; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COLD; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COLD; |
| ret = chip->vooc_strategy_normal_little_cold_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_little_cold_temp += VOOC_TEMP_RANGE_THD; |
| } |
| } |
| |
| return ret; |
| } |
| |
| static int oplus_vooc_set_current_temp_little_cold_range(struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| if (chip->vooc_batt_over_high_temp != -EINVAL |
| && vbat_temp_cur < chip->vooc_batt_over_low_temp) { |
| chip->vooc_strategy_change_count++; |
| if (chip->vooc_strategy_change_count >= VOOC_TEMP_OVER_COUNTS) { |
| chip->vooc_strategy_change_count = 0; |
| chip->fastchg_batt_temp_status = BAT_TEMP_EXIT; |
| ret = chip->vooc_over_high_or_low_current; |
| } |
| } else if (vbat_temp_cur < chip->vooc_little_cold_temp) { /*0C<=T<5C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COLD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COLD; |
| ret = chip->vooc_strategy_normal_little_cold_current; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_COOL; |
| ret = chip->vooc_strategy_normal_cool_current; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_COOL; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_little_cold_temp -= VOOC_TEMP_RANGE_THD; |
| } |
| |
| return ret; |
| } |
| |
| static int oplus_vooc_init_soc_range(struct oplus_vooc_chip *chip, int soc) |
| { |
| if (soc >= 0 && soc <= 50) { |
| chip->soc_range = 0; |
| } else if (soc >= 51 && soc <= 75) { |
| chip->soc_range = 1; |
| } else if (soc >= 76 && soc <= 85) { |
| chip->soc_range = 2; |
| } else { |
| chip->soc_range = 3; |
| } |
| chg_err("chip->soc_range[%d], soc[%d]", chip->soc_range, soc); |
| return chip->soc_range; |
| } |
| |
| static int oplus_vooc_init_temp_range(struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| if (vbat_temp_cur < chip->vooc_little_cold_temp) { /*0-5C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COLD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COLD; |
| } else if (vbat_temp_cur < chip->vooc_cool_temp) { /*5-12C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_COOL; |
| chip->fastchg_batt_temp_status = BAT_TEMP_COOL; |
| } else if (vbat_temp_cur < chip->vooc_little_cool_temp) { /*12-16C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COOL; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COOL; |
| } else if (vbat_temp_cur < chip->vooc_normal_low_temp) { /*16-25C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| } else {/*25C-43C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| } |
| chg_err("chip->vooc_temp_cur_range[%d], vbat_temp_cur[%d]", chip->vooc_temp_cur_range, vbat_temp_cur); |
| return chip->vooc_temp_cur_range; |
| |
| } |
| |
| static int oplus_vooc_set_current_when_bleow_setting_batt_temp |
| (struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| int diff = 0; |
| int temp_trend = TEMP_STRATEGY_NONE; |
| static int vbat_temp_last = 0; |
| |
| if (chip->vooc_temp_cur_range == FASTCHG_TEMP_RANGE_INIT) { |
| if (vbat_temp_cur < chip->vooc_little_cold_temp) { /*0-5C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COLD; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COLD; |
| } else if (vbat_temp_cur < chip->vooc_cool_temp) { /*5-12C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_COOL; |
| chip->fastchg_batt_temp_status = BAT_TEMP_COOL; |
| } else if (vbat_temp_cur < chip->vooc_little_cool_temp) { /*12-16C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_LITTLE_COOL; |
| chip->fastchg_batt_temp_status = BAT_TEMP_LITTLE_COOL; |
| } else if (vbat_temp_cur < chip->vooc_normal_low_temp) { /*16-25C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| } else {/*25C-43C*/ |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| } |
| vbat_temp_last = VBAT_TEMP_STRATEGY_INVALID; |
| temp_trend = TEMP_STRATEGY_NONE; |
| } |
| diff = vbat_temp_cur - vbat_temp_last; |
| if (abs(diff) < VBAT_TEMP_STRATEGY_HYS) { |
| temp_trend = TEMP_STRATEGY_NONE; |
| } else if (diff > 0) { |
| temp_trend = TEMP_STRATEGY_HIGH; |
| vbat_temp_last = vbat_temp_cur; |
| } else { |
| temp_trend = TEMP_STRATEGY_LOW; |
| vbat_temp_last = vbat_temp_cur; |
| } |
| //vbat_temp_last = vbat_temp_cur; |
| switch (chip->vooc_temp_cur_range) { |
| case FASTCHG_TEMP_RANGE_NORMAL_HIGH: |
| ret = oplus_vooc_set_current_1_temp_normal_range(chip, vbat_temp_cur, temp_trend); |
| break; |
| case FASTCHG_TEMP_RANGE_NORMAL_LOW: |
| ret = oplus_vooc_set_current_temp_low_normal_range(chip, vbat_temp_cur); |
| break; |
| case FASTCHG_TEMP_RANGE_LITTLE_COOL: |
| ret = oplus_vooc_set_current_temp_little_cool_range(chip, vbat_temp_cur); |
| break; |
| case FASTCHG_TEMP_RANGE_COOL: |
| ret = oplus_vooc_set_current_temp_cool_range(chip, vbat_temp_cur); |
| break; |
| case FASTCHG_TEMP_RANGE_LITTLE_COLD: |
| ret = oplus_vooc_set_current_temp_little_cold_range(chip, vbat_temp_cur); |
| break; |
| default: |
| break; |
| } |
| |
| vooc_xlog_printk(CHG_LOG_CRTI, "the ret: %d, the temp =%d, temp_status = %d, temp_range = %d\r\n", |
| ret, vbat_temp_cur, chip->fastchg_batt_temp_status, chip->vooc_temp_cur_range); |
| return ret; |
| } |
| |
| static int oplus_vooc_set_current_2_temp_normal_range(struct oplus_vooc_chip *chip, int vbat_temp_cur){ |
| int ret = 0; |
| |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| |
| switch (chip->fastchg_batt_temp_status) { |
| case BAT_TEMP_NORMAL_HIGH: |
| if (vbat_temp_cur > chip->vooc_strategy2_batt_up_temp1) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH0; |
| ret = chip->vooc_strategy2_high0_current; |
| } else if (vbat_temp_cur >= chip->vooc_normal_low_temp) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| ret = chip->vooc_strategy_normal_current; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_normal_low_temp += VOOC_TEMP_RANGE_THD; |
| } |
| break; |
| case BAT_TEMP_HIGH0: |
| if (vbat_temp_cur > chip->vooc_strategy2_batt_up_temp3) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH1; |
| ret = chip->vooc_strategy2_high1_current; |
| } else if (vbat_temp_cur < chip->vooc_normal_low_temp) { /*T<25*/ |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_normal_low_temp += VOOC_TEMP_RANGE_THD; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH0; |
| ret = chip->vooc_strategy2_high0_current; |
| } |
| break; |
| case BAT_TEMP_HIGH1: |
| if (vbat_temp_cur > chip->vooc_strategy2_batt_up_temp5) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH2; |
| ret = chip->vooc_strategy2_high2_current; |
| } else if (vbat_temp_cur < chip->vooc_normal_low_temp) { /*T<25*/ |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_LOW; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_LOW; |
| ret = chip->vooc_strategy_normal_current; |
| oplus_vooc_reset_temp_range(chip); |
| chip->vooc_normal_low_temp += VOOC_TEMP_RANGE_THD; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH1; |
| ret = chip->vooc_strategy2_high1_current; |
| } |
| break; |
| case BAT_TEMP_HIGH2: |
| if (vbat_temp_cur > chip->vooc_strategy2_batt_up_temp6) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH3; |
| ret = chip->vooc_strategy2_high3_current; |
| } else if (vbat_temp_cur < chip->vooc_strategy2_batt_up_down_temp2) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH1; |
| ret = chip->vooc_strategy2_high1_current; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH2; |
| ret = chip->vooc_strategy2_high2_current; |
| } |
| break; |
| case BAT_TEMP_HIGH3: |
| if (chip->vooc_batt_over_high_temp != -EINVAL |
| && vbat_temp_cur > chip->vooc_batt_over_high_temp) { |
| chip->vooc_strategy_change_count++; |
| if (chip->vooc_strategy_change_count >= VOOC_TEMP_OVER_COUNTS) { |
| chip->vooc_strategy_change_count = 0; |
| chip->fastchg_batt_temp_status = BAT_TEMP_EXIT; |
| ret = chip->vooc_over_high_or_low_current; |
| } |
| } else if (vbat_temp_cur < chip->vooc_strategy2_batt_up_down_temp4) { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH2; |
| ret = chip->vooc_strategy2_high2_current; |
| } else { |
| chip->fastchg_batt_temp_status = BAT_TEMP_HIGH3; |
| ret = chip->vooc_strategy2_high3_current; |
| } |
| break; |
| default: |
| break; |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, "the ret: %d, the temp =%d\r\n", ret, vbat_temp_cur); |
| return ret; |
| } |
| static int oplus_vooc_set_current_when_up_setting_batt_temp |
| (struct oplus_vooc_chip *chip, int vbat_temp_cur) |
| { |
| int ret = 0; |
| |
| if (chip->vooc_temp_cur_range == FASTCHG_TEMP_RANGE_INIT) { |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_NORMAL_HIGH; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NORMAL_HIGH; |
| } |
| |
| ret = oplus_vooc_set_current_2_temp_normal_range(chip, vbat_temp_cur); |
| |
| vooc_xlog_printk(CHG_LOG_CRTI, "the ret: %d, the temp =%d, temp_status = %d, temp_range = %d\r\n", |
| ret, vbat_temp_cur, chip->fastchg_batt_temp_status, chip->vooc_temp_cur_range); |
| return ret; |
| } |
| |
| int oplus_vooc_get_smaller_battemp_cooldown(int ret_batt, int ret_cool){ |
| int ret_batt_current =0; |
| int ret_cool_current = 0; |
| int i = 0; |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| int *current_level = NULL; |
| int array_len = 0; |
| |
| if (g_vooc_chip->vooc_current_lvl_cnt > 0) { |
| current_level = g_vooc_chip->vooc_current_lvl; |
| array_len = g_vooc_chip->vooc_current_lvl_cnt; |
| } else { |
| current_level = multistepCurrent; |
| array_len = ARRAY_SIZE(multistepCurrent); |
| } |
| |
| if(ret_batt > 0 && ret_batt < (array_len + 1) |
| && ret_cool > 0 && ret_cool < (array_len + 1)) { |
| ret_batt_current = current_level[ret_batt -1]; |
| ret_cool_current = current_level[ret_cool -1]; |
| oplus_chg_debug_get_cooldown_current(ret_batt_current, ret_cool_current); |
| ret_cool_current = ret_cool_current < ret_batt_current ? ret_cool_current : ret_batt_current; |
| |
| if(ret_cool > 0) { |
| if(ret_cool_current < ret_batt_current) { |
| /*set flag cool down by user */ |
| oplus_chg_debug_set_cool_down_by_user(1); |
| } else { |
| /*clear flag cool down by user */ |
| oplus_chg_debug_set_cool_down_by_user(0); |
| } |
| } |
| |
| for(i = 0 ; i < array_len; i++) { |
| if (current_level[i] == ret_cool_current) { |
| if (chip) { |
| chip->vooc_chg_current_now = ret_cool_current; |
| } |
| return i + 1; |
| } |
| } |
| } |
| |
| return -1; |
| } |
| |
| int oplus_vooc_get_cool_down_valid(void) { |
| int cool_down = oplus_chg_get_cool_down_status(); |
| if(!g_vooc_chip) { |
| pr_err("VOOC NULL ,return!!"); |
| return 0; |
| } |
| if (g_vooc_chip->vooc_multistep_adjust_current_support == true) { |
| if(g_vooc_chip->vooc_reply_mcu_bits == 7) { |
| return cool_down; |
| } else { |
| if(cool_down > 6 || cool_down < 0) |
| cool_down = 6; |
| } |
| } |
| |
| return cool_down; |
| } |
| |
| static void oplus_vooc_fastchg_func(struct work_struct *work) |
| { |
| struct delayed_work *dwork = to_delayed_work(work); |
| struct oplus_vooc_chip *chip = container_of(dwork, struct oplus_vooc_chip, fastchg_work); |
| int i = 0; |
| int bit = 0; |
| int data = 0; |
| int ret_info = 0; |
| int ret_info_temp = 0; |
| int ret_rst = 0; |
| static int pre_ret_info = 0; |
| static int select_func_flag = 0; |
| static bool first_detect_batt_temp = false; |
| static bool isnot_power_on = true; |
| static bool fw_ver_info = false; |
| static bool adapter_fw_ver_info = false; |
| static bool data_err = false; |
| static bool adapter_model_factory = false; |
| int volt = oplus_chg_get_batt_volt(); |
| int temp = oplus_chg_get_chg_temperature(); |
| int soc = oplus_chg_get_soc(); |
| int current_now = oplus_chg_get_icharging(); |
| int chg_vol = oplus_chg_get_charger_voltage(); |
| int remain_cap = 0; |
| static bool phone_mcu_updated = false; |
| static bool normalchg_disabled = false; |
| /* |
| if (!g_adapter_chip) { |
| chg_err(" g_adapter_chip NULL\n"); |
| return; |
| } |
| */ |
| usleep_range(2000, 2000); |
| if (chip->vops->get_gpio_ap_data(chip) != 1) { |
| /*vooc_xlog_printk(CHG_LOG_CRTI, " Shield fastchg irq, return\r\n");*/ |
| return; |
| } |
| |
| chip->vops->eint_unregist(chip); |
| for (i = 0; i < 7; i++) { |
| bit = chip->vops->read_ap_data(chip); |
| data |= bit << (6-i); |
| if ((i == 2) && (data != 0x50) && (!fw_ver_info) |
| && (!adapter_fw_ver_info) && (!adapter_model_factory)) { /*data recvd not start from "101"*/ |
| vooc_xlog_printk(CHG_LOG_CRTI, " data err:0x%x\n", data); |
| chip->allow_reading = true; |
| if (chip->fastchg_started == true) { |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| adapter_fw_ver_info = false; |
| /*chip->adapter_update_real = ADAPTER_FW_UPDATE_NONE;*/ |
| /*chip->adapter_update_report = chip->adapter_update_real;*/ |
| chip->btb_temp_over = false; |
| oplus_set_fg_i2c_err_occured(false); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| data_err = true; |
| if (chip->fastchg_dummy_started) { |
| chg_vol = oplus_chg_get_charger_voltage(); |
| if (chg_vol >= 0 && chg_vol < 2000) { |
| chip->fastchg_dummy_started = false; |
| oplus_chg_clear_chargerid_info(); |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| "chg_vol:%d dummy_started:false\n", chg_vol); |
| } |
| } else { |
| oplus_chg_clear_chargerid_info(); |
| } |
| ///del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| } |
| oplus_vooc_set_awake(chip, false); |
| goto out; |
| } |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, " recv data:0x%x, ap:0x%x, mcu:0x%x\n", |
| data, chip->fw_data_version, chip->fw_mcu_version); |
| |
| if (data == VOOC_NOTIFY_FAST_PRESENT) { |
| oplus_vooc_set_awake(chip, true); |
| oplus_set_fg_i2c_err_occured(false); |
| chip->need_to_up = 0; |
| fw_ver_info = false; |
| pre_ret_info = (chip->vooc_reply_mcu_bits == 7) ? 0x0c : 0x06; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| data_err = false; |
| phone_mcu_updated = false; |
| normalchg_disabled = false; |
| first_detect_batt_temp = true; |
| chip->fastchg_batt_temp_status = BAT_TEMP_NATURAL; |
| chip->vooc_temp_cur_range = FASTCHG_TEMP_RANGE_INIT; |
| if (chip->adapter_update_real == ADAPTER_FW_UPDATE_FAIL) { |
| chip->adapter_update_real = ADAPTER_FW_UPDATE_NONE; |
| chip->adapter_update_report = chip->adapter_update_real; |
| } |
| if (oplus_vooc_get_fastchg_allow() == true) { |
| oplus_chg_set_input_current_without_aicl(1200); |
| chip->allow_reading = false; |
| chip->fastchg_started = true; |
| chip->fastchg_ing = false; |
| chip->fastchg_dummy_started = false; |
| chip->fastchg_to_warm = false; |
| chip->btb_temp_over = false; |
| chip->reset_adapter = false; |
| } else { |
| chip->allow_reading = false; |
| chip->fastchg_dummy_started = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| oplus_vooc_set_awake(chip, false); |
| } |
| //mod_timer(&chip->watchdog, jiffies+msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| if (!isnot_power_on) { |
| isnot_power_on = true; |
| ret_info = 0x1; |
| } else { |
| ret_info = 0x2; |
| } |
| } else if (data == VOOC_NOTIFY_FAST_ABSENT) { |
| /* Zhangkun@BSP.CHG.Basic, 2020/08/17, Add for svooc detect and detach */ |
| chip->detach_unexpectly = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| oplus_set_fg_i2c_err_occured(false); |
| if (chip->fastchg_dummy_started) { |
| chg_vol = oplus_chg_get_charger_voltage(); |
| if (chg_vol >= 0 && chg_vol < 2000) { |
| chip->fastchg_dummy_started = false; |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| oplus_chg_clear_chargerid_info(); |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| "chg_vol:%d dummy_started:false\n", chg_vol); |
| } |
| } else { |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| oplus_chg_clear_chargerid_info(); |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| "fastchg stop unexpectly, switch off fastchg\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| //del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| chip->allow_reading = true; |
| ret_info = 0x2; |
| } else if (data == VOOC_NOTIFY_ADAPTER_MODEL_FACTORY) { |
| vooc_xlog_printk(CHG_LOG_CRTI, " VOOC_NOTIFY_ADAPTER_MODEL_FACTORY!\n"); |
| /*ready to get adapter_model_factory*/ |
| adapter_model_factory = 1; |
| ret_info = 0x2; |
| } else if (adapter_model_factory) { |
| vooc_xlog_printk(CHG_LOG_CRTI, "VOOC_NOTIFY_ADAPTER_MODEL_FACTORY:0x%x, \n", data); |
| //chip->fast_chg_type = data; |
| if (data == 0) { |
| chip->fast_chg_type = CHARGER_SUBTYPE_FASTCHG_VOOC; |
| } else { |
| chip->fast_chg_type = oplus_vooc_convert_fast_chg_type(data); |
| } |
| adapter_model_factory = 0; |
| if (chip->fast_chg_type == 0x0F |
| || chip->fast_chg_type == 0x1F |
| || chip->fast_chg_type == 0x3F |
| || chip->fast_chg_type == 0x7F) { |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| adapter_fw_ver_info = false; |
| oplus_set_fg_i2c_err_occured(false); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| data_err = true; |
| } |
| ret_info = 0x2; |
| } else if (data == VOOC_NOTIFY_ALLOW_READING_IIC) { |
| if(chip->fastchg_allow) { |
| /* Zhangkun@BSP.CHG.Basic, 2020/08/17, Add for svooc detect and detach */ |
| chip->detach_unexpectly = false; |
| chip->fastchg_ing = true; |
| chip->allow_reading = true; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| soc = oplus_gauge_get_batt_soc(); |
| oplus_chg_get_charger_voltage(); |
| if (oplus_get_fg_i2c_err_occured() == false) { |
| volt = oplus_gauge_get_batt_mvolts(); |
| } |
| if (oplus_get_fg_i2c_err_occured() == false) { |
| oplus_gauge_get_batt_temperature(); |
| if (!chip->temp_range_init) { |
| temp = oplus_chg_match_temp_for_chging(); |
| } |
| chip->temp_range_init = false; |
| } |
| if (oplus_get_fg_i2c_err_occured() == false) { |
| current_now = oplus_gauge_get_batt_current(); |
| } |
| if (oplus_get_fg_i2c_err_occured() == false) { |
| remain_cap = oplus_gauge_get_remaining_capacity(); |
| oplus_gauge_get_batt_fcc(); |
| oplus_gauge_get_batt_fc(); |
| oplus_gauge_get_batt_qm(); |
| oplus_gauge_get_batt_pd(); |
| oplus_gauge_get_batt_rcu(); |
| oplus_gauge_get_batt_rcf(); |
| oplus_gauge_get_batt_fcu(); |
| oplus_gauge_get_batt_fcf(); |
| oplus_gauge_get_batt_sou(); |
| oplus_gauge_get_batt_do0(); |
| oplus_gauge_get_batt_doe(); |
| oplus_gauge_get_batt_trm(); |
| oplus_gauge_get_batt_pc(); |
| oplus_gauge_get_batt_qs(); |
| } |
| oplus_chg_kick_wdt(); |
| if (chip->support_vooc_by_normal_charger_path) {//65w |
| if(!normalchg_disabled && chip->fast_chg_type != FASTCHG_CHARGER_TYPE_UNKOWN |
| && chip->fast_chg_type != CHARGER_SUBTYPE_FASTCHG_VOOC) { |
| oplus_chg_disable_charge(); |
| oplus_chg_suspend_charger(); |
| normalchg_disabled = true; |
| } |
| } else { |
| if(!normalchg_disabled) { |
| oplus_chg_disable_charge(); |
| normalchg_disabled = true; |
| } |
| } |
| //don't read |
| chip->allow_reading = false; |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, " volt:%d,temp:%d,soc:%d,current_now:%d,rm:%d, i2c_err:%d\n", |
| volt, temp, soc, current_now, remain_cap, oplus_get_fg_i2c_err_occured()); |
| //mod_timer(&chip->watchdog, jiffies+msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| if (chip->disable_adapter_output == true) { |
| ret_info = (chip->vooc_multistep_adjust_current_support |
| && (!(chip->support_vooc_by_normal_charger_path |
| && chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC))) |
| ? 0x07 : 0x03; |
| } else if (chip->set_vooc_current_limit == VOOC_MAX_CURRENT_LIMIT_2A |
| || (!(chip->support_vooc_by_normal_charger_path |
| && chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC) |
| && oplus_chg_get_cool_down_status() >= 1)) { |
| ret_info = oplus_vooc_get_cool_down_valid(); |
| pr_info("%s:origin cool_down ret_info=%d\n", __func__, ret_info); |
| ret_info = (chip->vooc_multistep_adjust_current_support |
| && (!(chip->support_vooc_by_normal_charger_path |
| && chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC))) |
| ? ret_info : 0x01; |
| pr_info("%s:recheck cool_down ret_info=%d\n", __func__, ret_info); |
| vooc_xlog_printk(CHG_LOG_CRTI, "ret_info:%d\n", ret_info); |
| } else { |
| if ((chip->vooc_multistep_adjust_current_support |
| && (!(chip->support_vooc_by_normal_charger_path |
| && chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC)))) { |
| if (chip->vooc_reply_mcu_bits == 7) { |
| ret_info = 0xC; |
| } else { |
| ret_info = 0x06; |
| } |
| } else { |
| ret_info = 0x02; |
| } |
| } |
| |
| if (chip->vooc_multistep_adjust_current_support |
| && chip->disable_adapter_output == false |
| && (!(chip->support_vooc_by_normal_charger_path |
| && chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC))) { |
| if (first_detect_batt_temp) { |
| if (temp < chip->vooc_multistep_initial_batt_temp) { |
| select_func_flag = 1; |
| } else { |
| select_func_flag = 2; |
| } |
| first_detect_batt_temp = false; |
| } |
| if (select_func_flag == 1) { |
| ret_info_temp = oplus_vooc_set_current_when_bleow_setting_batt_temp(chip, temp); |
| } else { |
| ret_info_temp = oplus_vooc_set_current_when_up_setting_batt_temp(chip, temp); |
| } |
| ret_rst = oplus_vooc_get_smaller_battemp_cooldown(ret_info_temp , ret_info); |
| if(ret_rst > 0) |
| ret_info = ret_rst; |
| } |
| |
| if ((chip->vooc_multistep_adjust_current_support == true) && (soc > 85)) { |
| ret_rst = oplus_vooc_get_smaller_battemp_cooldown(pre_ret_info , ret_info); |
| if(ret_rst > 0) { |
| ret_info = ret_rst; |
| } |
| pre_ret_info = (ret_info <= 3) ? 3 : ret_info; |
| } else if ((chip->vooc_multistep_adjust_current_support == true) && (soc > 75)) { |
| ret_rst = oplus_vooc_get_smaller_battemp_cooldown(pre_ret_info , ret_info); |
| if(ret_rst > 0) { |
| ret_info = ret_rst; |
| } |
| pre_ret_info = (ret_info <= 5) ? 5 : ret_info; |
| } else { |
| pre_ret_info = ret_info; |
| } |
| |
| vooc_xlog_printk(CHG_LOG_CRTI, "temp_range[%d-%d-%d-%d-%d]", chip->vooc_low_temp, chip->vooc_little_cold_temp, |
| chip->vooc_cool_temp, chip->vooc_little_cool_temp, chip->vooc_normal_low_temp, chip->vooc_high_temp); |
| vooc_xlog_printk(CHG_LOG_CRTI, " volt:%d,temp:%d,soc:%d,current_now:%d,rm:%d, i2c_err:%d, ret_info:%d\n", |
| volt, temp, soc, current_now, remain_cap, oplus_get_fg_i2c_err_occured(), ret_info); |
| } else if (data == VOOC_NOTIFY_NORMAL_TEMP_FULL) { |
| vooc_xlog_printk(CHG_LOG_CRTI, "VOOC_NOTIFY_NORMAL_TEMP_FULL\r\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| //del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| ret_info = 0x2; |
| } else if (data == VOOC_NOTIFY_LOW_TEMP_FULL) { |
| if (oplus_vooc_get_reply_bits() == 7) { |
| chip->temp_range_init = true; |
| chip->w_soc_temp_to_mcu = true; |
| temp = oplus_chg_match_temp_for_chging(); |
| soc = oplus_gauge_get_batt_soc(); |
| oplus_vooc_init_temp_range(chip, temp); |
| oplus_vooc_init_soc_range(chip, soc); |
| if (chip->vooc_temp_cur_range) { |
| ret_info = (chip->soc_range << 4) | (chip->vooc_temp_cur_range - 1); |
| } else { |
| ret_info = (chip->soc_range << 4) | 0x0; |
| } |
| } else { |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| " fastchg low temp full, switch NORMAL_CHARGER_MODE\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| //del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| ret_info = 0x2; |
| } |
| } else if (data == VOOC_NOTIFY_BAD_CONNECTED || data == VOOC_NOTIFY_DATA_UNKNOWN) { |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| " fastchg bad connected, switch NORMAL_CHARGER_MODE\n"); |
| /*usb bad connected, stop fastchg*/ |
| chip->btb_temp_over = false; /*to switch to normal mode*/ |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| //del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| ret_info = 0x2; |
| charger_abnormal_log = CRITICAL_LOG_VOOC_BAD_CONNECTED; |
| } else if (data == VOOC_NOTIFY_TEMP_OVER) { |
| /*fastchg temp over 45 or under 20*/ |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| " fastchg temp > 45 or < 20, switch NORMAL_CHARGER_MODE\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| //del_timer(&chip->watchdog); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_del_watchdog_timer(chip); |
| ret_info = 0x2; |
| } else if (data == VOOC_NOTIFY_BTB_TEMP_OVER) { |
| vooc_xlog_printk(CHG_LOG_CRTI, " btb_temp_over\n"); |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = true; |
| chip->fastchg_dummy_started = false; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| //mod_timer(&chip->watchdog, jiffies + msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| ret_info = 0x2; |
| charger_abnormal_log = CRITICAL_LOG_VOOC_BTB; |
| } else if (data == VOOC_NOTIFY_FIRMWARE_UPDATE) { |
| vooc_xlog_printk(CHG_LOG_CRTI, " firmware update, get fw_ver ready!\n"); |
| /*ready to get fw_ver*/ |
| fw_ver_info = 1; |
| ret_info = 0x2; |
| } else if (fw_ver_info && chip->firmware_data != NULL) { |
| /*get fw_ver*/ |
| /*fw in local is large than mcu1503_fw_ver*/ |
| if (!chip->have_updated |
| && chip->firmware_data[chip->fw_data_count- 4] != data) { |
| ret_info = 0x2; |
| chip->need_to_up = 1; /*need to update fw*/ |
| isnot_power_on = false; |
| } else { |
| ret_info = 0x1; |
| chip->need_to_up = 0; /*fw is already new, needn't to up*/ |
| adapter_fw_ver_info = true; |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, "local_fw:0x%x, need_to_up_fw:%d\n", |
| chip->firmware_data[chip->fw_data_count- 4], chip->need_to_up); |
| fw_ver_info = 0; |
| } else if (adapter_fw_ver_info) { |
| #if 0 |
| if (g_adapter_chip->adapter_firmware_data[g_adapter_chip->adapter_fw_data_count - 4] > data |
| && (oplus_gauge_get_batt_soc() > 2) && (chip->vops->is_power_off_charging(chip) == false) |
| && (chip->adapter_update_real != ADAPTER_FW_UPDATE_SUCCESS)) { |
| #else |
| if (0) { |
| #endif |
| ret_info = 0x02; |
| chip->adapter_update_real = ADAPTER_FW_NEED_UPDATE; |
| chip->adapter_update_report = chip->adapter_update_real; |
| } else { |
| ret_info = 0x01; |
| chip->adapter_update_real = ADAPTER_FW_UPDATE_NONE; |
| chip->adapter_update_report = chip->adapter_update_real; |
| } |
| adapter_fw_ver_info = false; |
| //mod_timer(&chip->watchdog, jiffies + msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| } else if (data == VOOC_NOTIFY_ADAPTER_FW_UPDATE) { |
| oplus_vooc_set_awake(chip, true); |
| ret_info = 0x02; |
| chip->adapter_update_real = ADAPTER_FW_NEED_UPDATE; |
| chip->adapter_update_report = chip->adapter_update_real; |
| //mod_timer(&chip->watchdog, jiffies + msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| } else { |
| oplus_chg_set_chargerid_switch_val(0); |
| oplus_chg_clear_chargerid_info(); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| chip->vops->reset_mcu(chip); |
| msleep(100); /*avoid i2c conflict*/ |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| data_err = true; |
| vooc_xlog_printk(CHG_LOG_CRTI, |
| " data err, set 0x101, data=0x%x switch off fastchg\n", data); |
| goto out; |
| } |
| |
| if (chip->fastchg_batt_temp_status == BAT_TEMP_EXIT) { |
| vooc_xlog_printk(CHG_LOG_CRTI, "chivas for zy0603 bug The temperature is lower than 12 du during the fast charging process\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| oplus_vooc_set_mcu_sleep(); |
| oplus_vooc_reset_mcu(); |
| oplus_vooc_del_watchdog_timer(chip); |
| oplus_vooc_set_awake(chip, false); |
| oplus_chg_unsuspend_charger(); |
| } |
| |
| msleep(2); |
| chip->vops->set_data_sleep(chip); |
| chip->vops->reply_mcu_data(chip, ret_info, oplus_gauge_get_device_type_for_vooc()); |
| |
| out: |
| chip->vops->set_data_active(chip); |
| chip->vops->set_clock_active(chip); |
| usleep_range(10000, 10000); |
| chip->vops->set_clock_sleep(chip); |
| usleep_range(25000, 25000); |
| if (chip->fastchg_batt_temp_status == BAT_TEMP_EXIT) { |
| usleep_range(350000, 350000); |
| chip->allow_reading = true; |
| chip->fastchg_ing = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_started = false; |
| if(oplus_vooc_is_battemp_exit()) { |
| chip->fastchg_to_warm = true; |
| chip->fastchg_dummy_started = false; |
| } else { |
| chip->fastchg_to_warm = false; |
| chip->fastchg_dummy_started = true; |
| } |
| } |
| if (data == VOOC_NOTIFY_NORMAL_TEMP_FULL || data == VOOC_NOTIFY_BAD_CONNECTED || data == VOOC_NOTIFY_DATA_UNKNOWN) { |
| usleep_range(350000, 350000); |
| chip->allow_reading = true; |
| chip->fastchg_ing = false; |
| chip->fastchg_to_normal = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_warm = false; |
| if (data == VOOC_NOTIFY_BAD_CONNECTED || data == VOOC_NOTIFY_DATA_UNKNOWN) |
| charger_abnormal_log = CRITICAL_LOG_VOOC_BAD_CONNECTED; |
| } else if (data == VOOC_NOTIFY_LOW_TEMP_FULL) { |
| if (oplus_vooc_get_reply_bits() != 7) { |
| usleep_range(350000, 350000); |
| chip->allow_reading = true; |
| chip->fastchg_ing = false; |
| chip->fastchg_low_temp_full = true; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_started = false; |
| chip->fastchg_to_warm = false; |
| } |
| } else if (data == VOOC_NOTIFY_TEMP_OVER) { |
| usleep_range(350000, 350000); |
| chip->fastchg_ing = false; |
| chip->fastchg_to_warm = true; |
| chip->allow_reading = true; |
| chip->fastchg_low_temp_full = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_started = false; |
| } |
| if (chip->need_to_up) { |
| msleep(500); |
| //del_timer(&chip->watchdog); |
| chip->vops->fw_update(chip); |
| chip->need_to_up = 0; |
| phone_mcu_updated = true; |
| //mod_timer(&chip->watchdog, jiffies + msecs_to_jiffies(25000)); |
| oplus_vooc_setup_watchdog_timer(chip, 25000); |
| } |
| if ((data == VOOC_NOTIFY_FAST_ABSENT || (data_err && !phone_mcu_updated) |
| || data == VOOC_NOTIFY_BTB_TEMP_OVER) |
| && (chip->fastchg_dummy_started == false)) { |
| oplus_chg_set_charger_type_unknown(); |
| oplus_chg_wake_update_work(); |
| } else if (data == VOOC_NOTIFY_NORMAL_TEMP_FULL |
| || data == VOOC_NOTIFY_TEMP_OVER |
| || data == VOOC_NOTIFY_BAD_CONNECTED |
| || data == VOOC_NOTIFY_DATA_UNKNOWN |
| || data == VOOC_NOTIFY_LOW_TEMP_FULL |
| || chip->fastchg_batt_temp_status == BAT_TEMP_EXIT) { |
| if (oplus_vooc_get_reply_bits() != 7 || data != VOOC_NOTIFY_LOW_TEMP_FULL) { |
| oplus_chg_set_charger_type_unknown(); |
| oplus_vooc_check_charger_out(chip); |
| } |
| } else if (data == VOOC_NOTIFY_BTB_TEMP_OVER) { |
| oplus_chg_set_charger_type_unknown(); |
| } |
| |
| if (chip->adapter_update_real != ADAPTER_FW_NEED_UPDATE) { |
| chip->vops->eint_regist(chip); |
| } |
| |
| if (chip->adapter_update_real == ADAPTER_FW_NEED_UPDATE) { |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_low_temp_full = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| //del_timer(&chip->watchdog); |
| oplus_vooc_del_watchdog_timer(chip); |
| oplus_vooc_battery_update(); |
| oplus_adapter_fw_update(); |
| oplus_vooc_set_awake(chip, false); |
| } else if ((data == VOOC_NOTIFY_FAST_PRESENT) |
| || (data == VOOC_NOTIFY_ALLOW_READING_IIC) |
| || (data == VOOC_NOTIFY_BTB_TEMP_OVER)) { |
| oplus_vooc_battery_update(); |
| if (oplus_vooc_get_reset_active_status() != 1 |
| && data == VOOC_NOTIFY_FAST_PRESENT) { |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| adapter_fw_ver_info = false; |
| adapter_model_factory = false; |
| chip->fastchg_dummy_started = false; |
| oplus_chg_set_charger_type_unknown(); |
| oplus_chg_clear_chargerid_info(); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| oplus_vooc_del_watchdog_timer(chip); |
| } |
| } else if ((data == VOOC_NOTIFY_LOW_TEMP_FULL) |
| || (data == VOOC_NOTIFY_FAST_ABSENT) |
| || (data == VOOC_NOTIFY_NORMAL_TEMP_FULL) |
| || (data == VOOC_NOTIFY_BAD_CONNECTED) |
| || (data == VOOC_NOTIFY_DATA_UNKNOWN) |
| || (data == VOOC_NOTIFY_TEMP_OVER) || oplus_vooc_is_battemp_exit()) { |
| if (oplus_vooc_get_reply_bits() != 7 || data != VOOC_NOTIFY_LOW_TEMP_FULL) { |
| if (!oplus_vooc_is_battemp_exit()) { |
| oplus_vooc_reset_temp_range(chip); |
| } |
| oplus_vooc_battery_update(); |
| #ifdef CHARGE_PLUG_IN_TP_AVOID_DISTURB |
| charge_plug_tp_avoid_distrub(1, is_oplus_fast_charger); |
| #endif |
| oplus_vooc_set_awake(chip, false); |
| } |
| } else if (data_err) { |
| data_err = false; |
| oplus_vooc_reset_temp_range(chip); |
| oplus_vooc_battery_update(); |
| #ifdef CHARGE_PLUG_IN_TP_AVOID_DISTURB |
| charge_plug_tp_avoid_distrub(1, is_oplus_fast_charger); |
| #endif |
| oplus_vooc_set_awake(chip, false); |
| } |
| if (chip->fastchg_started == false |
| && chip->fastchg_dummy_started == false |
| && chip->fastchg_to_normal == false |
| && chip->fastchg_to_warm == false){ |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| } |
| |
| } |
| |
| void fw_update_thread(struct work_struct *work) |
| { |
| struct delayed_work *dwork = to_delayed_work(work); |
| struct oplus_vooc_chip *chip = container_of(dwork, |
| struct oplus_vooc_chip, fw_update_work); |
| const struct firmware *fw = NULL; |
| int ret = 1; |
| int retry = 5; |
| char version[10]; |
| |
| if(chip->vooc_fw_update_newmethod) { |
| if(oplus_is_rf_ftm_mode()) { |
| chip->vops->fw_check_then_recover(chip); |
| return; |
| } |
| /* do { |
| ret = request_firmware_select(&fw, chip->fw_path, chip->dev); |
| if (!ret) { |
| break; |
| } |
| } while((ret < 0) && (--retry > 0)); |
| chg_debug(" retry times %d, chip->fw_path[%s]\n", 5 - retry, chip->fw_path); |
| */ |
| if(!ret) { |
| chip->firmware_data = fw->data; |
| chip->fw_data_count = fw->size; |
| chip->fw_data_version = chip->firmware_data[chip->fw_data_count - 4]; |
| chg_debug("count:0x%x, version:0x%x\n", |
| chip->fw_data_count,chip->fw_data_version); |
| if(chip->vops->fw_check_then_recover) { |
| ret = chip->vops->fw_check_then_recover(chip); |
| sprintf(version,"%d", chip->fw_data_version); |
| sprintf(chip->manufacture_info.version,"%s", version); |
| if (ret == FW_CHECK_MODE) { |
| chg_debug("update finish, then clean fastchg_dummy , fastchg_started, watch_dog\n"); |
| chip->fastchg_dummy_started = false; |
| chip->fastchg_started = false; |
| chip->allow_reading = true; |
| del_timer(&chip->watchdog); |
| } |
| } |
| release_firmware(fw); |
| chip->firmware_data = NULL; |
| } else { |
| chg_debug("%s: fw_name request failed, %d\n", __func__, ret); |
| } |
| }else { |
| ret = chip->vops->fw_check_then_recover(chip); |
| if (ret == FW_CHECK_MODE) { |
| chg_debug("update finish, then clean fastchg_dummy , fastchg_started, watch_dog\n"); |
| chip->fastchg_dummy_started = false; |
| chip->fastchg_started = false; |
| chip->allow_reading = true; |
| del_timer(&chip->watchdog); |
| } |
| } |
| chip->mcu_update_ing = false; |
| oplus_chg_unsuspend_charger(); |
| oplus_vooc_set_awake(chip, false); |
| } |
| |
| #define FASTCHG_FW_INTERVAL_INIT 1000 /* 1S */ |
| void oplus_vooc_fw_update_work_init(struct oplus_vooc_chip *chip) |
| { |
| INIT_DELAYED_WORK(&chip->fw_update_work, fw_update_thread); |
| schedule_delayed_work(&chip->fw_update_work, round_jiffies_relative(msecs_to_jiffies(FASTCHG_FW_INTERVAL_INIT))); |
| } |
| |
| void oplus_vooc_shedule_fastchg_work(void) |
| { |
| if (!g_vooc_chip) { |
| chg_err(" g_vooc_chip is NULL\n"); |
| } else { |
| schedule_delayed_work(&g_vooc_chip->fastchg_work, 0); |
| } |
| } |
| static ssize_t proc_fastchg_fw_update_write(struct file *file, const char __user *buff, |
| size_t len, loff_t *data) |
| { |
| struct oplus_vooc_chip *chip = PDE_DATA(file_inode(file)); |
| char write_data[32] = {0}; |
| |
| if (len > sizeof(write_data)) { |
| return -EINVAL; |
| } |
| |
| if (copy_from_user(&write_data, buff, len)) { |
| chg_err("fastchg_fw_update error.\n"); |
| return -EFAULT; |
| } |
| |
| if (write_data[0] == '1') { |
| chg_err("fastchg_fw_update\n"); |
| chip->fw_update_flag = 1; |
| schedule_delayed_work(&chip->fw_update_work, 0); |
| } else { |
| chip->fw_update_flag = 0; |
| chg_err("Disable fastchg_fw_update\n"); |
| } |
| |
| return len; |
| } |
| |
| static ssize_t proc_fastchg_fw_update_read(struct file *file, char __user *buff, |
| size_t count, loff_t *off) |
| { |
| struct oplus_vooc_chip *chip = PDE_DATA(file_inode(file)); |
| char page[256] = {0}; |
| char read_data[32] = {0}; |
| int len = 0; |
| |
| if(chip->fw_update_flag == 1) { |
| read_data[0] = '1'; |
| } else { |
| read_data[0] = '0'; |
| } |
| len = sprintf(page,"%s",read_data); |
| if(len > *off) { |
| len -= *off; |
| } else { |
| len = 0; |
| } |
| if (copy_to_user(buff,page,(len < count ? len : count))) { |
| return -EFAULT; |
| } |
| *off += len < count ? len : count; |
| return (len < count ? len : count); |
| } |
| |
| |
| static const struct file_operations fastchg_fw_update_proc_fops = { |
| .write = proc_fastchg_fw_update_write, |
| .read = proc_fastchg_fw_update_read, |
| }; |
| |
| static int init_proc_fastchg_fw_update(struct oplus_vooc_chip *chip) |
| { |
| struct proc_dir_entry *p = NULL; |
| |
| p = proc_create_data("fastchg_fw_update", 0664, NULL, &fastchg_fw_update_proc_fops,chip); |
| if (!p) { |
| pr_err("proc_create fastchg_fw_update_proc_fops fail!\n"); |
| } |
| return 0; |
| } |
| |
| static int init_vooc_proc(struct oplus_vooc_chip *chip) |
| { |
| strcpy(chip->manufacture_info.version, "0"); |
| if (get_vooc_mcu_type(chip) == OPLUS_VOOC_MCU_HWID_STM8S) { |
| snprintf(chip->fw_path, MAX_FW_NAME_LENGTH, "fastchg/%d/oplus_vooc_fw.bin", get_project()); |
| } else if (get_vooc_mcu_type(chip) == OPLUS_VOOC_MCU_HWID_N76E) { |
| snprintf(chip->fw_path, MAX_FW_NAME_LENGTH, "fastchg/%d/oplus_vooc_fw_n76e.bin", get_project()); |
| } else if (get_vooc_mcu_type(chip) == OPLUS_VOOC_ASIC_HWID_RK826) { |
| snprintf(chip->fw_path, MAX_FW_NAME_LENGTH, "fastchg/%d/oplus_vooc_fw_rk826.bin", get_project()); |
| } else { |
| snprintf(chip->fw_path, MAX_FW_NAME_LENGTH, "fastchg/%d/oplus_vooc_fw_op10.bin", get_project()); |
| } |
| memcpy(chip->manufacture_info.manufacture, chip->fw_path, MAX_FW_NAME_LENGTH); |
| register_devinfo("fastchg", &chip->manufacture_info); |
| init_proc_fastchg_fw_update(chip); |
| chg_debug(" version:%s, fw_path:%s\n", chip->manufacture_info.version, chip->fw_path); |
| return 0; |
| } |
| void oplus_vooc_init(struct oplus_vooc_chip *chip) |
| { |
| int ret = 0; |
| |
| /* Zhangkun@BSP.CHG.Basic, 2020/08/17, Add for svooc detect and detach */ |
| chip->detach_unexpectly = false; |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_dummy_started = false; |
| chip->fastchg_ing = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_allow = false; |
| chip->fastchg_low_temp_full = false; |
| chip->have_updated = false; |
| chip->need_to_up = false; |
| chip->btb_temp_over = false; |
| chip->adapter_update_real = ADAPTER_FW_UPDATE_NONE; |
| chip->adapter_update_report = chip->adapter_update_real; |
| chip->mcu_update_ing = true; |
| chip->mcu_boot_by_gpio = false; |
| chip->dpdm_switch_mode = NORMAL_CHARGER_MODE; |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| /*chip->batt_psy = power_supply_get_by_name("battery");*/ |
| chip->disable_adapter_output = false; |
| chip->set_vooc_current_limit = VOOC_MAX_CURRENT_NO_LIMIT; |
| chip->reset_adapter = false; |
| chip->temp_range_init = false; |
| chip->w_soc_temp_to_mcu = false; |
| oplus_vooc_init_watchdog_timer(chip); |
| |
| oplus_vooc_awake_init(chip); |
| INIT_DELAYED_WORK(&chip->fastchg_work, oplus_vooc_fastchg_func); |
| INIT_DELAYED_WORK(&chip->check_charger_out_work, check_charger_out_work_func); |
| INIT_WORK(&chip->vooc_watchdog_work, vooc_watchdog_work_func); |
| g_vooc_chip = chip; |
| chip->vops->eint_regist(chip); |
| if(chip->vooc_fw_update_newmethod) { |
| if(oplus_is_rf_ftm_mode()) { |
| return; |
| } |
| INIT_DELAYED_WORK(&chip->fw_update_work, fw_update_thread); |
| //Alloc fw_name/devinfo memory space |
| |
| chip->fw_path = kzalloc(MAX_FW_NAME_LENGTH, GFP_KERNEL); |
| if (chip->fw_path == NULL) { |
| ret = -ENOMEM; |
| chg_err("panel_data.fw_name kzalloc error\n"); |
| goto manu_fwpath_alloc_err; |
| } |
| chip->manufacture_info.version = kzalloc(MAX_DEVICE_VERSION_LENGTH, GFP_KERNEL); |
| if (chip->manufacture_info.version == NULL) { |
| ret = -ENOMEM; |
| chg_err("manufacture_info.version kzalloc error\n"); |
| goto manu_version_alloc_err; |
| } |
| chip->manufacture_info.manufacture = kzalloc(MAX_DEVICE_MANU_LENGTH, GFP_KERNEL); |
| if (chip->manufacture_info.manufacture == NULL) { |
| ret = -ENOMEM; |
| chg_err("panel_data.manufacture kzalloc error\n"); |
| goto manu_info_alloc_err; |
| } |
| init_vooc_proc(chip); |
| return; |
| |
| manu_fwpath_alloc_err: |
| kfree(chip->fw_path); |
| |
| manu_info_alloc_err: |
| kfree(chip->manufacture_info.manufacture); |
| |
| manu_version_alloc_err: |
| kfree(chip->manufacture_info.version); |
| } |
| return ; |
| } |
| |
| bool oplus_vooc_wake_fastchg_work(struct oplus_vooc_chip *chip) |
| { |
| return schedule_delayed_work(&chip->fastchg_work, 0); |
| } |
| |
| void oplus_vooc_print_log(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } |
| vooc_xlog_printk(CHG_LOG_CRTI, "VOOC[ %d / %d / %d / %d / %d / %d]\n", |
| g_vooc_chip->fastchg_allow, g_vooc_chip->fastchg_started, g_vooc_chip->fastchg_dummy_started, |
| g_vooc_chip->fastchg_to_normal, g_vooc_chip->fastchg_to_warm, g_vooc_chip->btb_temp_over); |
| } |
| |
| bool oplus_vooc_get_allow_reading(void) |
| { |
| if (!g_vooc_chip) { |
| return true; |
| } else { |
| if (g_vooc_chip->support_vooc_by_normal_charger_path |
| && g_vooc_chip->fast_chg_type == CHARGER_SUBTYPE_FASTCHG_VOOC) { |
| return true; |
| } else { |
| return g_vooc_chip->allow_reading; |
| } |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_started(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_started; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_ing(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_ing; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_allow(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_allow; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_allow(int enable) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fastchg_allow = enable; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_to_normal(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_to_normal; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_to_normal_false(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fastchg_to_normal = false; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_type_unknow(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_to_warm(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_to_warm; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_to_warm_false(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fastchg_to_warm = false; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_low_temp_full(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_low_temp_full; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_low_temp_full_false(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fastchg_low_temp_full = false; |
| } |
| } |
| |
| bool oplus_vooc_get_vooc_multistep_adjust_current_support(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->vooc_multistep_adjust_current_support; |
| } |
| } |
| |
| bool oplus_vooc_get_fastchg_dummy_started(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->fastchg_dummy_started; |
| } |
| } |
| |
| void oplus_vooc_set_fastchg_dummy_started_false(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->fastchg_dummy_started = false; |
| } |
| } |
| |
| int oplus_vooc_get_adapter_update_status(void) |
| { |
| if (!g_vooc_chip) { |
| return ADAPTER_FW_UPDATE_NONE; |
| } else { |
| return g_vooc_chip->adapter_update_report; |
| } |
| } |
| |
| int oplus_vooc_get_adapter_update_real_status(void) |
| { |
| if (!g_vooc_chip) { |
| return ADAPTER_FW_UPDATE_NONE; |
| } else { |
| return g_vooc_chip->adapter_update_real; |
| } |
| } |
| |
| bool oplus_vooc_get_btb_temp_over(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->btb_temp_over; |
| } |
| } |
| |
| void oplus_vooc_reset_fastchg_after_usbout(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->vops->reset_fastchg_after_usbout(g_vooc_chip); |
| } |
| } |
| |
| void oplus_vooc_switch_fast_chg(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->vops->switch_fast_chg(g_vooc_chip); |
| } |
| } |
| |
| void oplus_vooc_set_ap_clk_high(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->vops->set_clock_sleep(g_vooc_chip); |
| } |
| } |
| |
| void oplus_vooc_reset_mcu(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| g_vooc_chip->vops->reset_mcu(g_vooc_chip); |
| } |
| } |
| |
| void oplus_vooc_set_mcu_sleep(void) |
| { |
| if (!g_vooc_chip) { |
| return; |
| } else { |
| if (g_vooc_chip->vops->set_mcu_sleep) |
| g_vooc_chip->vops->set_mcu_sleep(g_vooc_chip); |
| } |
| } |
| |
| bool oplus_vooc_check_chip_is_null(void) |
| { |
| if (!g_vooc_chip) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| int oplus_vooc_get_vooc_switch_val(void) |
| { |
| if (!g_vooc_chip) { |
| return 0; |
| } else { |
| return g_vooc_chip->vops->get_switch_gpio_val(g_vooc_chip); |
| } |
| } |
| |
| void oplus_vooc_uart_init(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->vops->set_data_active(chip); |
| chip->vops->set_clock_sleep(chip); |
| } |
| } |
| |
| int oplus_vooc_get_uart_tx(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return -1; |
| } else { |
| return chip->vops->get_clk_gpio_num(chip); |
| } |
| } |
| |
| int oplus_vooc_get_uart_rx(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return -1; |
| } else { |
| return chip->vops->get_data_gpio_num(chip); |
| } |
| } |
| |
| |
| void oplus_vooc_uart_reset(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->vops->eint_regist(chip); |
| oplus_chg_set_chargerid_switch_val(0); |
| chip->vops->set_switch_mode(chip, NORMAL_CHARGER_MODE); |
| chip->vops->reset_mcu(chip); |
| } |
| } |
| |
| void oplus_vooc_set_adapter_update_real_status(int real) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->adapter_update_real = real; |
| } |
| } |
| |
| void oplus_vooc_set_adapter_update_report_status(int report) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->adapter_update_report = report; |
| } |
| } |
| |
| int oplus_vooc_get_fast_chg_type(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return FASTCHG_CHARGER_TYPE_UNKOWN; |
| } else { |
| return chip->fast_chg_type; |
| } |
| } |
| |
| static int oplus_vooc_convert_fast_chg_type(int fast_chg_type) |
| { |
| switch(fast_chg_type) { |
| case FASTCHG_CHARGER_TYPE_UNKOWN: |
| case 0x11: /*50w*/ |
| case 0x12: /*50w*/ |
| case 0x14: /*65w*/ |
| case 0x21: /*50w*/ |
| case 0x31: /*50w*/ |
| case 0x33: /*50w*/ |
| case 0x61: /*reserve for svooc*/ |
| case 0x62: /*reserve for svooc*/ |
| case 0x63: /*reserve for svooc*/ |
| case 0x64: /*reserve for svooc*/ |
| case 0x65: /*reserve for svooc*/ |
| case 0x66: /*reserve for svooc*/ |
| case 0x69: /*reserve for svooc*/ |
| case 0x6A: /*reserve for svooc*/ |
| case 0x6B: /*reserve for svooc*/ |
| case 0x6C: /*reserve for svooc*/ |
| case 0x6D: /*reserve for svooc*/ |
| case 0x6E: /*reserve for svooc*/ |
| case 0x0F: /*special code*/ |
| case 0x1F: /*special code*/ |
| case 0x3F: /*special code*/ |
| case 0x7F: /*special code*/ |
| return fast_chg_type; |
| break; |
| |
| default: |
| return CHARGER_SUBTYPE_FASTCHG_VOOC; |
| break; |
| } |
| |
| return FASTCHG_CHARGER_TYPE_UNKOWN; |
| } |
| |
| void oplus_vooc_set_disable_adapter_output(bool disable) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->disable_adapter_output = disable; |
| } |
| chg_err(" chip->disable_adapter_output:%d\n", chip->disable_adapter_output); |
| } |
| |
| void oplus_vooc_set_vooc_max_current_limit(int current_level) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return ; |
| } else { |
| chip->set_vooc_current_limit = current_level; |
| } |
| } |
| |
| void oplus_vooc_set_vooc_chargerid_switch_val(int value) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| |
| if (!chip) { |
| return; |
| } else if (chip->vops->set_vooc_chargerid_switch_val) { |
| chip->vops->set_vooc_chargerid_switch_val(chip, value); |
| } |
| } |
| |
| int oplus_vooc_get_reply_bits(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| |
| if (!chip) { |
| return 0; |
| } else { |
| return chip->vooc_reply_mcu_bits; |
| } |
| } |
| |
| void oplus_vooc_turn_off_fastchg(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return; |
| } |
| |
| chg_err("oplus_vooc_turn_off_fastchg\n"); |
| oplus_chg_set_chargerid_switch_val(0); |
| oplus_vooc_switch_mode(NORMAL_CHARGER_MODE); |
| if (chip->vops->set_mcu_sleep) { |
| chip->vops->set_mcu_sleep(chip); |
| |
| chip->allow_reading = true; |
| chip->fastchg_started = false; |
| chip->fastchg_to_normal = false; |
| chip->fastchg_to_warm = false; |
| chip->fastchg_ing = false; |
| chip->btb_temp_over = false; |
| chip->fastchg_dummy_started = false; |
| chip->fast_chg_type = FASTCHG_CHARGER_TYPE_UNKOWN; |
| |
| oplus_chg_clear_chargerid_info(); |
| oplus_vooc_del_watchdog_timer(chip); |
| oplus_chg_set_charger_type_unknown(); |
| oplus_chg_wake_update_work(); |
| oplus_vooc_set_awake(chip, false); |
| } |
| } |
| |
| bool opchg_get_mcu_update_state(void) |
| { |
| struct oplus_vooc_chip *chip = g_vooc_chip; |
| if (!chip) { |
| return false; |
| } |
| return chip->mcu_update_ing; |
| } |
| |
| |
| void oplus_vooc_get_vooc_chip_handle(struct oplus_vooc_chip **chip) { |
| *chip = g_vooc_chip; |
| } |
| |
| void oplus_vooc_reset_temp_range(struct oplus_vooc_chip *chip) |
| { |
| if (chip != NULL) { |
| chip->temp_range_init = false; |
| chip->w_soc_temp_to_mcu = false; |
| chip->vooc_little_cold_temp = chip->vooc_little_cold_temp_default; |
| chip->vooc_cool_temp = chip->vooc_cool_temp_default; |
| chip->vooc_little_cool_temp = chip->vooc_little_cool_temp_default; |
| chip->vooc_normal_low_temp = chip->vooc_normal_low_temp_default; |
| } |
| } |
| |
| |
| /* Zhangkun@BSP.CHG.Basic, 2020/08/17, Add for svooc detect and detach */ |
| bool oplus_vooc_get_detach_unexpectly(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| chg_err("detach_unexpectly = %d\n",g_vooc_chip->detach_unexpectly); |
| return g_vooc_chip->detach_unexpectly; |
| } |
| } |
| |
| void oplus_vooc_set_detach_unexpectly(bool val) |
| { |
| if (!g_vooc_chip) { |
| return ; |
| } else { |
| g_vooc_chip->detach_unexpectly = val; |
| chg_err("detach_unexpectly = %d\n",g_vooc_chip->detach_unexpectly); |
| } |
| } |
| |
| void oplus_vooc_set_disable_real_fast_chg(bool val) |
| { |
| if (!g_vooc_chip) { |
| return ; |
| } else { |
| g_vooc_chip->disable_real_fast_chg= val; |
| chg_err("disable_real_fast_chg = %d\n",g_vooc_chip->disable_real_fast_chg); |
| } |
| } |
| |
| bool oplus_vooc_get_reset_adapter_st(void) |
| { |
| if (!g_vooc_chip) { |
| return false; |
| } else { |
| return g_vooc_chip->reset_adapter; |
| } |
| } |
| |
| int oplus_vooc_get_reset_active_status(void) |
| { |
| int active_level = 0; |
| int mcu_hwid_type = OPLUS_VOOC_MCU_HWID_UNKNOW; |
| |
| if (!g_vooc_chip) { |
| return -EINVAL; |
| } else { |
| mcu_hwid_type = get_vooc_mcu_type(g_vooc_chip); |
| if (mcu_hwid_type == OPLUS_VOOC_ASIC_HWID_RK826 |
| || mcu_hwid_type == OPLUS_VOOC_ASIC_HWID_OP10 |
| || mcu_hwid_type == OPLUS_VOOC_ASIC_HWID_RT5125) { |
| active_level = 1; |
| } |
| if (active_level == g_vooc_chip->vops->get_reset_gpio_val(g_vooc_chip)) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } |
| } |