unplugged-kernel/drivers/power/supply/mediatek/battery_meter_fg_20.c

4802 lines
129 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h> /* For init/exit macros */
#include <linux/interrupt.h>
#include <linux/module.h> /* For MODULE_ marcros */
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/time.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#endif
#include <linux/kernel.h>
#include <linux/netlink.h>
#include <linux/reboot.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <net/genetlink.h>
#include <net/sock.h>
#include <mt-plat/mtk_boot.h>
#include <mt-plat/mtk_rtc.h>
#include <mach/mtk_battery_meter.h>
#include <mach/mtk_battery_meter_table.h>
#include <mach/mtk_pmic.h>
#include <mt-plat/battery_common.h>
#include <mt-plat/battery_meter.h>
#include <mt-plat/battery_meter_hal.h>
#include <mt-plat/upmu_common.h>
/* ============================================================ // */
/* define */
/* ============================================================ // */
#define PROFILE_SIZE 4
static DEFINE_MUTEX(FGADC_mutex);
int Enable_FGADC_LOG = BMLOG_INFO_LEVEL;
#define NETLINK_FGD 26
#define CUST_SETTING_VERSION 0x100000
#define FGD_CHECK_VERSION 0x100001
/* ============================================================ // */
/* global variable */
/* ============================================================ // */
BATTERY_METER_CONTROL battery_meter_ctrl;
kal_bool gFG_Is_Charging = KAL_FALSE;
kal_bool gFG_Is_Charging_init = KAL_FALSE;
signed int g_auxadc_solution;
unsigned int g_spm_timer = 600;
bool bat_spm_timeout;
struct timespec g_sleep_total_time;
#ifdef MTK_ENABLE_AGING_ALGORITHM
unsigned int suspend_total_time;
#endif
unsigned int add_time;
signed int g_booting_vbat;
/*static unsigned int temperature_change = 1;*/
static struct sock *daemo_nl_sk;
static void nl_send_to_user(u32 pid, int seq, struct fgd_nl_msg_t *reply_msg);
static u_int g_fgd_pid;
static unsigned int g_fgd_version = -1;
static kal_bool init_flag;
void battery_meter_set_init_flag(kal_bool flag)
{
init_flag = flag;
}
void battery_meter_reset_sleep_time(void)
{
g_sleep_total_time.tv_sec = 0;
g_sleep_total_time.tv_nsec = 0;
}
/* PMIC AUXADC Related Variable */
int g_R_BAT_SENSE = R_BAT_SENSE;
int g_R_I_SENSE = R_I_SENSE;
int g_R_CHARGER_1 = R_CHARGER_1;
int g_R_CHARGER_2 = R_CHARGER_2;
int gFG_result = 1;
int gFG_plugout_status;
int gFG_result_soc;
int fix_coverity1;
int fix_coverity2;
/* HW FG */
#ifndef DIFFERENCE_HWOCV_RTC
#define DIFFERENCE_HWOCV_RTC 30 /* 30% difference */
#endif
#ifndef DIFFERENCE_HWOCV_SWOCV
#define DIFFERENCE_HWOCV_SWOCV 15 /* 105% difference */
#endif
#ifndef DIFFERENCE_SWOCV_RTC
#define DIFFERENCE_SWOCV_RTC 10 /* 10% difference */
#endif
#ifndef DIFFERENCE_HWOCV_VBAT
#define DIFFERENCE_HWOCV_VBAT 30
#endif
#ifndef DIFFERENCE_VBAT_RTC
#define DIFFERENCE_VBAT_RTC 30
#endif
#ifndef DIFFERENCE_SWOCV_RTC_POS
#define DIFFERENCE_SWOCV_RTC_POS 15
#endif
#ifndef MAX_SWOCV
#define MAX_SWOCV 5 /* 5% maximum */
#endif
/* SW Fuel Gauge */
#ifndef MAX_HWOCV
#define MAX_HWOCV 5
#endif
#ifndef MAX_VBAT
#define MAX_VBAT 90
#endif
#ifndef Q_MAX_SYS_VOLTAGE
#define Q_MAX_SYS_VOLTAGE 3300
#endif
#ifndef CUST_TRACKING_GAP
#define CUST_TRACKING_GAP 15
#endif
#ifndef CUST_TRACKINGOFFSET
#define CUST_TRACKINGOFFSET 0
#endif
#ifndef CUST_TRACKINGEN
#define CUST_TRACKINGEN 0
#endif
/* smooth time tracking */
signed int gFG_coulomb_act_time = -1;
signed int gFG_coulomb_act_pre;
signed int gFG_coulomb_act_diff;
signed int gFG_coulomb_act_diff_time;
signed int gFG_coulomb_is_charging;
signed int gFG_DOD0_init;
signed int gFG_DOD0;
signed int gFG_DOD1;
signed int gFG_DOD_B;
signed int gFG_coulomb;
signed int gFG_coulomb_act;
signed int gFG_voltage;
signed int gFG_current;
signed int gFG_current_init;
signed int gFG_capacity;
signed int gFG_capacity_by_c = -1;
signed int gFG_capacity_by_c_init;
signed int gFG_capacity_by_v;
signed int gFG_capacity_by_v_init;
signed int gFG_temp = 100;
signed int gFG_temp_avg = 100;
signed int gFG_temp_avg_init = 100;
signed int gFG_resistance_bat;
signed int gFG_compensate_value;
signed int gFG_ori_voltage;
signed int gFG_BATT_CAPACITY;
signed int gFG_voltage_init;
signed int gFG_current_auto_detect_R_fg_total;
signed int gFG_current_auto_detect_R_fg_count;
signed int gFG_current_auto_detect_R_fg_result;
signed int gFG_15_vlot = 3700;
signed int gFG_BATT_CAPACITY_high_current = 1200;
signed int gFG_BATT_CAPACITY_aging = 1200;
signed int gFG_vbat;
signed int gFG_swocv;
signed int gFG_hwocv;
signed int gFG_vbat_soc;
signed int gFG_hw_soc;
signed int gFG_sw_soc;
#ifdef USING_SMOOTH_UI_SOC2
signed int temp_UI_SOC2 = -1;
signed int pre_UI_SOC2;
signed int UI_SOC3;
signed int pre_cc_act;
#endif
/* voltage mode */
signed int gfg_percent_check_point = 50;
signed int volt_mode_update_timer;
signed int volt_mode_update_time_out = 6; /* 1mins */
/* EM */
signed int g_fg_dbg_bat_volt;
signed int g_fg_dbg_bat_current;
signed int g_fg_dbg_bat_zcv;
signed int g_fg_dbg_bat_temp;
signed int g_fg_dbg_bat_r;
signed int g_fg_dbg_bat_car;
signed int g_fg_dbg_bat_qmax;
signed int g_fg_dbg_d0;
signed int g_fg_dbg_d1;
signed int g_fg_dbg_percentage;
signed int g_fg_dbg_percentage_fg;
signed int g_fg_dbg_percentage_voltmode;
signed int FGvbatVoltageBuffer[FG_VBAT_AVERAGE_SIZE];
signed int FGbatteryIndex;
signed int FGbatteryVoltageSum;
signed int gFG_voltage_AVG;
signed int gFG_vbat_offset;
signed int vbat_offset_counter;
#ifdef Q_MAX_BY_CURRENT
signed int FGCurrentBuffer[FG_CURRENT_AVERAGE_SIZE];
signed int FGCurrentIndex;
signed int FGCurrentSum;
#endif
signed int gFG_current_AVG;
signed int g_tracking_point = CUST_TRACKING_POINT;
signed int g_rtc_fg_soc;
signed int g_I_SENSE_offset;
/* SW FG */
signed int oam_v_ocv_init;
signed int oam_v_ocv_1;
signed int oam_v_ocv_2;
signed int oam_r_1;
signed int oam_r_2;
signed int oam_d0;
signed int oam_i_ori;
signed int oam_i_1;
signed int oam_i_2;
signed int oam_car_1;
signed int oam_car_2;
signed int oam_d_1 = 1;
signed int oam_d_2 = 1;
signed int oam_d_3 = 1;
signed int oam_d_3_pre;
signed int oam_d_4;
signed int oam_d_4_pre;
signed int oam_d_5;
signed int oam_init_i;
signed int oam_run_i;
signed int d5_count;
signed int d5_count_time = 60;
signed int d5_count_time_rate = 1;
signed int g_d_hw_ocv;
signed int g_vol_bat_hw_ocv;
/* SW FG 2.0 */
signed int oam_v_ocv;
signed int oam_r;
signed int swfg_ap_suspend_time;
signed int ap_suspend_car;
struct timespec ap_suspend_time;
signed int total_suspend_times;
signed int this_suspend_times;
signed int last_hwocv;
signed int last_i;
signed int hwocv_token;
signed int is_hwocv_update;
signed int g_hw_ocv_before_sleep;
struct timespec suspend_time, car_time;
signed int g_sw_vbat_temp;
struct timespec last_oam_run_time;
/*static signed int coulomb_before_sleep = 0x123456;*/
#if !defined(CONFIG_POWER_EXT)
static signed int last_time = 1;
#endif
/* aging mechanism */
#ifdef MTK_ENABLE_AGING_ALGORITHM
#ifndef SUSPEND_CURRENT_CHECK_THRESHOLD
#define SUSPEND_CURRENT_CHECK_THRESHOLD 100 /* 10mA */
#endif
#ifndef DIFFERENCE_VOLTAGE_UPDATE
#define DIFFERENCE_VOLTAGE_UPDATE 20 /* 20mV */
#endif
#ifndef OCV_RECOVER_TIME
#define OCV_RECOVER_TIME 2100
#endif
#ifndef AGING1_UPDATE_SOC
#define AGING1_UPDATE_SOC 30
#endif
#ifndef AGING1_LOAD_SOC
#define AGING1_LOAD_SOC 70
#endif
#ifndef MIN_DOD_DIFF_THRESHOLD
#define MIN_DOD_DIFF_THRESHOLD 40
#endif
#ifndef MIN_DOD2_DIFF_THRESHOLD
#define MIN_DOD2_DIFF_THRESHOLD 70
#endif
#ifndef CHARGE_TRACKING_TIME
#define CHARGE_TRACKING_TIME 60
#endif
#ifndef DISCHARGE_TRACKING_TIME
#define DISCHARGE_TRACKING_TIME 10
#endif
static signed int suspend_current_threshold = SUSPEND_CURRENT_CHECK_THRESHOLD;
static signed int ocv_check_time = OCV_RECOVER_TIME;
static signed int difference_voltage_update = DIFFERENCE_VOLTAGE_UPDATE;
static signed int aging1_load_soc = AGING1_LOAD_SOC;
static signed int aging1_update_soc = AGING1_UPDATE_SOC;
static signed int shutdown_system_voltage = SHUTDOWN_SYSTEM_VOLTAGE;
static signed int charge_tracking_time = CHARGE_TRACKING_TIME;
static signed int discharge_tracking_time = DISCHARGE_TRACKING_TIME;
#endif /* aging mechanism */
#ifndef RECHARGE_TOLERANCE
#define RECHARGE_TOLERANCE 10
#endif
/*static signed int recharge_tolerance = RECHARGE_TOLERANCE;*/
#ifdef SHUTDOWN_GAUGE0
static signed int shutdown_gauge0 = 1;
#else
static signed int shutdown_gauge0;
#endif
#ifdef SHUTDOWN_GAUGE1_MINS
static signed int shutdown_gauge1_xmins = 1;
#else
static signed int shutdown_gauge1_xmins;
#endif
#ifndef FG_CURRENT_INIT_VALUE
#define FG_CURRENT_INIT_VALUE 3500
#endif
#ifndef FG_MIN_CHARGING_SMOOTH_TIME
#define FG_MIN_CHARGING_SMOOTH_TIME 40
#endif
#ifndef APSLEEP_MDWAKEUP_CAR
#define APSLEEP_MDWAKEUP_CAR 5240
#endif
#ifndef AP_MDSLEEP_CAR
#define AP_MDSLEEP_CAR 30
#endif
#ifndef APSLEEP_BATTERY_VOLTAGE_COMPENSATE
#define APSLEEP_BATTERY_VOLTAGE_COMPENSATE 150
#endif
static signed int shutdown_gauge1_mins = SHUTDOWN_GAUGE1_MINS;
signed int gFG_battery_cycle;
signed int gFG_aging_factor_1 = 100;
signed int gFG_aging_factor_2 = 100;
signed int gFG_loading_factor1 = 100;
signed int gFG_loading_factor2 = 100;
/* battery info */
signed int gFG_coulomb_cyc;
signed int gFG_coulomb_aging;
signed int gFG_pre_coulomb_count = 0x12345678;
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
signed int gFG_max_voltage;
signed int gFG_min_voltage = 10000;
signed int gFG_max_current;
signed int gFG_min_current;
signed int gFG_max_temperature = -20;
signed int gFG_min_temperature = 100;
#endif /* battery info */
unsigned int g_sw_fg_version = 150327;
static signed int gFG_daemon_log_level = BM_DAEMON_DEFAULT_LOG_LEVEL;
static unsigned char gDisableFG;
/* ============================================================ // */
/* function prototype */
/* ============================================================ // */
int __attribute__((weak)) PMIC_IMM_GetCurrent(void)
{
battery_log(BAT_LOG_FULL, "wait for auxadc porting\n");
return 0;
}
struct battery_meter_table_custom_data {
/* cust_battery_meter_table.h */
int battery_profile_t0_size;
BATTERY_PROFILE_STRUCT battery_profile_t0[100];
int battery_profile_t1_size;
BATTERY_PROFILE_STRUCT battery_profile_t1[100];
int battery_profile_t2_size;
BATTERY_PROFILE_STRUCT battery_profile_t2[100];
int battery_profile_t3_size;
BATTERY_PROFILE_STRUCT battery_profile_t3[100];
int battery_profile_temperature_size;
BATTERY_PROFILE_STRUCT battery_profile_temperature[100];
int r_profile_t0_size;
R_PROFILE_STRUCT r_profile_t0[100];
int r_profile_t1_size;
R_PROFILE_STRUCT r_profile_t1[100];
int r_profile_t2_size;
R_PROFILE_STRUCT r_profile_t2[100];
int r_profile_t3_size;
R_PROFILE_STRUCT r_profile_t3[100];
int r_profile_temperature_size;
R_PROFILE_STRUCT r_profile_temperature[100];
};
struct battery_meter_custom_data batt_meter_cust_data;
struct battery_meter_table_custom_data batt_meter_table_cust_data;
/* Temperature window size */
#define TEMP_AVERAGE_SIZE 30
kal_bool gFG_Is_offset_init = KAL_FALSE;
#ifdef MTK_MULTI_BAT_PROFILE_SUPPORT
unsigned int g_fg_battery_id;
#ifdef MTK_GET_BATTERY_ID_BY_AUXADC
void fgauge_get_profile_id(void)
{
int id_volt = 0;
int id = 0;
int ret = 0;
ret = IMM_GetOneChannelValue_Cali(BATTERY_ID_CHANNEL_NUM, &id_volt);
if (ret != 0)
bm_info("[%s]id_volt read fail\n", __func__);
else
bm_info("[%s]id_volt = %d\n", __func__, id_volt);
if ((sizeof(g_battery_id_voltage) / sizeof(signed int)) !=
TOTAL_BATTERY_NUMBER) {
bm_info("[%s]error! voltage range incorrect!\n",
__func__);
return;
}
for (id = 0; id < TOTAL_BATTERY_NUMBER; id++) {
if (id_volt < g_battery_id_voltage[id]) {
g_fg_battery_id = id;
break;
} else if (g_battery_id_voltage[id] == -1) {
g_fg_battery_id = TOTAL_BATTERY_NUMBER - 1;
}
}
bm_info("[%s]Battery id (%d)\n", __func__, g_fg_battery_id);
}
#elif defined(MTK_GET_BATTERY_ID_BY_GPIO)
void fgauge_get_profile_id(void)
{
g_fg_battery_id = 0;
}
#else
void fgauge_get_profile_id(void)
{
g_fg_battery_id = 0;
}
#endif
#endif
int __batt_meter_init_cust_data_from_cust_header(struct platform_device *dev)
{
/* cust_battery_meter_table.h */
batt_meter_table_cust_data.battery_profile_t0_size =
sizeof(battery_profile_t0) / sizeof(BATTERY_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.battery_profile_t0,
&battery_profile_t0, sizeof(battery_profile_t0));
batt_meter_table_cust_data.battery_profile_t1_size =
sizeof(battery_profile_t1) / sizeof(BATTERY_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.battery_profile_t1,
&battery_profile_t1, sizeof(battery_profile_t1));
batt_meter_table_cust_data.battery_profile_t2_size =
sizeof(battery_profile_t2) / sizeof(BATTERY_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.battery_profile_t2,
&battery_profile_t2, sizeof(battery_profile_t2));
batt_meter_table_cust_data.battery_profile_t3_size =
sizeof(battery_profile_t3) / sizeof(BATTERY_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.battery_profile_t3,
&battery_profile_t3, sizeof(battery_profile_t3));
batt_meter_table_cust_data.r_profile_t0_size =
sizeof(r_profile_t0) / sizeof(R_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.r_profile_t0, &r_profile_t0,
sizeof(r_profile_t0));
batt_meter_table_cust_data.r_profile_t1_size =
sizeof(r_profile_t1) / sizeof(R_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.r_profile_t1, &r_profile_t1,
sizeof(r_profile_t1));
batt_meter_table_cust_data.r_profile_t2_size =
sizeof(r_profile_t2) / sizeof(R_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.r_profile_t2, &r_profile_t2,
sizeof(r_profile_t2));
batt_meter_table_cust_data.r_profile_t3_size =
sizeof(r_profile_t3) / sizeof(R_PROFILE_STRUCT);
memcpy(&batt_meter_table_cust_data.r_profile_t3, &r_profile_t3,
sizeof(r_profile_t3));
/* cust_battery_meter.h */
#if defined(SOC_BY_HW_FG)
batt_meter_cust_data.soc_flow = HW_FG;
#elif defined(SOC_BY_SW_FG)
batt_meter_cust_data.soc_flow = SW_FG;
#elif defined(SOC_BY_AUXADC)
batt_meter_cust_data.soc_flow = AUXADC;
#endif
#if defined(HW_FG_FORCE_USE_SW_OCV)
batt_meter_cust_data.hw_fg_force_use_sw_ocv = 1;
#else /* #if defined(HW_FG_FORCE_USE_SW_OCV) */
batt_meter_cust_data.hw_fg_force_use_sw_ocv = 0;
#endif /* #if defined(HW_FG_FORCE_USE_SW_OCV) */
/* ADC resister */
batt_meter_cust_data.r_bat_sense = R_BAT_SENSE;
g_R_BAT_SENSE = R_BAT_SENSE;
batt_meter_cust_data.r_i_sense = R_I_SENSE;
g_R_I_SENSE = R_I_SENSE;
batt_meter_cust_data.r_charger_1 = R_CHARGER_1;
g_R_CHARGER_1 = R_CHARGER_1;
batt_meter_cust_data.r_charger_2 = R_CHARGER_2;
g_R_CHARGER_2 = R_CHARGER_2;
batt_meter_cust_data.temperature_t0 = TEMPERATURE_T0;
batt_meter_cust_data.temperature_t1 = TEMPERATURE_T1;
batt_meter_cust_data.temperature_t2 = TEMPERATURE_T2;
batt_meter_cust_data.temperature_t3 = TEMPERATURE_T3;
batt_meter_cust_data.temperature_t = TEMPERATURE_T;
batt_meter_cust_data.fg_meter_resistance = FG_METER_RESISTANCE;
/* Qmax for battery */
batt_meter_cust_data.q_max_pos_50 = Q_MAX_POS_50;
batt_meter_cust_data.q_max_pos_25 = Q_MAX_POS_25;
batt_meter_cust_data.q_max_pos_0 = Q_MAX_POS_0;
batt_meter_cust_data.q_max_neg_10 = Q_MAX_NEG_10;
batt_meter_cust_data.q_max_pos_50_h_current = Q_MAX_POS_50_H_CURRENT;
batt_meter_cust_data.q_max_pos_25_h_current = Q_MAX_POS_25_H_CURRENT;
batt_meter_cust_data.q_max_pos_0_h_current = Q_MAX_POS_0_H_CURRENT;
batt_meter_cust_data.q_max_neg_10_h_current = Q_MAX_NEG_10_H_CURRENT;
batt_meter_cust_data.oam_d5 = OAM_D5; /* 1 : D5, 0: D2 */
#if defined(CHANGE_TRACKING_POINT)
batt_meter_cust_data.change_tracking_point = 1;
#else /* #if defined(CHANGE_TRACKING_POINT) */
batt_meter_cust_data.change_tracking_point = 0;
#endif /* #if defined(CHANGE_TRACKING_POINT) */
batt_meter_cust_data.cust_tracking_point = CUST_TRACKING_POINT;
g_tracking_point = CUST_TRACKING_POINT;
batt_meter_cust_data.cust_r_sense = CUST_R_SENSE;
batt_meter_cust_data.cust_hw_cc = CUST_HW_CC;
batt_meter_cust_data.aging_tuning_value = AGING_TUNING_VALUE;
batt_meter_cust_data.cust_r_fg_offset = CUST_R_FG_OFFSET;
batt_meter_cust_data.ocv_board_compesate = OCV_BOARD_COMPESATE;
batt_meter_cust_data.r_fg_board_base = R_FG_BOARD_BASE;
batt_meter_cust_data.r_fg_board_slope = R_FG_BOARD_SLOPE;
batt_meter_cust_data.car_tune_value = CAR_TUNE_VALUE;
/* HW Fuel gague */
batt_meter_cust_data.current_detect_r_fg = CURRENT_DETECT_R_FG;
batt_meter_cust_data.minerroroffset = MinErrorOffset;
batt_meter_cust_data.fg_vbat_average_size = FG_VBAT_AVERAGE_SIZE;
batt_meter_cust_data.r_fg_value = R_FG_VALUE;
batt_meter_cust_data.difference_hwocv_rtc = DIFFERENCE_HWOCV_RTC;
batt_meter_cust_data.difference_hwocv_swocv = DIFFERENCE_HWOCV_SWOCV;
batt_meter_cust_data.difference_swocv_rtc = DIFFERENCE_SWOCV_RTC;
batt_meter_cust_data.max_swocv = MAX_SWOCV;
batt_meter_cust_data.max_hwocv = MAX_HWOCV;
batt_meter_cust_data.max_vbat = MAX_VBAT;
batt_meter_cust_data.difference_hwocv_vbat = DIFFERENCE_HWOCV_VBAT;
batt_meter_cust_data.difference_vbat_rtc = DIFFERENCE_VBAT_RTC;
batt_meter_cust_data.difference_swocv_rtc_pos =
DIFFERENCE_SWOCV_RTC_POS;
batt_meter_cust_data.suspend_current_threshold =
SUSPEND_CURRENT_CHECK_THRESHOLD;
batt_meter_cust_data.ocv_check_time = OCV_RECOVER_TIME;
batt_meter_cust_data.shutdown_system_voltage = SHUTDOWN_SYSTEM_VOLTAGE;
batt_meter_cust_data.recharge_tolerance = RECHARGE_TOLERANCE;
#if defined(FIXED_TBAT_25)
batt_meter_cust_data.fixed_tbat_25 = 1;
#else /* #if defined(FIXED_TBAT_25) */
batt_meter_cust_data.fixed_tbat_25 = 0;
#endif /* #if defined(FIXED_TBAT_25) */
batt_meter_cust_data.batterypseudo100 = BATTERYPSEUDO100;
batt_meter_cust_data.batterypseudo1 = BATTERYPSEUDO1;
/* Dynamic change wake up period of battery thread when suspend */
batt_meter_cust_data.vbat_normal_wakeup = VBAT_NORMAL_WAKEUP;
batt_meter_cust_data.vbat_low_power_wakeup = VBAT_LOW_POWER_WAKEUP;
batt_meter_cust_data.normal_wakeup_period = NORMAL_WAKEUP_PERIOD;
/* _g_bat_sleep_total_time = NORMAL_WAKEUP_PERIOD; */
batt_meter_cust_data.low_power_wakeup_period = LOW_POWER_WAKEUP_PERIOD;
batt_meter_cust_data.close_poweroff_wakeup_period =
CLOSE_POWEROFF_WAKEUP_PERIOD;
#if defined(INIT_SOC_BY_SW_SOC)
batt_meter_cust_data.init_soc_by_sw_soc = 1;
#else /* #if defined(INIT_SOC_BY_SW_SOC) */
batt_meter_cust_data.init_soc_by_sw_soc = 0;
#endif /* #if defined(INIT_SOC_BY_SW_SOC) */
#if defined(SYNC_UI_SOC_IMM)
batt_meter_cust_data.sync_ui_soc_imm = 1;
#else /* #if defined(SYNC_UI_SOC_IMM) */
batt_meter_cust_data.sync_ui_soc_imm = 0;
#endif /* #if defined(SYNC_UI_SOC_IMM) */
#if defined(MTK_ENABLE_AGING_ALGORITHM)
batt_meter_cust_data.mtk_enable_aging_algorithm = 1;
#else /* #if defined(MTK_ENABLE_AGING_ALGORITHM) */
batt_meter_cust_data.mtk_enable_aging_algorithm = 0;
#endif /* #if defined(MTK_ENABLE_AGING_ALGORITHM) */
#if defined(MD_SLEEP_CURRENT_CHECK)
batt_meter_cust_data.md_sleep_current_check = 1;
#else /* #if defined(MD_SLEEP_CURRENT_CHECK) */
batt_meter_cust_data.md_sleep_current_check = 0;
#endif /* #if defined(MD_SLEEP_CURRENT_CHECK) */
#if defined(Q_MAX_BY_CURRENT)
batt_meter_cust_data.q_max_by_current = 1;
#elif defined(Q_MAX_BY_SYS)
batt_meter_cust_data.q_max_by_current = 2;
#else /* #if defined(Q_MAX_BY_CURRENT) */
batt_meter_cust_data.q_max_by_current = 0;
#endif /* #if defined(Q_MAX_BY_CURRENT) */
batt_meter_cust_data.q_max_sys_voltage = Q_MAX_SYS_VOLTAGE;
#if defined(CONFIG_MTK_EMBEDDED_BATTERY)
batt_meter_cust_data.embedded_battery = 1;
#else
batt_meter_cust_data.embedded_battery = 0;
#endif
#if defined(SHUTDOWN_GAUGE0)
batt_meter_cust_data.shutdown_gauge0 = 1;
#else /* #if defined(SHUTDOWN_GAUGE0) */
batt_meter_cust_data.shutdown_gauge0 = 0;
#endif /* #if defined(SHUTDOWN_GAUGE0) */
#if defined(SHUTDOWN_GAUGE1_XMINS)
batt_meter_cust_data.shutdown_gauge1_xmins = 1;
#else /* #if defined(SHUTDOWN_GAUGE1_XMINS) */
batt_meter_cust_data.shutdown_gauge1_xmins = 0;
#endif /* #if defined(SHUTDOWN_GAUGE1_XMINS) */
batt_meter_cust_data.shutdown_gauge1_mins = SHUTDOWN_GAUGE1_MINS;
batt_meter_cust_data.tracking_gap = CUST_TRACKING_GAP;
batt_meter_cust_data.trackingoffset = CUST_TRACKINGOFFSET;
batt_meter_cust_data.trackingen = CUST_TRACKINGEN;
batt_meter_cust_data.min_charging_smooth_time =
FG_MIN_CHARGING_SMOOTH_TIME;
batt_meter_cust_data.apsleep_battery_voltage_compensate =
APSLEEP_BATTERY_VOLTAGE_COMPENSATE;
batt_meter_cust_data.bat_task_period = BAT_TASK_PERIOD;
return 0;
}
int __batt_meter_init_cust_data_from_dt(struct platform_device *dev)
{
struct device_node *np = dev->dev.of_node;
unsigned int val;
bm_debug("%s\n", __func__);
if (of_property_read_u32(np, "hw_fg_force_use_sw_ocv", &val)) {
batt_meter_cust_data.hw_fg_force_use_sw_ocv = (int)val;
bm_debug("Get hw_fg_force_use_sw_ocv: %d\n",
batt_meter_cust_data.hw_fg_force_use_sw_ocv);
} else {
bm_err("Get hw_fg_force_use_sw_ocv failed\n");
}
if (of_property_read_u32(np, "r_bat_sense", &val)) {
batt_meter_cust_data.r_bat_sense = (int)val;
bm_debug("Get r_bat_sense: %d\n",
batt_meter_cust_data.r_bat_sense);
} else {
bm_err("Get r_bat_sense failed\n");
}
if (of_property_read_u32(np, "r_i_sense", &val)) {
batt_meter_cust_data.r_i_sense = (int)val;
bm_debug("Get r_i_sense: %d\n", batt_meter_cust_data.r_i_sense);
} else {
bm_err("Get r_i_sense failed\n");
}
if (of_property_read_u32(np, "r_charger_1", &val)) {
batt_meter_cust_data.r_charger_1 = (int)val;
bm_debug("Get r_charger_1: %d\n",
batt_meter_cust_data.r_charger_1);
} else {
bm_err("Get r_charger_1 failed\n");
}
if (of_property_read_u32(np, "r_charger_2", &val)) {
batt_meter_cust_data.r_charger_2 = (int)val;
bm_debug("Get r_charger_2: %d\n",
batt_meter_cust_data.r_charger_2);
} else {
bm_err("Get r_charger_2 failed\n");
}
if (of_property_read_u32(np, "temperature_t0", &val)) {
batt_meter_cust_data.temperature_t0 = (int)val;
bm_debug("Get temperature_t0: %d\n",
batt_meter_cust_data.temperature_t0);
} else {
bm_err("Get temperature_t0 failed\n");
}
if (of_property_read_u32(np, "temperature_t1", &val)) {
batt_meter_cust_data.temperature_t1 = (int)val;
bm_debug("Get temperature_t1: %d\n",
batt_meter_cust_data.temperature_t1);
} else {
bm_err("Get temperature_t1 failed\n");
}
if (of_property_read_u32(np, "temperature_t2", &val)) {
batt_meter_cust_data.temperature_t2 = (int)val;
bm_debug("Get temperature_t2: %d\n",
batt_meter_cust_data.temperature_t2);
} else {
bm_err("Get temperature_t2 failed\n");
}
if (of_property_read_u32(np, "temperature_t3", &val)) {
batt_meter_cust_data.temperature_t3 = (int)val;
bm_debug("Get temperature_t3: %d\n",
batt_meter_cust_data.temperature_t3);
} else {
bm_err("Get temperature_t3 failed\n");
}
if (of_property_read_u32(np, "temperature_t", &val)) {
batt_meter_cust_data.temperature_t = (int)val;
bm_debug("Get temperature_t: %d\n",
batt_meter_cust_data.temperature_t);
} else {
bm_err("Get temperature_t failed\n");
}
if (of_property_read_u32(np, "fg_meter_resistance", &val)) {
batt_meter_cust_data.fg_meter_resistance = (int)val;
bm_debug("Get fg_meter_resistance: %d\n",
batt_meter_cust_data.fg_meter_resistance);
} else {
bm_err("Get fg_meter_resistance failed\n");
}
if (of_property_read_u32(np, "q_max_pos_50", &val)) {
batt_meter_cust_data.q_max_pos_50 = (int)val;
bm_debug("Get q_max_pos_50: %d\n",
batt_meter_cust_data.q_max_pos_50);
} else {
bm_err("Get q_max_pos_50 failed\n");
}
if (of_property_read_u32(np, "q_max_pos_25", &val)) {
batt_meter_cust_data.q_max_pos_25 = (int)val;
bm_debug("Get q_max_pos_25: %d\n",
batt_meter_cust_data.q_max_pos_25);
} else {
bm_err("Get q_max_pos_25 failed\n");
}
if (of_property_read_u32(np, "q_max_pos_0", &val)) {
batt_meter_cust_data.q_max_pos_0 = (int)val;
bm_debug("Get q_max_pos_0: %d\n",
batt_meter_cust_data.q_max_pos_0);
} else {
bm_err("Get q_max_pos_0 failed\n");
}
if (of_property_read_u32(np, "q_max_neg_10", &val)) {
batt_meter_cust_data.q_max_neg_10 = (int)val;
bm_debug("Get q_max_neg_10: %d\n",
batt_meter_cust_data.q_max_neg_10);
} else {
bm_err("Get q_max_neg_10 failed\n");
}
if (of_property_read_u32(np, "q_max_pos_50_h_current", &val)) {
batt_meter_cust_data.q_max_pos_50_h_current = (int)val;
bm_debug("Get q_max_pos_50_h_current: %d\n",
batt_meter_cust_data.q_max_pos_50_h_current);
} else {
bm_err("Get q_max_pos_50_h_current failed\n");
}
if (of_property_read_u32(np, "q_max_pos_25_h_current", &val)) {
batt_meter_cust_data.q_max_pos_25_h_current = (int)val;
bm_debug("Get q_max_pos_25_h_current: %d\n",
batt_meter_cust_data.q_max_pos_25_h_current);
} else {
bm_err("Get q_max_pos_25_h_current failed\n");
}
if (of_property_read_u32(np, "q_max_pos_0_h_current", &val)) {
batt_meter_cust_data.q_max_pos_0_h_current = (int)val;
bm_debug("Get q_max_pos_0_h_current: %d\n",
batt_meter_cust_data.q_max_pos_0_h_current);
} else {
bm_err("Get q_max_pos_0_h_current failed\n");
}
if (of_property_read_u32(np, "q_max_neg_10_h_current", &val)) {
batt_meter_cust_data.q_max_neg_10_h_current = (int)val;
bm_debug("Get q_max_neg_10_h_current: %d\n",
batt_meter_cust_data.q_max_neg_10_h_current);
} else {
bm_err("Get q_max_neg_10_h_current failed\n");
}
if (of_property_read_u32(np, "oam_d5", &val)) {
batt_meter_cust_data.oam_d5 = (int)val;
bm_debug("Get oam_d5: %d\n", batt_meter_cust_data.oam_d5);
} else {
bm_err("Get oam_d5 failed\n");
}
if (of_property_read_u32(np, "change_tracking_point", &val)) {
batt_meter_cust_data.change_tracking_point = (int)val;
bm_debug("Get change_tracking_point: %d\n",
batt_meter_cust_data.change_tracking_point);
} else {
bm_err("Get change_tracking_point failed\n");
}
if (of_property_read_u32(np, "cust_tracking_point", &val)) {
batt_meter_cust_data.cust_tracking_point = (int)val;
bm_debug("Get cust_tracking_point: %d\n",
batt_meter_cust_data.cust_tracking_point);
} else {
bm_err("Get cust_tracking_point failed\n");
}
if (of_property_read_u32(np, "cust_r_sense", &val)) {
batt_meter_cust_data.cust_r_sense = (int)val;
bm_debug("Get cust_r_sense: %d\n",
batt_meter_cust_data.cust_r_sense);
} else {
bm_err("Get cust_r_sense failed\n");
}
if (of_property_read_u32(np, "cust_hw_cc", &val)) {
batt_meter_cust_data.cust_hw_cc = (int)val;
bm_debug("Get cust_hw_cc: %d\n",
batt_meter_cust_data.cust_hw_cc);
} else {
bm_err("Get cust_hw_cc failed\n");
}
if (of_property_read_u32(np, "aging_tuning_value", &val)) {
batt_meter_cust_data.aging_tuning_value = (int)val;
bm_debug("Get aging_tuning_value: %d\n",
batt_meter_cust_data.aging_tuning_value);
} else {
bm_err("Get aging_tuning_value failed\n");
}
if (of_property_read_u32(np, "cust_r_fg_offset", &val)) {
batt_meter_cust_data.cust_r_fg_offset = (int)val;
bm_debug("Get cust_r_fg_offset: %d\n",
batt_meter_cust_data.cust_r_fg_offset);
} else {
bm_err("Get cust_r_fg_offset failed\n");
}
if (of_property_read_u32(np, "ocv_board_compesate", &val)) {
batt_meter_cust_data.ocv_board_compesate = (int)val;
bm_debug("Get ocv_board_compesate: %d\n",
batt_meter_cust_data.ocv_board_compesate);
} else {
bm_err("Get ocv_board_compesate failed\n");
}
if (of_property_read_u32(np, "r_fg_board_base", &val)) {
batt_meter_cust_data.r_fg_board_base = (int)val;
bm_debug("Get r_fg_board_base: %d\n",
batt_meter_cust_data.r_fg_board_base);
} else {
bm_err("Get r_fg_board_base failed\n");
}
if (of_property_read_u32(np, "r_fg_board_slope", &val)) {
batt_meter_cust_data.r_fg_board_slope = (int)val;
bm_debug("Get r_fg_board_slope: %d\n",
batt_meter_cust_data.r_fg_board_slope);
} else {
bm_err("Get r_fg_board_slope failed\n");
}
if (of_property_read_u32(np, "car_tune_value", &val)) {
batt_meter_cust_data.car_tune_value = (int)val;
bm_debug("Get car_tune_value: %d\n",
batt_meter_cust_data.car_tune_value);
} else {
bm_err("Get car_tune_value failed\n");
}
if (of_property_read_u32(np, "current_detect_r_fg", &val)) {
batt_meter_cust_data.current_detect_r_fg = (int)val;
bm_debug("Get current_detect_r_fg: %d\n",
batt_meter_cust_data.current_detect_r_fg);
} else {
bm_err("Get current_detect_r_fg failed\n");
}
if (of_property_read_u32(np, "minerroroffset", &val)) {
batt_meter_cust_data.minerroroffset = (int)val;
bm_debug("Get minerroroffset: %d\n",
batt_meter_cust_data.minerroroffset);
} else {
bm_err("Get minerroroffset failed\n");
}
if (of_property_read_u32(np, "fg_vbat_average_size", &val)) {
batt_meter_cust_data.fg_vbat_average_size = (int)val;
bm_debug("Get fg_vbat_average_size: %d\n",
batt_meter_cust_data.fg_vbat_average_size);
} else {
bm_err("Get fg_vbat_average_size failed\n");
}
if (of_property_read_u32(np, "r_fg_value", &val)) {
batt_meter_cust_data.r_fg_value = (int)val;
bm_debug("Get r_fg_value: %d\n",
batt_meter_cust_data.r_fg_value);
} else {
bm_err("Get r_fg_value failed\n");
}
/* TODO: update dt for new parameters */
if (of_property_read_u32(np, "difference_hwocv_rtc", &val)) {
batt_meter_cust_data.difference_hwocv_rtc = (int)val;
bm_debug("Get difference_hwocv_rtc: %d\n",
batt_meter_cust_data.difference_hwocv_rtc);
} else {
bm_err("Get difference_hwocv_rtc failed\n");
}
if (of_property_read_u32(np, "difference_hwocv_swocv", &val)) {
batt_meter_cust_data.difference_hwocv_swocv = (int)val;
bm_debug("Get difference_hwocv_swocv: %d\n",
batt_meter_cust_data.difference_hwocv_swocv);
} else {
bm_err("Get difference_hwocv_swocv failed\n");
}
if (of_property_read_u32(np, "difference_swocv_rtc", &val)) {
batt_meter_cust_data.difference_swocv_rtc = (int)val;
bm_debug("Get difference_swocv_rtc: %d\n",
batt_meter_cust_data.difference_swocv_rtc);
} else {
bm_err("Get difference_swocv_rtc failed\n");
}
if (of_property_read_u32(np, "max_swocv", &val)) {
batt_meter_cust_data.max_swocv = (int)val;
bm_debug("Get max_swocv: %d\n", batt_meter_cust_data.max_swocv);
} else {
bm_err("Get max_swocv failed\n");
}
if (of_property_read_u32(np, "max_hwocv", &val)) {
batt_meter_cust_data.max_hwocv = (int)val;
bm_debug("Get max_hwocv: %d\n", batt_meter_cust_data.max_hwocv);
} else {
bm_err("Get max_hwocv failed\n");
}
if (of_property_read_u32(np, "max_vbat", &val)) {
batt_meter_cust_data.max_vbat = (int)val;
bm_debug("Get max_vbat: %d\n", batt_meter_cust_data.max_vbat);
} else {
bm_err("Get max_vbat failed\n");
}
if (of_property_read_u32(np, "difference_hwocv_vbat", &val)) {
batt_meter_cust_data.difference_hwocv_vbat = (int)val;
bm_debug("Get difference_hwocv_vbat: %d\n",
batt_meter_cust_data.difference_hwocv_vbat);
} else {
bm_err("Get difference_hwocv_vbat failed\n");
}
if (of_property_read_u32(np, "suspend_current_threshold", &val)) {
batt_meter_cust_data.suspend_current_threshold = (int)val;
bm_debug("Get suspend_current_threshold: %d\n",
batt_meter_cust_data.suspend_current_threshold);
} else {
bm_err("Get suspend_current_threshold failed\n");
}
if (of_property_read_u32(np, "ocv_check_time", &val)) {
batt_meter_cust_data.ocv_check_time = (int)val;
bm_debug("Get ocv_check_time: %d\n",
batt_meter_cust_data.ocv_check_time);
} else {
bm_err("Get ocv_check_time failed\n");
}
if (of_property_read_u32(np, "fixed_tbat_25", &val)) {
batt_meter_cust_data.fixed_tbat_25 = (int)val;
bm_debug("Get fixed_tbat_25: %d\n",
batt_meter_cust_data.fixed_tbat_25);
} else {
bm_err("Get fixed_tbat_25 failed\n");
}
batt_meter_cust_data.batterypseudo100 = BATTERYPSEUDO100;
batt_meter_cust_data.batterypseudo1 = BATTERYPSEUDO1;
if (of_property_read_u32(np, "vbat_normal_wakeup", &val)) {
batt_meter_cust_data.vbat_normal_wakeup = (int)val;
bm_debug("Get vbat_normal_wakeup: %d\n",
batt_meter_cust_data.vbat_normal_wakeup);
} else {
bm_err("Get vbat_normal_wakeup failed\n");
}
if (of_property_read_u32(np, "vbat_low_power_wakeup", &val)) {
batt_meter_cust_data.vbat_low_power_wakeup = (int)val;
bm_debug("Get vbat_low_power_wakeup: %d\n",
batt_meter_cust_data.vbat_low_power_wakeup);
} else {
bm_err("Get vbat_low_power_wakeup failed\n");
}
if (of_property_read_u32(np, "normal_wakeup_period", &val)) {
batt_meter_cust_data.normal_wakeup_period = (int)val;
bm_debug("Get normal_wakeup_period: %d\n",
batt_meter_cust_data.normal_wakeup_period);
} else {
bm_err("Get normal_wakeup_period failed\n");
}
if (of_property_read_u32(np, "low_power_wakeup_period", &val)) {
batt_meter_cust_data.low_power_wakeup_period = (int)val;
bm_debug("Get low_power_wakeup_period: %d\n",
batt_meter_cust_data.low_power_wakeup_period);
} else {
bm_err("Get low_power_wakeup_period failed\n");
}
if (of_property_read_u32(np, "close_poweroff_wakeup_period", &val)) {
batt_meter_cust_data.close_poweroff_wakeup_period = (int)val;
bm_debug("Get close_poweroff_wakeup_period: %d\n",
batt_meter_cust_data.close_poweroff_wakeup_period);
} else {
bm_err("Get close_poweroff_wakeup_period failed\n");
}
if (of_property_read_u32(np, "init_soc_by_sw_soc", &val)) {
batt_meter_cust_data.init_soc_by_sw_soc = (int)val;
bm_debug("Get init_soc_by_sw_soc: %d\n",
batt_meter_cust_data.init_soc_by_sw_soc);
} else {
bm_err("Get init_soc_by_sw_soc failed\n");
}
if (of_property_read_u32(np, "sync_ui_soc_imm", &val)) {
batt_meter_cust_data.sync_ui_soc_imm = (int)val;
bm_debug("Get sync_ui_soc_imm: %d\n",
batt_meter_cust_data.sync_ui_soc_imm);
} else {
bm_err("Get sync_ui_soc_imm failed\n");
}
if (of_property_read_u32(np, "mtk_enable_aging_algorithm", &val)) {
batt_meter_cust_data.mtk_enable_aging_algorithm = (int)val;
bm_debug("Get mtk_enable_aging_algorithm: %d\n",
batt_meter_cust_data.mtk_enable_aging_algorithm);
} else {
bm_err("Get mtk_enable_aging_algorithm failed\n");
}
if (of_property_read_u32(np, "md_sleep_current_check", &val)) {
batt_meter_cust_data.md_sleep_current_check = (int)val;
bm_debug("Get md_sleep_current_check: %d\n",
batt_meter_cust_data.md_sleep_current_check);
} else {
bm_err("Get md_sleep_current_check failed\n");
}
if (of_property_read_u32(np, "q_max_by_current", &val)) {
batt_meter_cust_data.q_max_by_current = (int)val;
bm_debug("Get q_max_by_current: %d\n",
batt_meter_cust_data.q_max_by_current);
} else {
bm_err("Get q_max_by_current failed\n");
}
if (of_property_read_u32(np, "q_max_sys_voltage", &val)) {
batt_meter_cust_data.q_max_sys_voltage = (int)val;
bm_debug("Get q_max_sys_voltage: %d\n",
batt_meter_cust_data.q_max_sys_voltage);
} else {
bm_err("Get q_max_sys_voltage failed\n");
}
if (of_property_read_u32(np, "shutdown_gauge0", &val)) {
batt_meter_cust_data.shutdown_gauge0 = (int)val;
bm_debug("Get shutdown_gauge0: %d\n",
batt_meter_cust_data.shutdown_gauge0);
} else {
bm_err("Get shutdown_gauge0 failed\n");
}
if (of_property_read_u32(np, "shutdown_gauge1_xmins", &val)) {
batt_meter_cust_data.shutdown_gauge1_xmins = (int)val;
bm_debug("Get shutdown_gauge1_xmins: %d\n",
batt_meter_cust_data.shutdown_gauge1_xmins);
} else {
bm_err("Get shutdown_gauge1_xmins failed\n");
}
if (of_property_read_u32(np, "shutdown_gauge1_mins", &val)) {
batt_meter_cust_data.shutdown_gauge1_mins = (int)val;
bm_debug("Get shutdown_gauge1_mins: %d\n",
batt_meter_cust_data.shutdown_gauge1_mins);
} else {
bm_err("Get shutdown_gauge1_mins failed\n");
}
return 0;
}
int batt_meter_init_cust_data(struct platform_device *dev)
{
/* #ifdef CONFIG_OF */
/* return __batt_meter_init_cust_data_from_dt(dev); */
/* #else */
return __batt_meter_init_cust_data_from_cust_header(dev);
/* #endif */
}
int get_r_fg_value(void)
{
return (R_FG_VALUE + CUST_R_FG_OFFSET);
}
#ifdef MTK_MULTI_BAT_PROFILE_SUPPORT
int BattThermistorConverTemp(int Res)
{
int i = 0;
int RES1 = 0, RES2 = 0;
int TBatt_Value = -200, TMP1 = 0, TMP2 = 0;
BATT_TEMPERATURE *batt_temperature_table =
&Batt_Temperature_Table[g_fg_battery_id];
if (Res >= batt_temperature_table[0].TemperatureR) {
TBatt_Value = -20;
} else if (Res <= batt_temperature_table[16].TemperatureR) {
TBatt_Value = 60;
} else {
RES1 = batt_temperature_table[0].TemperatureR;
TMP1 = batt_temperature_table[0].BatteryTemp;
for (i = 0; i <= 16; i++) {
if (Res >= batt_temperature_table[i].TemperatureR) {
RES2 = batt_temperature_table[i].TemperatureR;
TMP2 = batt_temperature_table[i].BatteryTemp;
break;
}
RES1 = batt_temperature_table[i].TemperatureR;
TMP1 = batt_temperature_table[i].BatteryTemp;
}
TBatt_Value = (((Res - RES2) * TMP1) + ((RES1 - Res) * TMP2)) /
(RES1 - RES2);
}
return TBatt_Value;
}
signed int fgauge_get_Q_max(signed short temperature)
{
signed int ret_Q_max = 0;
signed int low_temperature = 0, high_temperature = 0;
signed int low_Q_max = 0, high_Q_max = 0;
signed int tmp_Q_max_1 = 0, tmp_Q_max_2 = 0;
if (temperature <= TEMPERATURE_T1) {
low_temperature = (-10);
tmp_Q_max_1 = g_Q_MAX_NEG_10[g_fg_battery_id];
high_temperature = TEMPERATURE_T1;
tmp_Q_max_2 = g_Q_MAX_POS_0[g_fg_battery_id];
if (temperature < low_temperature)
temperature = low_temperature;
} else if (temperature <= TEMPERATURE_T2) {
low_temperature = TEMPERATURE_T1;
tmp_Q_max_1 = g_Q_MAX_POS_0[g_fg_battery_id];
high_temperature = TEMPERATURE_T2;
tmp_Q_max_2 = g_Q_MAX_POS_25[g_fg_battery_id];
if (temperature < low_temperature)
temperature = low_temperature;
} else {
low_temperature = TEMPERATURE_T2;
tmp_Q_max_1 = g_Q_MAX_POS_25[g_fg_battery_id];
high_temperature = TEMPERATURE_T3;
tmp_Q_max_2 = g_Q_MAX_POS_50[g_fg_battery_id];
if (temperature > high_temperature)
temperature = high_temperature;
}
if (tmp_Q_max_1 <= tmp_Q_max_2) {
low_Q_max = tmp_Q_max_1;
high_Q_max = tmp_Q_max_2;
ret_Q_max = low_Q_max +
((((temperature - low_temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
} else {
low_Q_max = tmp_Q_max_2;
high_Q_max = tmp_Q_max_1;
ret_Q_max = low_Q_max +
((((high_temperature - temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
bm_trace("[%s] Q_max = %d\r\n", __func__, ret_Q_max);
return ret_Q_max;
}
signed int fgauge_get_Q_max_high_current(signed short temperature)
{
signed int ret_Q_max = 0;
signed int low_temperature = 0, high_temperature = 0;
signed int low_Q_max = 0, high_Q_max = 0;
signed int tmp_Q_max_1 = 0, tmp_Q_max_2 = 0;
if (temperature <= TEMPERATURE_T1) {
low_temperature = (-10);
tmp_Q_max_1 = g_Q_MAX_NEG_10_H_CURRENT[g_fg_battery_id];
high_temperature = TEMPERATURE_T1;
tmp_Q_max_2 = g_Q_MAX_POS_0_H_CURRENT[g_fg_battery_id];
if (temperature < low_temperature)
temperature = low_temperature;
} else if (temperature <= TEMPERATURE_T2) {
low_temperature = TEMPERATURE_T1;
tmp_Q_max_1 = g_Q_MAX_POS_0_H_CURRENT[g_fg_battery_id];
high_temperature = TEMPERATURE_T2;
tmp_Q_max_2 = g_Q_MAX_POS_25_H_CURRENT[g_fg_battery_id];
if (temperature < low_temperature)
temperature = low_temperature;
} else {
low_temperature = TEMPERATURE_T2;
tmp_Q_max_1 = g_Q_MAX_POS_25_H_CURRENT[g_fg_battery_id];
high_temperature = TEMPERATURE_T3;
tmp_Q_max_2 = g_Q_MAX_POS_50_H_CURRENT[g_fg_battery_id];
if (temperature > high_temperature)
temperature = high_temperature;
}
if (tmp_Q_max_1 <= tmp_Q_max_2) {
low_Q_max = tmp_Q_max_1;
high_Q_max = tmp_Q_max_2;
ret_Q_max = low_Q_max +
((((temperature - low_temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
} else {
low_Q_max = tmp_Q_max_2;
high_Q_max = tmp_Q_max_1;
ret_Q_max = low_Q_max +
((((high_temperature - temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
bm_trace("[%s] Q_max = %d\r\n", __func__, ret_Q_max);
return ret_Q_max;
}
#else
int BattThermistorConverTemp(int Res)
{
int i = 0;
int RES1 = 0, RES2 = 0;
int TBatt_Value = -200, TMP1 = 0, TMP2 = 0;
if (Res >= Batt_Temperature_Table[0].TemperatureR) {
TBatt_Value = -20;
} else if (Res <= Batt_Temperature_Table[16].TemperatureR) {
TBatt_Value = 60;
} else {
RES1 = Batt_Temperature_Table[0].TemperatureR;
TMP1 = Batt_Temperature_Table[0].BatteryTemp;
for (i = 0; i <= 16; i++) {
if (Res >= Batt_Temperature_Table[i].TemperatureR) {
RES2 = Batt_Temperature_Table[i].TemperatureR;
TMP2 = Batt_Temperature_Table[i].BatteryTemp;
break;
}
RES1 = Batt_Temperature_Table[i].TemperatureR;
TMP1 = Batt_Temperature_Table[i].BatteryTemp;
}
TBatt_Value = (((Res - RES2) * TMP1) + ((RES1 - Res) * TMP2)) /
(RES1 - RES2);
}
return TBatt_Value;
}
signed int fgauge_get_Q_max(signed short temperature)
{
signed int ret_Q_max = 0;
signed int low_temperature = 0, high_temperature = 0;
signed int low_Q_max = 0, high_Q_max = 0;
signed int tmp_Q_max_1 = 0, tmp_Q_max_2 = 0;
if (temperature <= TEMPERATURE_T1) {
low_temperature = (-10);
tmp_Q_max_1 = Q_MAX_NEG_10;
high_temperature = TEMPERATURE_T1;
tmp_Q_max_2 = Q_MAX_POS_0;
if (temperature < low_temperature)
temperature = low_temperature;
} else if (temperature <= TEMPERATURE_T2) {
low_temperature = TEMPERATURE_T1;
tmp_Q_max_1 = Q_MAX_POS_0;
high_temperature = TEMPERATURE_T2;
tmp_Q_max_2 = Q_MAX_POS_25;
/* fix coverity wont reach here */
/* if (temperature < low_temperature) */
/* temperature = low_temperature; */
} else {
low_temperature = TEMPERATURE_T2;
tmp_Q_max_1 = Q_MAX_POS_25;
high_temperature = TEMPERATURE_T3;
tmp_Q_max_2 = Q_MAX_POS_50;
if (temperature > high_temperature)
temperature = high_temperature;
}
if (tmp_Q_max_1 <= tmp_Q_max_2) {
low_Q_max = tmp_Q_max_1;
high_Q_max = tmp_Q_max_2;
ret_Q_max = low_Q_max +
((((temperature - low_temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
/* fix coverity */
tmp_Q_max_1 = tmp_Q_max_1 + fix_coverity1;
tmp_Q_max_2 = tmp_Q_max_2 + fix_coverity2;
if (tmp_Q_max_1 > tmp_Q_max_2) {
low_Q_max = tmp_Q_max_2;
high_Q_max = tmp_Q_max_1;
ret_Q_max = low_Q_max +
((((high_temperature - temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
bm_trace("[%s] Q_max = %d\r\n", __func__, ret_Q_max);
return ret_Q_max;
}
signed int fgauge_get_Q_max_high_current(signed short temperature)
{
signed int ret_Q_max = 0;
signed int low_temperature = 0, high_temperature = 0;
signed int low_Q_max = 0, high_Q_max = 0;
signed int tmp_Q_max_1 = 0, tmp_Q_max_2 = 0;
if (temperature <= TEMPERATURE_T1) {
low_temperature = (-10);
tmp_Q_max_1 = Q_MAX_NEG_10_H_CURRENT;
high_temperature = TEMPERATURE_T1;
tmp_Q_max_2 = Q_MAX_POS_0_H_CURRENT;
if (temperature < low_temperature)
temperature = low_temperature;
} else if (temperature <= TEMPERATURE_T2) {
low_temperature = TEMPERATURE_T1;
tmp_Q_max_1 = Q_MAX_POS_0_H_CURRENT;
high_temperature = TEMPERATURE_T2;
tmp_Q_max_2 = Q_MAX_POS_25_H_CURRENT;
/* fix coverity , should not reach here */
/* if (temperature < low_temperature) */
/* temperature = low_temperature; */
} else {
low_temperature = TEMPERATURE_T2;
tmp_Q_max_1 = Q_MAX_POS_25_H_CURRENT;
high_temperature = TEMPERATURE_T3;
tmp_Q_max_2 = Q_MAX_POS_50_H_CURRENT;
if (temperature > high_temperature)
temperature = high_temperature;
}
if (tmp_Q_max_1 <= tmp_Q_max_2) {
low_Q_max = tmp_Q_max_1;
high_Q_max = tmp_Q_max_2;
ret_Q_max = low_Q_max +
((((temperature - low_temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
/* fix coverity */
tmp_Q_max_1 = tmp_Q_max_1 + fix_coverity1;
tmp_Q_max_2 = tmp_Q_max_2 + fix_coverity2;
if (tmp_Q_max_1 > tmp_Q_max_2) {
low_Q_max = tmp_Q_max_2;
high_Q_max = tmp_Q_max_1;
ret_Q_max = low_Q_max +
((((high_temperature - temperature) *
(high_Q_max - low_Q_max) * 10) /
(high_temperature - low_temperature) +
5) /
10);
}
bm_trace("[%s] Q_max = %d\r\n", __func__, ret_Q_max);
return ret_Q_max;
}
#endif
int BattVoltToTemp(int dwVolt)
{
long long TRes_temp;
long long TRes;
int sBaTTMP = -100;
/* TRes_temp = ((long long)RBAT_PULL_UP_R*(long long)dwVolt) / */
/* (RBAT_PULL_UP_VOLT-dwVolt); */
/* TRes = (TRes_temp * (long long)RBAT_PULL_DOWN_R)/((long */
/* long)RBAT_PULL_DOWN_R - TRes_temp); */
TRes_temp = (RBAT_PULL_UP_R * (long long)dwVolt);
#ifdef RBAT_PULL_UP_VOLT_BY_BIF
do_div(TRes_temp, (pmic_get_vbif28_volt() - dwVolt));
/* bm_debug("[RBAT_PULL_UP_VOLT_BY_BIF] vbif28:%d\n",pmic_get_vbif28_volt()); */
#else
do_div(TRes_temp, (RBAT_PULL_UP_VOLT - dwVolt));
#endif
#ifdef RBAT_PULL_DOWN_R
TRes = (TRes_temp * RBAT_PULL_DOWN_R);
do_div(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));
#else
TRes = TRes_temp;
#endif
/* convert register to temperature */
sBaTTMP = BattThermistorConverTemp((int)TRes);
#ifdef RBAT_PULL_UP_VOLT_BY_BIF
bm_debug("[%s] %d %d\n", __func__, RBAT_PULL_UP_R,
pmic_get_vbif28_volt());
#else
bm_debug("[%s] %d\n", __func__, RBAT_PULL_UP_R);
#endif
return sBaTTMP;
}
int force_get_tbat(kal_bool update)
{
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)
bm_debug("[%s] fixed TBAT=25 t\n", __func__);
return 25;
#else
int bat_temperature_volt = 0;
int bat_temperature_val = 0;
static int pre_bat_temperature_val = -1;
int fg_r_value = 0;
signed int fg_current_temp = 0;
kal_bool fg_current_state = KAL_FALSE;
int bat_temperature_volt_temp = 0;
int ret = 0;
if (batt_meter_cust_data.fixed_tbat_25) {
bm_err("[%s] fixed TBAT=25 t\n", __func__);
return 25;
}
if (update == KAL_TRUE || pre_bat_temperature_val == -1) {
/* Get V_BAT_Temperature */
bat_temperature_volt = 2;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP,
&bat_temperature_volt);
if (bat_temperature_volt != 0) {
#if defined(SOC_BY_HW_FG)
fg_r_value = get_r_fg_value();
ret = battery_meter_ctrl(
BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&fg_current_temp);
ret = battery_meter_ctrl(
BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
&fg_current_state);
fg_current_temp = fg_current_temp / 10;
if (fg_current_state == KAL_TRUE) {
bat_temperature_volt_temp =
bat_temperature_volt;
bat_temperature_volt =
bat_temperature_volt -
((fg_current_temp * fg_r_value) / 1000);
} else {
bat_temperature_volt_temp =
bat_temperature_volt;
bat_temperature_volt =
bat_temperature_volt +
((fg_current_temp * fg_r_value) / 1000);
}
#endif
bat_temperature_val =
BattVoltToTemp(bat_temperature_volt);
}
#ifdef CONFIG_MTK_BIF_SUPPORT
battery_charging_control(CHARGING_CMD_GET_BIF_TBAT,
&bat_temperature_val);
#endif
if ((bat_temperature_val > 55) || (bat_temperature_val < 10)) {
bm_err("[%s] %d,%d,%d,%d,%d,%d\n", __func__
bat_temperature_volt_temp, bat_temperature_volt,
fg_current_state, fg_current_temp, fg_r_value,
bat_temperature_val);
}
pre_bat_temperature_val = bat_temperature_val;
} else {
bat_temperature_val = pre_bat_temperature_val;
}
return bat_temperature_val;
#endif
}
EXPORT_SYMBOL(force_get_tbat);
#if defined(SOC_BY_HW_FG)
void update_fg_dbg_tool_value(void)
{
g_fg_dbg_bat_volt = gFG_voltage_init;
if (gFG_Is_Charging == KAL_TRUE)
g_fg_dbg_bat_current = 1 - gFG_current - 1;
else
g_fg_dbg_bat_current = gFG_current;
g_fg_dbg_bat_zcv = gFG_voltage;
g_fg_dbg_bat_temp = gFG_temp;
g_fg_dbg_bat_r = gFG_resistance_bat;
g_fg_dbg_bat_car = gFG_coulomb_act;
g_fg_dbg_bat_qmax = gFG_BATT_CAPACITY_aging;
g_fg_dbg_d0 = gFG_DOD0;
g_fg_dbg_d1 = gFG_DOD1;
g_fg_dbg_percentage = bat_get_ui_percentage();
g_fg_dbg_percentage_fg = gFG_capacity_by_c;
g_fg_dbg_percentage_voltmode = gfg_percent_check_point;
}
void fgauge_algo_run_get_init_data(void)
{
#if defined(INIT_BAT_CUR_FROM_PTIM)
unsigned int bat = 0;
signed int cur = 0;
#else
int ret = 0;
#endif
kal_bool charging_enable = KAL_FALSE;
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) && !defined(SWCHR_POWER_PATH)
if (get_boot_mode() != LOW_POWER_OFF_CHARGING_BOOT)
#endif
/*stop charging for vbat measurement */
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
msleep(50);
/* 1. Get Raw Data */
#if defined(INIT_BAT_CUR_FROM_PTIM)
do_ptim_ex(true, &bat, &cur);
gFG_voltage_init = bat / 10;
gFG_current_init = abs(cur);
if (cur > 0)
gFG_Is_Charging_init = KAL_FALSE;
else
gFG_Is_Charging_init = KAL_TRUE;
#else
gFG_voltage_init = battery_meter_get_battery_voltage(KAL_TRUE);
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&gFG_current_init);
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
&gFG_Is_Charging_init);
#endif
charging_enable = KAL_TRUE;
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
bm_info("1.[%s](gFG_voltage_init %d, gFG_current_init %d, gFG_Is_Charging_init %d)\n",
__func__, gFG_voltage_init,
gFG_current_init, gFG_Is_Charging_init);
mt_battery_set_init_vol(gFG_voltage_init);
}
#endif
#if defined(SOC_BY_SW_FG)
void update_fg_dbg_tool_value(void)
{
}
void fgauge_algo_run_get_init_data(void)
{
kal_bool charging_enable = KAL_FALSE;
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) && !defined(SWCHR_POWER_PATH)
if (get_boot_mode() != LOW_POWER_OFF_CHARGING_BOOT)
#endif
/*stop charging for vbat measurement */
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
msleep(50);
/* 1. Get Raw Data */
gFG_voltage_init = battery_meter_get_battery_voltage(KAL_TRUE);
gFG_current_init = FG_CURRENT_INIT_VALUE;
gFG_Is_Charging_init = KAL_FALSE;
charging_enable = KAL_TRUE;
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
bm_info("1.[%s](gFG_voltage_init %d, gFG_current_init %d, gFG_Is_Charging_init %d)\n",
__func__, gFG_voltage_init,
gFG_current_init, gFG_Is_Charging_init);
}
#endif
signed int get_dynamic_period(int first_use, int first_wakeup_time,
int battery_capacity_level)
{
#if defined(CONFIG_POWER_EXT)
return first_wakeup_time;
#elif defined(SOC_BY_AUXADC) || defined(SOC_BY_SW_FG)
#if (CONFIG_MTK_GAUGE_VERSION == 20)
signed int vbat_val = 0;
vbat_val = g_sw_vbat_temp;
#ifdef CONFIG_MTK_POWER_EXT_DETECT
if (bat_is_ext_power() == KAL_TRUE)
return NORMAL_WAKEUP_PERIOD;
#endif
if (wake_up_smooth_time == 0) {
/* change wake up period when system suspend. */
if (vbat_val > VBAT_NORMAL_WAKEUP) /* 3.6v */
g_spm_timer = NORMAL_WAKEUP_PERIOD; /* 90 min */
else if (vbat_val > VBAT_LOW_POWER_WAKEUP) /* 3.5v */
g_spm_timer = LOW_POWER_WAKEUP_PERIOD; /* 5 min */
else
g_spm_timer =
CLOSE_POWEROFF_WAKEUP_PERIOD; /* 0.5 min */
} else
g_spm_timer = wake_up_smooth_time;
bm_print(BM_LOG_CRTI,
"vbat_val=%d, g_spm_timer=%d wake_up_smooth_time=%d\n",
vbat_val, g_spm_timer, wake_up_smooth_time);
return g_spm_timer;
#else
signed int vbat_val = 0;
vbat_val = g_sw_vbat_temp;
#ifdef CONFIG_MTK_POWER_EXT_DETECT
if (bat_is_ext_power() == KAL_TRUE)
return NORMAL_WAKEUP_PERIOD;
#endif
/* change wake up period when system suspend. */
if (vbat_val > VBAT_NORMAL_WAKEUP) /* 3.6v */
g_spm_timer = NORMAL_WAKEUP_PERIOD; /* 90 min */
else if (vbat_val > VBAT_LOW_POWER_WAKEUP) /* 3.5v */
g_spm_timer = LOW_POWER_WAKEUP_PERIOD; /* 5 min */
else
g_spm_timer = CLOSE_POWEROFF_WAKEUP_PERIOD; /* 0.5 min */
bm_debug("vbat_val=%d, g_spm_timer=%d\n", vbat_val, g_spm_timer);
return g_spm_timer;
#endif
#else
#ifdef FG_BAT_INT
int ret = 0;
signed int car_instant = 0;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&car_instant);
if (wake_up_smooth_time == 0)
g_spm_timer = NORMAL_WAKEUP_PERIOD;
else
g_spm_timer = wake_up_smooth_time;
bm_print(
BM_LOG_CRTI,
"[%s] g_spm_timer:%d wake_up_smooth_time:%d vbat:%d car:%d\r\n",
__func__, g_spm_timer, wake_up_smooth_time,
g_sw_vbat_temp, car_instant);
return g_spm_timer;
#else
signed int car_instant = 0;
signed int current_instant = 0;
static signed int car_sleep = 0x12345678;
signed int car_wakeup = 0;
signed int ret_val = -1;
signed int I_sleep = 0;
signed int new_time = 0;
signed int vbat_val = 0;
int ret = 0;
vbat_val = g_sw_vbat_temp;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&current_instant);
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&car_instant);
if (car_instant < 0)
car_instant = car_instant - (car_instant * 2);
/* 3.6v */
if (vbat_val > VBAT_NORMAL_WAKEUP) {
static unsigned int pre_time;
car_wakeup = car_instant;
if (car_sleep > car_wakeup || car_sleep == 0x12345678) {
car_sleep = car_wakeup;
bm_debug("[%s] reset car_sleep\n",
__func__);
}
if (last_time == 0) {
last_time = 1;
} else {
/* mt_battery_update_time(&car_time); */
/* add_time = mt_battery_get_duration_time(); */
if (car_wakeup == car_sleep) {
pre_time += add_time;
last_time = pre_time;
} else {
last_time = pre_time + add_time;
pre_time = 0;
}
}
I_sleep = (((car_wakeup - car_sleep) * 3600) / last_time + 5) /
10; /* unit: second */
if (I_sleep == 0) {
new_time = g_spm_timer;
} else {
new_time = ((gFG_BATT_CAPACITY_aging *
battery_capacity_level * 3600) /
100) /
I_sleep;
}
bm_print(
BM_LOG_CRTI,
"[%s] car_instant=%d, car_wakeup=%d, car_sleep=%d, I_sleep=%d, gFG_BATT_CAPACITY=%d, add_time=%d, last_time=%d, new_time=%d , battery_capacity_level = %d\r\n",
__func__, car_instant, car_wakeup, car_sleep, I_sleep,
gFG_BATT_CAPACITY_aging, add_time, last_time, new_time,
battery_capacity_level);
if (new_time > 1800)
new_time = 1800;
ret_val = new_time;
if (ret_val == 0)
ret_val = first_wakeup_time;
/* update parameter */
car_sleep = car_wakeup;
g_spm_timer = ret_val;
} else if (vbat_val > VBAT_LOW_POWER_WAKEUP) { /* 3.5v */
g_spm_timer = LOW_POWER_WAKEUP_PERIOD; /* 5 min */
} else {
g_spm_timer = CLOSE_POWEROFF_WAKEUP_PERIOD; /* 0.5 min */
}
bm_debug("vbat_val=%d, g_spm_timer=%d\n", vbat_val, g_spm_timer);
return g_spm_timer;
#endif
#endif
}
/* ============================================================ // */
signed int battery_meter_get_battery_voltage(kal_bool update)
{
int ret = 0;
int val = 5;
static int pre_val = -1;
if (update == KAL_TRUE || pre_val == -1) {
val = 5; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE,
&val);
pre_val = val;
} else {
val = pre_val;
}
g_sw_vbat_temp = val;
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
if (g_sw_vbat_temp > gFG_max_voltage)
gFG_max_voltage = g_sw_vbat_temp;
if (g_sw_vbat_temp < gFG_min_voltage)
gFG_min_voltage = g_sw_vbat_temp;
#endif
return val;
}
int battery_meter_get_low_battery_interrupt_status(void)
{
int is_lbat_int_trigger;
int ret;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_LOW_BAT_INTERRUPT_STATUS,
&is_lbat_int_trigger);
if (ret != 0)
return KAL_FALSE;
return is_lbat_int_trigger;
}
signed int battery_meter_get_charging_current_imm(void)
{
#ifdef AUXADC_SUPPORT_IMM_CURRENT_MODE
return PMIC_IMM_GetCurrent();
#else
int ret;
signed int ADC_I_SENSE = 1; /* 1 measure time */
signed int ADC_BAT_SENSE = 1; /* 1 measure time */
int ICharging = 0;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE,
&ADC_BAT_SENSE);
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE,
&ADC_I_SENSE);
ICharging = (ADC_I_SENSE - ADC_BAT_SENSE + g_I_SENSE_offset) * 1000 /
CUST_R_SENSE;
return ICharging;
#endif
}
signed int battery_meter_get_charging_current(void)
{
#ifdef DISABLE_CHARGING_CURRENT_MEASURE
return 0;
#elif defined(AUXADC_SUPPORT_IMM_CURRENT_MODE)
return PMIC_IMM_GetCurrent();
#elif !defined(EXTERNAL_SWCHR_SUPPORT)
signed int ADC_BAT_SENSE_tmp[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
signed int ADC_BAT_SENSE_sum = 0;
signed int ADC_BAT_SENSE = 0;
signed int ADC_I_SENSE_tmp[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
signed int ADC_I_SENSE_sum = 0;
signed int ADC_I_SENSE = 0;
int repeat = 20;
int i = 0;
int j = 0;
signed int temp = 0;
int ICharging = 0;
int ret = 0;
int val = 1;
for (i = 0; i < repeat; i++) {
val = 1; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE,
&val);
ADC_BAT_SENSE_tmp[i] = val;
val = 1; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE,
&val);
ADC_I_SENSE_tmp[i] = val;
ADC_BAT_SENSE_sum += ADC_BAT_SENSE_tmp[i];
ADC_I_SENSE_sum += ADC_I_SENSE_tmp[i];
}
/* sorting BAT_SENSE */
for (i = 0; i < repeat; i++) {
for (j = i; j < repeat; j++) {
if (ADC_BAT_SENSE_tmp[j] < ADC_BAT_SENSE_tmp[i]) {
temp = ADC_BAT_SENSE_tmp[j];
ADC_BAT_SENSE_tmp[j] = ADC_BAT_SENSE_tmp[i];
ADC_BAT_SENSE_tmp[i] = temp;
}
}
}
bm_trace("[g_Get_I_Charging:BAT_SENSE]\r\n");
for (i = 0; i < repeat; i++)
bm_trace("%d,", ADC_BAT_SENSE_tmp[i]);
bm_trace("\r\n");
/* sorting I_SENSE */
for (i = 0; i < repeat; i++) {
for (j = i; j < repeat; j++) {
if (ADC_I_SENSE_tmp[j] < ADC_I_SENSE_tmp[i]) {
temp = ADC_I_SENSE_tmp[j];
ADC_I_SENSE_tmp[j] = ADC_I_SENSE_tmp[i];
ADC_I_SENSE_tmp[i] = temp;
}
}
}
bm_trace("[g_Get_I_Charging:I_SENSE]\r\n");
for (i = 0; i < repeat; i++)
bm_trace("%d,", ADC_I_SENSE_tmp[i]);
bm_trace("\r\n");
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[0];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[1];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[18];
ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[19];
ADC_BAT_SENSE = ADC_BAT_SENSE_sum / (repeat - 4);
bm_trace("[g_Get_I_Charging] ADC_BAT_SENSE=%d\r\n", ADC_BAT_SENSE);
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[0];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[1];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[18];
ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[19];
ADC_I_SENSE = ADC_I_SENSE_sum / (repeat - 4);
bm_trace("[g_Get_I_Charging] ADC_I_SENSE(Before)=%d\r\n", ADC_I_SENSE);
bm_trace("[g_Get_I_Charging] ADC_I_SENSE(After)=%d\r\n", ADC_I_SENSE);
if (ADC_I_SENSE > ADC_BAT_SENSE)
ICharging = (ADC_I_SENSE - ADC_BAT_SENSE + g_I_SENSE_offset) *
1000 / CUST_R_SENSE;
else
ICharging = 0;
return ICharging;
#else
return 0;
#endif
}
signed int battery_meter_get_battery_current(void)
{
int ret = 0;
signed int val = 0;
if (g_auxadc_solution == 1)
val = oam_i_2;
else
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&val);
return val;
}
kal_bool battery_meter_get_battery_current_sign(void)
{
int ret = 0;
kal_bool val = 0;
if (g_auxadc_solution == 1)
val = 0; /* discharging */
else
ret = battery_meter_ctrl(
BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN, &val);
return val;
}
signed int battery_meter_get_car(void)
{
int ret = 0;
signed int val = 0;
if (g_auxadc_solution == 1)
val = oam_car_2;
else {
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&val);
if (val < 0)
val = (val - 5) / 10;
else
val = (val + 5) / 10;
}
return val;
}
signed int battery_meter_get_battery_temperature(void)
{
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
signed int batt_temp = force_get_tbat(KAL_TRUE);
if (batt_temp > gFG_max_temperature)
gFG_max_temperature = batt_temp;
if (batt_temp < gFG_min_temperature)
gFG_min_temperature = batt_temp;
return batt_temp;
#else
return force_get_tbat(KAL_TRUE);
#endif
}
signed int battery_meter_get_charger_voltage(void)
{
int ret = 0;
int val = 0;
val = 5; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_CHARGER, &val);
/* val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100; */
return val;
}
signed int battery_meter_get_battery_percentage(void)
{
#if defined(CONFIG_POWER_EXT)
return 50;
#else
#if defined(SOC_BY_HW_FG)
return gFG_capacity_by_c;
/* hw fg, return gfg_percent_check_point; */
/* voltage mode */
#else
return gFG_capacity_by_c;
#endif
#endif
}
signed int battery_meter_initial(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
static kal_bool meter_initilized = KAL_FALSE;
mutex_lock(&FGADC_mutex);
if (meter_initilized == KAL_FALSE) {
#if defined(SOC_BY_HW_FG)
/* 1. HW initialization */
battery_meter_ctrl(BATTERY_METER_CMD_HW_FG_INIT, NULL);
if (wakeup_fg_algo(FG_MAIN) == -1) {
/* fgauge_initialization(); */
fgauge_algo_run_get_init_data();
bm_err("[%s] SOC_BY_HW_FG not done\n",
__func__);
}
#endif
#if defined(SOC_BY_SW_FG)
/* 1. HW initialization */
battery_meter_ctrl(BATTERY_METER_CMD_HW_FG_INIT, NULL);
if (wakeup_fg_algo(FG_MAIN) == -1) {
/* fgauge_initialization(); */
fgauge_algo_run_get_init_data();
bm_err("[%s] SOC_BY_SW_FG not done\n",
__func__);
}
#endif
meter_initilized = KAL_TRUE;
}
mutex_unlock(&FGADC_mutex);
return 0;
#endif
}
signed int battery_meter_sync(signed int bat_i_sense_offset)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
g_I_SENSE_offset = bat_i_sense_offset;
return 0;
#endif
}
signed int battery_meter_get_battery_zcv(void)
{
#if defined(CONFIG_POWER_EXT)
return 3987;
#else
return gFG_voltage;
#endif
}
signed int battery_meter_get_battery_nPercent_zcv(void)
{
#if defined(CONFIG_POWER_EXT)
return 3700;
#else
return gFG_15_vlot;
/* 15% zcv, 15% can be customized by */
/* 100-g_tracking_point */
#endif
}
signed int battery_meter_get_battery_nPercent_UI_SOC(void)
{
#if defined(CONFIG_POWER_EXT)
return 15;
#else
return g_tracking_point; /* tracking point */
#endif
}
signed int battery_meter_get_tempR(signed int dwVolt)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int TRes;
TRes = (RBAT_PULL_UP_R * dwVolt) / (RBAT_PULL_UP_VOLT - dwVolt);
return TRes;
#endif
}
signed int battery_meter_get_tempV(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int ret = 0;
int val = 0;
val = 1; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &val);
return val;
#endif
}
signed int battery_meter_get_VSense(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
int ret = 0;
int val = 0;
val = 1; /* set avg times */
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val);
return val;
#endif
}
signed int battery_meter_get_QMAX25(void)
{
return batt_meter_cust_data.q_max_pos_25;
}
#ifdef USING_SMOOTH_UI_SOC2
void battery_meter_smooth_uisoc2(void)
{
static int init_flag = -1;
signed int smooth_cc = 0;
signed int cc_act = 0;
signed int cc_act_delta = 0;
if (temp_UI_SOC2 == -1)
return;
if (init_flag == -1) {
UI_SOC3 = temp_UI_SOC2;
pre_UI_SOC2 = temp_UI_SOC2;
init_flag = 1;
}
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT, &cc_act);
if (gFG_coulomb_is_charging == 1) {
/* charging */
cc_act_delta = abs(cc_act - pre_cc_act);
smooth_cc = (100 - temp_UI_SOC2) * gFG_BATT_CAPACITY_aging /
(100 - UI_SOC3) / 100 * 6;
if ((cc_act_delta > smooth_cc) && UI_SOC3 < 100) {
UI_SOC3++;
pre_cc_act = cc_act;
bm_debug("smooth_UISOC2-###+++UI_SOC3=%d\n", UI_SOC3);
}
} else {
/* discharging */
/* reset pre_cc_act if UI_SOC2 changed */
if (temp_UI_SOC2 != pre_UI_SOC2) {
pre_UI_SOC2 = temp_UI_SOC2;
pre_cc_act = cc_act;
}
/* get delta coulomb count every persent */
cc_act_delta = abs(cc_act - pre_cc_act);
smooth_cc = temp_UI_SOC2 * gFG_BATT_CAPACITY_aging / UI_SOC3 /
100 * 15;
if ((cc_act_delta > smooth_cc) && UI_SOC3 > 0) {
UI_SOC3--;
pre_cc_act = cc_act;
bm_debug("smooth_UISOC2-###---UI_SOC3=%d\n", UI_SOC3);
}
}
/* using UI_SOC2 when it not keeping,full,shutdown case */
if ((temp_UI_SOC2 <= UI_SOC3) || (BMT_status.bat_full == KAL_TRUE) ||
(temp_UI_SOC2 == 1))
UI_SOC3 = temp_UI_SOC2;
BMT_status.UI_SOC2 = UI_SOC3;
bm_debug("smooth_UISOC2-@@@@@@@%d,%d,%d,%d,%d,%d,%d,%d\n",
gFG_coulomb_is_charging, temp_UI_SOC2, UI_SOC3, smooth_cc,
cc_act_delta, pre_cc_act, cc_act, gFG_BATT_CAPACITY_aging);
}
#endif
/* ============================================================ // */
static ssize_t fgadc_log_write(struct file *filp, const char __user *buff,
size_t len, loff_t *data)
{
char proc_fgadc_data;
if ((len <= 0) || copy_from_user(&proc_fgadc_data, buff, 1)) {
bm_debug("%s error.\n", __func__);
return -EFAULT;
}
if (proc_fgadc_data == '1') {
bm_debug("enable FGADC driver log system\n");
Enable_FGADC_LOG = 1;
} else if (proc_fgadc_data == '2') {
bm_debug("enable FGADC driver log system:2\n");
Enable_FGADC_LOG = 2;
} else if (proc_fgadc_data == '3') {
bm_debug("enable FGADC driver log system:3\n");
Enable_FGADC_LOG = 3;
} else if (proc_fgadc_data == '4') {
bm_debug("enable FGADC driver log system:4\n");
Enable_FGADC_LOG = 4;
} else if (proc_fgadc_data == '5') {
bm_debug("enable FGADC driver log system:5\n");
Enable_FGADC_LOG = 5;
} else if (proc_fgadc_data == '6') {
bm_debug("enable FGADC driver log system:6\n");
Enable_FGADC_LOG = 6;
} else if (proc_fgadc_data == '7') {
bm_debug("enable FGADC driver log system:7\n");
Enable_FGADC_LOG = 7;
} else if (proc_fgadc_data == '8') {
bm_debug("enable FGADC driver log system:8\n");
Enable_FGADC_LOG = 8;
} else {
bm_debug("Disable FGADC driver log system\n");
Enable_FGADC_LOG = 0;
}
return len;
}
static const struct file_operations fgadc_proc_fops = {
.write = fgadc_log_write,
};
int init_proc_log_fg(void)
{
int ret = 0;
#if 1
proc_create("fgadc_log", 0644, NULL, &fgadc_proc_fops);
bm_debug("proc_create fgadc_proc_fops\n");
#else
proc_entry_fgadc = create_proc_entry("fgadc_log", 0644, NULL);
if (proc_entry_fgadc == NULL) {
ret = -ENOMEM;
bm_debug("%s: Couldn't create proc entry\n", __func__);
} else {
proc_entry_fgadc->write_proc = fgadc_log_write;
bm_debug("%s loaded.\n", __func__);
}
#endif
return ret;
}
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
#ifdef CUSTOM_BATTERY_CYCLE_AGING_DATA
signed int get_battery_aging_factor(signed int cycle)
{
signed int i, f1, f2, c1, c2;
signed int saddles;
saddles = sizeof(battery_aging_table) / sizeof(BATTERY_CYCLE_STRUCT);
for (i = 0; i < saddles; i++) {
if (battery_aging_table[i].cycle == cycle)
return battery_aging_table[i].aging_factor;
if (battery_aging_table[i].cycle > cycle) {
if (i == 0)
return 100;
if (battery_aging_table[i].aging_factor >
battery_aging_table[i - 1].aging_factor) {
f1 = battery_aging_table[i].aging_factor;
f2 = battery_aging_table[i - 1].aging_factor;
c1 = battery_aging_table[i].cycle;
c2 = battery_aging_table[i - 1].cycle;
return (f2 +
((cycle - c2) * (f1 - f2)) / (c1 - c2));
}
f1 = battery_aging_table[i - 1].aging_factor;
f2 = battery_aging_table[i].aging_factor;
c1 = battery_aging_table[i].cycle;
c2 = battery_aging_table[i - 1].cycle;
return (f2 + ((cycle - c2) * (f1 - f2)) / (c1 - c2));
}
}
return battery_aging_table[saddles - 1].aging_factor;
}
#endif
static ssize_t show_FG_Battery_Cycle(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] gFG_battery_cycle : %d\n", gFG_battery_cycle);
return sprintf(buf, "%d\n", gFG_battery_cycle);
}
static ssize_t store_FG_Battery_Cycle(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int cycle;
#ifdef CUSTOM_BATTERY_CYCLE_AGING_DATA
signed int aging_capacity;
signed int factor;
#endif
if (kstrtoint(buf, 10, &cycle) == 0) {
bm_debug("[FG] update battery cycle count: %d\n", cycle);
gFG_battery_cycle = cycle;
#ifdef CUSTOM_BATTERY_CYCLE_AGING_DATA
/* perform cycle aging calculation */
factor = get_battery_aging_factor(gFG_battery_cycle);
if (factor > 0 && factor < 100) {
bm_debug("[FG] cycle count to aging factor %d\n",
factor);
aging_capacity = gFG_BATT_CAPACITY * factor / 100;
if (aging_capacity < gFG_BATT_CAPACITY_aging) {
bm_debug(
"[FG] update gFG_BATT_CAPACITY_aging to %d\n",
aging_capacity);
gFG_BATT_CAPACITY_aging = aging_capacity;
}
}
#endif
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Battery_Cycle, 0664, show_FG_Battery_Cycle,
store_FG_Battery_Cycle);
static ssize_t show_FG_Max_Battery_Voltage(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_max_voltage : %d\n", gFG_max_voltage);
return sprintf(buf, "%d\n", gFG_max_voltage);
}
static ssize_t store_FG_Max_Battery_Voltage(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int voltage;
if (kstrtoint(buf, 10, &voltage) == 0) {
if (voltage > gFG_max_voltage) {
bm_debug("[FG] update battery max voltage: %d\n",
voltage);
gFG_max_voltage = voltage;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Max_Battery_Voltage, 0664, show_FG_Max_Battery_Voltage,
store_FG_Max_Battery_Voltage);
static ssize_t show_FG_Min_Battery_Voltage(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_min_voltage : %d\n", gFG_min_voltage);
return sprintf(buf, "%d\n", gFG_min_voltage);
}
static ssize_t store_FG_Min_Battery_Voltage(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int voltage;
if (kstrtoint(buf, 10, &voltage) == 0) {
if (voltage < gFG_min_voltage) {
bm_debug("[FG] update battery min voltage: %d\n",
voltage);
gFG_min_voltage = voltage;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Min_Battery_Voltage, 0664, show_FG_Min_Battery_Voltage,
store_FG_Min_Battery_Voltage);
static ssize_t show_FG_Max_Battery_Current(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_max_current : %d\n", gFG_max_current);
return sprintf(buf, "%d\n", gFG_max_current);
}
static ssize_t store_FG_Max_Battery_Current(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int bat_current;
if (kstrtoint(buf, 10, &bat_current) == 0) {
if (bat_current > gFG_max_current) {
bm_debug("[FG] update battery max current: %d\n",
bat_current);
gFG_max_current = bat_current;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Max_Battery_Current, 0664, show_FG_Max_Battery_Current,
store_FG_Max_Battery_Current);
static ssize_t show_FG_Min_Battery_Current(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_min_current : %d\n", gFG_min_current);
return sprintf(buf, "%d\n", gFG_min_current);
}
static ssize_t store_FG_Min_Battery_Current(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int bat_current;
if (kstrtoint(buf, 10, &bat_current) == 0) {
if (bat_current < gFG_min_current) {
bm_debug("[FG] update battery min current: %d\n",
bat_current);
gFG_min_current = bat_current;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Min_Battery_Current, 0664, show_FG_Min_Battery_Current,
store_FG_Min_Battery_Current);
static ssize_t show_FG_Max_Battery_Temperature(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_max_temperature : %d\n", gFG_max_temperature);
return sprintf(buf, "%d\n", gFG_max_temperature);
}
static ssize_t store_FG_Max_Battery_Temperature(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int temp;
if (kstrtoint(buf, 10, &temp) == 0) {
if (temp > gFG_max_temperature) {
bm_debug("[FG] update battery max temp: %d\n", temp);
gFG_max_temperature = temp;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Max_Battery_Temperature, 0664,
show_FG_Max_Battery_Temperature,
store_FG_Max_Battery_Temperature);
static ssize_t show_FG_Min_Battery_Temperature(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] gFG_min_temperature : %d\n", gFG_min_temperature);
return sprintf(buf, "%d\n", gFG_min_temperature);
}
static ssize_t store_FG_Min_Battery_Temperature(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int temp;
if (kstrtoint(buf, 10, &temp) == 0) {
if (temp < gFG_min_temperature) {
bm_debug("[FG] update battery min temp: %d\n", temp);
gFG_min_temperature = temp;
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Min_Battery_Temperature, 0664,
show_FG_Min_Battery_Temperature,
store_FG_Min_Battery_Temperature);
static ssize_t show_FG_Aging_Factor(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] gFG_aging_factor_1 : %d\n", gFG_aging_factor_1);
return sprintf(buf, "%d\n", gFG_aging_factor_1);
}
static ssize_t store_FG_Aging_Factor(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
signed int factor;
signed int aging_capacity;
if (kstrtoint(buf, 10, &factor) == 0) {
if (factor <= 100 && factor >= 0) {
bm_print(
BM_LOG_CRTI,
"[FG] update battery aging factor: old(%d), new(%d)\n",
gFG_aging_factor_1, factor);
gFG_aging_factor_1 = factor;
if (gFG_aging_factor_1 != 100) {
aging_capacity = gFG_BATT_CAPACITY *
gFG_aging_factor_1 / 100;
if (aging_capacity < gFG_BATT_CAPACITY_aging) {
bm_print(
BM_LOG_CRTI,
"[FG] update gFG_BATT_CAPACITY_aging to %d\n",
aging_capacity);
gFG_BATT_CAPACITY_aging =
aging_capacity;
}
}
}
} else {
bm_debug("[FG] format error!\n");
}
return size;
}
static DEVICE_ATTR(FG_Aging_Factor, 0664, show_FG_Aging_Factor,
store_FG_Aging_Factor);
#endif
static ssize_t show_FG_Current(struct device *dev,
struct device_attribute *attr, char *buf)
{
signed int ret = 0;
signed int fg_current_inout_battery = 0;
signed int val = 0;
kal_bool is_charging = 0;
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT, &val);
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
&is_charging);
if (is_charging == KAL_TRUE)
fg_current_inout_battery = 0 - val;
else
fg_current_inout_battery = val;
bm_debug("[FG] gFG_current_inout_battery : %d\n",
fg_current_inout_battery);
return sprintf(buf, "%d\n", fg_current_inout_battery);
}
static ssize_t store_FG_Current(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t size)
{
return size;
}
static DEVICE_ATTR(FG_Current, 0664, show_FG_Current, store_FG_Current);
static ssize_t show_FG_g_fg_dbg_bat_volt(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_volt : %d\n", g_fg_dbg_bat_volt);
return sprintf(buf, "%d\n", g_fg_dbg_bat_volt);
}
static ssize_t store_FG_g_fg_dbg_bat_volt(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_volt, 0664, show_FG_g_fg_dbg_bat_volt,
store_FG_g_fg_dbg_bat_volt);
static ssize_t show_FG_g_fg_dbg_bat_current(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_current : %d\n", g_fg_dbg_bat_current);
return sprintf(buf, "%d\n", g_fg_dbg_bat_current);
}
static ssize_t store_FG_g_fg_dbg_bat_current(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_current, 0664, show_FG_g_fg_dbg_bat_current,
store_FG_g_fg_dbg_bat_current);
static ssize_t show_FG_g_fg_dbg_bat_zcv(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_zcv : %d\n", g_fg_dbg_bat_zcv);
return sprintf(buf, "%d\n", g_fg_dbg_bat_zcv);
}
static ssize_t store_FG_g_fg_dbg_bat_zcv(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_zcv, 0664, show_FG_g_fg_dbg_bat_zcv,
store_FG_g_fg_dbg_bat_zcv);
static ssize_t show_FG_g_fg_dbg_bat_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_temp : %d\n", g_fg_dbg_bat_temp);
return sprintf(buf, "%d\n", g_fg_dbg_bat_temp);
}
static ssize_t store_FG_g_fg_dbg_bat_temp(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_temp, 0664, show_FG_g_fg_dbg_bat_temp,
store_FG_g_fg_dbg_bat_temp);
static ssize_t show_FG_g_fg_dbg_bat_r(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_r : %d\n", g_fg_dbg_bat_r);
return sprintf(buf, "%d\n", g_fg_dbg_bat_r);
}
static ssize_t store_FG_g_fg_dbg_bat_r(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_r, 0664, show_FG_g_fg_dbg_bat_r,
store_FG_g_fg_dbg_bat_r);
static ssize_t show_FG_g_fg_dbg_bat_car(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_car : %d\n", g_fg_dbg_bat_car);
return sprintf(buf, "%d\n", g_fg_dbg_bat_car);
}
static ssize_t store_FG_g_fg_dbg_bat_car(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_car, 0664, show_FG_g_fg_dbg_bat_car,
store_FG_g_fg_dbg_bat_car);
static ssize_t show_FG_g_fg_dbg_bat_qmax(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_bat_qmax : %d\n", g_fg_dbg_bat_qmax);
return sprintf(buf, "%d\n", g_fg_dbg_bat_qmax);
}
static ssize_t store_FG_g_fg_dbg_bat_qmax(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_bat_qmax, 0664, show_FG_g_fg_dbg_bat_qmax,
store_FG_g_fg_dbg_bat_qmax);
static ssize_t show_FG_g_fg_dbg_d0(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] g_fg_dbg_d0 : %d\n", g_fg_dbg_d0);
return sprintf(buf, "%d\n", g_fg_dbg_d0);
}
static ssize_t store_FG_g_fg_dbg_d0(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_d0, 0664, show_FG_g_fg_dbg_d0,
store_FG_g_fg_dbg_d0);
static ssize_t show_FG_g_fg_dbg_d1(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] g_fg_dbg_d1 : %d\n", g_fg_dbg_d1);
return sprintf(buf, "%d\n", g_fg_dbg_d1);
}
static ssize_t store_FG_g_fg_dbg_d1(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_d1, 0664, show_FG_g_fg_dbg_d1,
store_FG_g_fg_dbg_d1);
static ssize_t show_FG_g_fg_dbg_percentage(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_percentage : %d\n", g_fg_dbg_percentage);
return sprintf(buf, "%d\n", g_fg_dbg_percentage);
}
static ssize_t store_FG_g_fg_dbg_percentage(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_percentage, 0664, show_FG_g_fg_dbg_percentage,
store_FG_g_fg_dbg_percentage);
static ssize_t show_FG_g_fg_dbg_percentage_uisoc(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_percentage :%d\n", BMT_status.UI_SOC);
return sprintf(buf, "%d\n", BMT_status.UI_SOC);
}
static ssize_t store_FG_g_fg_dbg_percentage_uisoc(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_percentage_uisoc, 0664,
show_FG_g_fg_dbg_percentage_uisoc,
store_FG_g_fg_dbg_percentage_uisoc);
static ssize_t show_FG_g_fg_dbg_percentage_fg(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] g_fg_dbg_percentage_fg : %d\n", g_fg_dbg_percentage_fg);
return sprintf(buf, "%d\n", g_fg_dbg_percentage_fg);
}
static ssize_t store_FG_g_fg_dbg_percentage_fg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_percentage_fg, 0664,
show_FG_g_fg_dbg_percentage_fg,
store_FG_g_fg_dbg_percentage_fg);
static ssize_t
show_FG_g_fg_dbg_percentage_voltmode(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] g_fg_dbg_percentage_voltmode : %d\n",
g_fg_dbg_percentage_voltmode);
return sprintf(buf, "%d\n", g_fg_dbg_percentage_voltmode);
}
static ssize_t
store_FG_g_fg_dbg_percentage_voltmode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
return size;
}
static DEVICE_ATTR(FG_g_fg_dbg_percentage_voltmode, 0664,
show_FG_g_fg_dbg_percentage_voltmode,
store_FG_g_fg_dbg_percentage_voltmode);
#ifdef MTK_ENABLE_AGING_ALGORITHM
static ssize_t show_FG_suspend_current_threshold(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show suspend_current_threshold : %d\n",
suspend_current_threshold);
return sprintf(buf, "%d\n", suspend_current_threshold);
}
static ssize_t store_FG_suspend_current_threshold(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[%s]\n", __func__);
if (buf != NULL && size != 0) {
bm_debug("[%s] buf is %s\n",
__func__, buf);
ret = kstrtouint(buf, 10, &val);
if (val < 100)
val = 100;
suspend_current_threshold = val;
bm_debug(
"[%s] suspend_current_threshold=%d\n",
__func__, suspend_current_threshold);
}
return size;
}
static DEVICE_ATTR(FG_suspend_current_threshold, 0664,
show_FG_suspend_current_threshold,
store_FG_suspend_current_threshold);
static ssize_t show_FG_ocv_check_time(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] show %s : %d\n", __func__, ocv_check_time);
return sprintf(buf, "%d\n", ocv_check_time);
}
static ssize_t store_FG_ocv_check_time(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val = 0;
int ret = 0;
bm_debug("[%s]\n", __func__);
if (buf != NULL && size != 0) {
bm_debug("[%s] buf is %s\n", __func__, buf);
ret = kstrtoul(buf, 10, &val);
if (val < 100)
val = 100;
ocv_check_time = val;
bm_debug("[store_ocv_check_time] ocv_check_time=%d\n",
ocv_check_time);
}
return size;
}
static DEVICE_ATTR(FG_ocv_check_time, 0664, show_FG_ocv_check_time,
store_FG_ocv_check_time);
static ssize_t show_FG_difference_voltage_update(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show ocv_check_time : %d\n", ocv_check_time);
return sprintf(buf, "%d\n", ocv_check_time);
}
static ssize_t store_FG_difference_voltage_update(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val = 0;
int ret = 0;
bm_debug("[%s]\n", __func__);
if (buf != NULL && size != 0) {
bm_debug("[%s] buf is %s\n",
__func__, buf);
ret = kstrtoul(buf, 10, &val);
if (val < 0)
val = 0;
difference_voltage_update = val;
bm_debug(
"[%s] difference_voltage_update=%d\n",
__func__, difference_voltage_update);
}
return size;
}
static DEVICE_ATTR(FG_difference_voltage_update, 0664,
show_FG_difference_voltage_update,
store_FG_difference_voltage_update);
static ssize_t show_FG_aging1_load_soc(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] show aging1_load_soc : %d\n", aging1_load_soc);
return sprintf(buf, "%d\n", aging1_load_soc);
}
static ssize_t store_FG_aging1_load_soc(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[%s]\n", __func__);
if (buf != NULL && size != 0) {
bm_debug("[%s] buf is %s\n", __func__, buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
if (val > 100)
val = 100;
aging1_load_soc = val;
bm_debug("[store_aging1_load_soc] aging1_load_soc=%d\n",
aging1_load_soc);
}
return size;
}
static DEVICE_ATTR(FG_aging1_load_soc, 0664, show_FG_aging1_load_soc,
store_FG_aging1_load_soc);
static ssize_t show_FG_aging1_update_soc(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show %s : %d\n", __func__, aging1_update_soc);
return sprintf(buf, "%d\n", aging1_update_soc);
}
static ssize_t store_FG_aging1_update_soc(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[%s]\n", __func__);
if (buf != NULL && size != 0) {
bm_debug("[%s] buf is %s\n", __func__, buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
if (val > 100)
val = 100;
aging1_update_soc = val;
bm_debug("[%s] aging1_update_soc=%d\n",
__func__, aging1_update_soc);
}
return size;
}
static DEVICE_ATTR(FG_aging1_update_soc, 0664, show_FG_aging1_update_soc,
store_FG_aging1_update_soc);
static ssize_t show_FG_shutdown_system_voltage(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show %s : %d\n",
__func__, shutdown_system_voltage);
return sprintf(buf, "%d\n", shutdown_system_voltage);
}
static ssize_t store_FG_shutdown_system_voltage(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[shutdown_system_voltage]\n");
if (buf != NULL && size != 0) {
bm_debug("[shutdown_system_voltage] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
shutdown_system_voltage = val;
bm_debug(
"[shutdown_system_voltage] shutdown_system_voltage=%d\n",
shutdown_system_voltage);
}
return size;
}
static DEVICE_ATTR(FG_shutdown_system_voltage, 0664,
show_FG_shutdown_system_voltage,
store_FG_shutdown_system_voltage);
static ssize_t show_FG_charge_tracking_time(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show charge_tracking_time : %d\n", charge_tracking_time);
return sprintf(buf, "%d\n", charge_tracking_time);
}
static ssize_t store_FG_charge_tracking_time(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[charge_tracking_time]\n");
if (buf != NULL && size != 0) {
bm_debug("[charge_tracking_time] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
charge_tracking_time = val;
bm_debug("[charge_tracking_time] charge_tracking_time=%d\n",
charge_tracking_time);
}
return size;
}
static DEVICE_ATTR(FG_charge_tracking_time, 0664, show_FG_charge_tracking_time,
store_FG_charge_tracking_time);
static ssize_t show_FG_discharge_tracking_time(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show discharge_tracking_time : %d\n",
discharge_tracking_time);
return sprintf(buf, "%d\n", discharge_tracking_time);
}
static ssize_t store_FG_discharge_tracking_time(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[discharge_tracking_time]\n");
if (buf != NULL && size != 0) {
bm_debug("[discharge_tracking_time] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
discharge_tracking_time = val;
bm_debug(
"[discharge_tracking_time] discharge_tracking_time=%d\n",
discharge_tracking_time);
}
return size;
}
static DEVICE_ATTR(FG_discharge_tracking_time, 0664,
show_FG_discharge_tracking_time,
store_FG_discharge_tracking_time);
#endif
static ssize_t show_FG_shutdown_gauge0(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] show shutdown_gauge0 : %d\n", shutdown_gauge0);
return sprintf(buf, "%d\n", shutdown_gauge0);
}
static ssize_t store_FG_shutdown_gauge0(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[shutdown_gauge0]\n");
if (buf != NULL && size != 0) {
bm_debug("[shutdown_gauge0] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
shutdown_gauge0 = val;
bm_debug("[shutdown_gauge0] shutdown_gauge0=%d\n",
shutdown_gauge0);
}
return size;
}
static DEVICE_ATTR(FG_shutdown_gauge0, 0664, show_FG_shutdown_gauge0,
store_FG_shutdown_gauge0);
static ssize_t show_FG_shutdown_gauge1_xmins(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show shutdown_gauge1_xmins : %d\n",
shutdown_gauge1_xmins);
return sprintf(buf, "%d\n", shutdown_gauge1_xmins);
}
static ssize_t store_FG_shutdown_gauge1_xmins(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[shutdown_gauge1_xmins]\n");
if (buf != NULL && size != 0) {
bm_debug("[shutdown_gauge1_xmins] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
shutdown_gauge1_xmins = val;
bm_debug("[shutdown_gauge1_xmins] shutdown_gauge1_xmins=%d\n",
shutdown_gauge1_xmins);
}
return size;
}
static DEVICE_ATTR(FG_shutdown_gauge1_xmins, 0664,
show_FG_shutdown_gauge1_xmins,
store_FG_shutdown_gauge1_xmins);
static ssize_t show_FG_shutdown_gauge1_mins(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_debug("[FG] show shutdown_gauge1_mins : %d\n", shutdown_gauge1_mins);
return sprintf(buf, "%d\n", shutdown_gauge1_mins);
}
static ssize_t store_FG_shutdown_gauge1_mins(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned int val = 0;
int ret;
bm_debug("[shutdown_gauge1_mins]\n");
if (buf != NULL && size != 0) {
bm_debug("[shutdown_gauge1_mins] buf is %s\n", buf);
ret = kstrtouint(buf, 10, &val);
if (val < 0)
val = 0;
shutdown_gauge1_mins = val;
bm_debug("[shutdown_gauge1_mins] shutdown_gauge1_mins=%d\n",
shutdown_gauge1_mins);
}
return size;
}
static DEVICE_ATTR(FG_shutdown_gauge1_mins, 0664, show_FG_shutdown_gauge1_mins,
store_FG_shutdown_gauge1_mins);
static ssize_t show_FG_daemon_log_level(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bm_trace("[FG] show FG_daemon_log_level : %d\n", gFG_daemon_log_level);
return sprintf(buf, "%d\n", gFG_daemon_log_level);
}
static ssize_t store_FG_daemon_log_level(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val = 0;
int ret;
bm_debug("[FG_daemon_log_level]\n");
if (buf != NULL && size != 0) {
bm_debug("[FG_daemon_log_level] buf is %s\n", buf);
ret = kstrtoul(buf, 10, &val);
if (val < 0) {
bm_debug("[FG_daemon_log_level] val is %d ??\n",
(int)val);
val = 0;
}
gFG_daemon_log_level = val;
bm_debug("[FG_daemon_log_level] gFG_daemon_log_level=%d\n",
gFG_daemon_log_level);
}
return size;
}
static DEVICE_ATTR(FG_daemon_log_level, 0664, show_FG_daemon_log_level,
store_FG_daemon_log_level);
static ssize_t show_FG_daemon_disable(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_trace("[FG] show FG_daemon_log_level : %d\n", gDisableFG);
return sprintf(buf, "%d\n", gDisableFG);
}
static ssize_t store_FG_daemon_disable(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
bm_debug("[disable FG daemon]\n");
BMT_status.UI_SOC2 = 50;
if (!g_battery_soc_ready) {
g_battery_soc_ready = KAL_TRUE;
gfg_percent_check_point = 50;
}
bat_update_thread_wakeup();
gDisableFG = 1;
return size;
}
static DEVICE_ATTR(FG_daemon_disable, 0664, show_FG_daemon_disable,
store_FG_daemon_disable);
static ssize_t show_FG_drv_force25c(struct device *dev,
struct device_attribute *attr, char *buf)
{
bm_debug("[FG] show FG_drv_force25c : %d\n",
batt_meter_cust_data.fixed_tbat_25);
return sprintf(buf, "%d\n", batt_meter_cust_data.fixed_tbat_25);
}
static ssize_t store_FG_drv_force25c(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
unsigned long val = 0;
int ret;
bm_debug("[Enable FG_drv_force25c]\n");
batt_meter_cust_data.fixed_tbat_25 = 1;
if (buf != NULL && size != 0) {
bm_debug("[FG_drv_force25c] buf is %s\n", buf);
ret = kstrtoul(buf, 10, &val);
if (val < 0) {
bm_debug("[FG_drv_force25c] val is %d ??\n", (int)val);
val = 0;
}
batt_meter_cust_data.fixed_tbat_25 = val;
bm_debug("[FG_drv_force25c] fixed_tbat_25=%d, ret=%d\n",
batt_meter_cust_data.fixed_tbat_25, ret);
}
return size;
}
static DEVICE_ATTR(FG_drv_force25c, 0664, show_FG_drv_force25c,
store_FG_drv_force25c);
#ifdef FG_BAT_INT
unsigned char reset_fg_bat_int = KAL_TRUE;
signed int fg_bat_int_coulomb_pre;
signed int fg_bat_int_coulomb;
void fg_bat_int_handler(void)
{
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&fg_bat_int_coulomb);
battery_log(BAT_LOG_CRTI, "%s %d %d\n", __func__,
fg_bat_int_coulomb_pre, fg_bat_int_coulomb);
reset_fg_bat_int = KAL_TRUE;
if (bat_is_charger_exist() == KAL_FALSE) {
battery_log(BAT_LOG_CRTI, "wake up user space >>\n");
/* self_correct_dod_scheme(duration_time); */
wakeup_fg_algo(FG_RESUME);
}
}
signed int battery_meter_set_columb_interrupt(unsigned int val)
{
battery_log(BAT_LOG_FULL, "%s=%d\n",
__func__, val);
battery_meter_ctrl(BATTERY_METER_CMD_SET_COLUMB_INTERRUPT, &val);
return 0;
}
#endif
static int battery_meter_probe(struct platform_device *dev)
{
int ret_device_file = 0;
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
char *temp_strptr;
#endif
bm_info("[%s] probe\n", __func__);
/* select battery meter control method */
battery_meter_ctrl = bm_ctrl_cmd;
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
if (get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT ||
get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT) {
temp_strptr =
kzalloc(strlen(saved_command_line) +
strlen(" androidboot.mode=charger") + 1,
GFP_KERNEL);
strncpy(temp_strptr, saved_command_line,
strlen(saved_command_line));
strncat(temp_strptr, " androidboot.mode=charger",
strlen(" androidboot.mode=charger") + 1);
saved_command_line = temp_strptr;
}
#endif
/* LOG System Set */
init_proc_log_fg();
/* last_oam_run_time = rtc_read_hw_time(); */
getrawmonotonic(&last_oam_run_time);
/* Create File For FG UI DEBUG */
ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_Current);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_volt);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_g_fg_dbg_bat_current);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_zcv);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_temp);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_r);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_car);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_qmax);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d0);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d1);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_g_fg_dbg_percentage);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_fg);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_uisoc);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_voltmode);
#ifdef MTK_ENABLE_AGING_ALGORITHM
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_suspend_current_threshold);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_ocv_check_time);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_difference_voltage_update);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_aging1_load_soc);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_aging1_update_soc);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_shutdown_system_voltage);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_charge_tracking_time);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_discharge_tracking_time);
#endif
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_shutdown_gauge0);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_shutdown_gauge1_xmins);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_shutdown_gauge1_mins);
#ifdef MTK_BATTERY_LIFETIME_DATA_SUPPORT
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_Battery_Cycle);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_Aging_Factor);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_Max_Battery_Voltage);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_Min_Battery_Voltage);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_Max_Battery_Current);
ret_device_file = device_create_file(&(dev->dev),
&dev_attr_FG_Min_Battery_Current);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_Max_Battery_Temperature);
ret_device_file = device_create_file(
&(dev->dev), &dev_attr_FG_Min_Battery_Temperature);
#endif
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_daemon_log_level);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_daemon_disable);
ret_device_file =
device_create_file(&(dev->dev), &dev_attr_FG_drv_force25c);
batt_meter_init_cust_data(dev);
#if defined(FG_BAT_INT)
pmic_register_interrupt_callback(FG_BAT_INT_L_NO, fg_bat_int_handler);
pmic_register_interrupt_callback(FG_BAT_INT_H_NO, fg_bat_int_handler);
#endif
return 0;
}
static int battery_meter_remove(struct platform_device *dev)
{
bm_debug("[%s]\n", __func__);
return 0;
}
static void battery_meter_shutdown(struct platform_device *dev)
{
}
static int battery_meter_suspend(struct platform_device *dev,
pm_message_t state)
{
/* -- hibernation path */
if (state.event == PM_EVENT_FREEZE) {
pr_notice("[%s] %p:%p\n", __func__, battery_meter_ctrl,
&bm_ctrl_cmd);
battery_meter_ctrl = bm_ctrl_cmd;
}
/* -- end of hibernation path */
#if defined(FG_BAT_INT)
#if defined(CONFIG_POWER_EXT)
#elif defined(SOC_BY_HW_FG)
if (reset_fg_bat_int == KAL_TRUE) {
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&fg_bat_int_coulomb_pre);
bm_notice(
"[%s]enable battery_meter_set_columb_interrupt %d\n",
__func__, batt_meter_cust_data.q_max_pos_25);
battery_meter_set_columb_interrupt(
batt_meter_cust_data.q_max_pos_25 / 100);
/*battery_meter_set_columb_interrupt(1); */
reset_fg_bat_int = KAL_FALSE;
} else {
bm_notice(
"[%s]do not enable battery_meter_set_columb_interrupt %d\n",
__func__, batt_meter_cust_data.q_max_pos_25);
battery_meter_set_columb_interrupt(0x1ffff);
}
#endif
#else
#endif /* #if defined(FG_BAT_INT) */
#if defined(CONFIG_POWER_EXT)
#elif defined(SOC_BY_SW_FG) || defined(SOC_BY_HW_FG)
{
#if defined(SOC_BY_SW_FG)
{
get_monotonic_boottime(&ap_suspend_time);
}
#endif
battery_meter_ctrl(BATTERY_METER_CMD_GET_REFRESH_HW_OCV,
&hwocv_token);
#ifdef MTK_POWER_EXT_DETECT
if (bat_is_ext_power() == KAL_TRUE)
return 0;
#endif
mt_battery_update_time(&car_time, CAR_TIME);
add_time = mt_battery_get_duration_time(CAR_TIME);
if ((g_sleep_total_time.tv_sec < g_spm_timer) &&
g_sleep_total_time.tv_sec != 0) {
if (wake_up_smooth_time == 0)
return 0;
else if (g_sleep_total_time.tv_sec <
wake_up_smooth_time)
return 0;
}
battery_meter_reset_sleep_time();
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV,
&g_hw_ocv_before_sleep);
bm_info("[%s]sleep_total_time = %d, last_time = %d\n",
__func__,
(int)g_sleep_total_time.tv_sec, last_time);
}
#endif
return 0;
}
static int battery_meter_resume(struct platform_device *dev)
{
#if defined(CONFIG_POWER_EXT)
#elif defined(SOC_BY_SW_FG) || defined(SOC_BY_HW_FG)
unsigned int duration_time = 0;
#ifdef MTK_POWER_EXT_DETECT
if (bat_is_ext_power() == KAL_TRUE)
return 0;
#endif
mt_battery_update_time(&suspend_time, SUSPEND_TIME);
add_time = mt_battery_get_duration_time_act(SUSPEND_TIME).tv_sec;
g_sleep_total_time =
timespec_add(g_sleep_total_time,
mt_battery_get_duration_time_act(SUSPEND_TIME));
bm_info("[%s] sleep time = %d, duration_time = %d, wake_up_smooth_time %d, g_spm_timer = %d\n",
__func__, (int)g_sleep_total_time.tv_sec,
duration_time, wake_up_smooth_time, g_spm_timer);
#if defined(SOC_BY_HW_FG)
#ifdef MTK_ENABLE_AGING_ALGORITHM
if (g_sleep_total_time.tv_sec < g_spm_timer) {
if (wake_up_smooth_time == 0) {
if (bat_is_charger_exist() == KAL_FALSE) {
/* self_correct_dod_scheme(duration_time); */
wakeup_fg_algo(FG_RESUME);
}
return 0;
} else if (g_sleep_total_time.tv_sec < wake_up_smooth_time) {
if (bat_is_charger_exist() == KAL_FALSE) {
/* self_correct_dod_scheme(duration_time); */
wakeup_fg_algo(FG_RESUME);
}
return 0;
}
}
#endif
bm_info("* %s!! * suspend_time %d smooth_time %d g_spm_timer %d\n",
__func__,
(int)g_sleep_total_time.tv_sec, wake_up_smooth_time,
g_spm_timer);
bat_spm_timeout = true;
if (g_sleep_total_time.tv_sec >= wake_up_smooth_time)
wake_up_smooth_time = 0;
#elif defined(SOC_BY_SW_FG)
if (bat_is_charger_exist() == KAL_FALSE) {
unsigned int time;
signed int voltage = 0;
int oam_i = 0, oam_car_tmp;
/* mt_battery_update_time(&ap_suspend_time, AP_SUSPEND_TIME); */
/* time = mt_battery_get_duration_time(AP_SUSPEND_TIME); */
time = add_time;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &voltage);
total_suspend_times++;
this_suspend_times++;
if (voltage == hwocv_token) {
oam_car_tmp = -time * APSLEEP_MDWAKEUP_CAR;
bm_print(
BM_LOG_CRTI,
"[%s](1)time:%d bat:%d ocv:%d r:%d i:%d ocar:%d card:%d lbat:%d %d\n",
__func__, time, voltage,
oam_v_ocv, oam_r, oam_i,
ap_suspend_car / 3600, oam_car_tmp / 3600,
pmic_get_register_value(PMIC_RG_ADC_OUT_LBAT),
pmic_get_register_value(
PMIC_RG_LBAT_DEBOUNCE_COUNT_MIN));
last_hwocv = 0;
last_i = 0;
is_hwocv_update = KAL_FALSE;
} else {
oam_car_tmp = -time * AP_MDSLEEP_CAR;
last_hwocv = voltage;
last_i = oam_i;
is_hwocv_update = KAL_TRUE;
bm_print(
BM_LOG_CRTI,
"[%s](2)time:%d bat:%d ocv:%d r:%d i:%d",
"ocar:%d card:%d lbat:%d %d\n",
__func__, time, voltage,
oam_v_ocv, oam_r, oam_i,
ap_suspend_car / 3600, oam_car_tmp / 3600,
pmic_get_register_value(PMIC_RG_ADC_OUT_LBAT),
pmic_get_register_value(
PMIC_RG_LBAT_DEBOUNCE_COUNT_MIN));
}
swfg_ap_suspend_time = g_sleep_total_time.tv_sec;
ap_suspend_car = ap_suspend_car + oam_car_tmp;
if (abs(ap_suspend_car / 3600) > 100) {
bat_spm_timeout = true;
return 0;
}
if (g_sleep_total_time.tv_sec > wake_up_smooth_time &&
wake_up_smooth_time != 0) {
wake_up_smooth_time = 0;
bat_spm_timeout = true;
return 0;
}
if (swfg_ap_suspend_time > 600) {
bat_spm_timeout = true;
return 0;
}
return 0;
}
#endif
#endif
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id mt_bat_meter_of_match[] = {
{
.compatible = "mediatek,bat_meter",
},
{},
};
MODULE_DEVICE_TABLE(of, mt_bat_meter_of_match);
#endif
struct platform_device battery_meter_device = {
.name = "battery_meter", .id = -1,
};
static struct platform_driver battery_meter_driver = {
.probe = battery_meter_probe,
.remove = battery_meter_remove,
.shutdown = battery_meter_shutdown,
.suspend = battery_meter_suspend,
.resume = battery_meter_resume,
.driver = {
.name = "battery_meter",
},
};
static int battery_meter_dts_probe(struct platform_device *dev)
{
int ret = 0;
bm_err("******** %s!! ********\n", __func__);
battery_meter_device.dev.of_node = dev->dev.of_node;
ret = platform_device_register(&battery_meter_device);
if (ret) {
bm_err("****[%s] Unable to register device (%d)\n",
__func__, ret);
return ret;
}
return 0;
}
static struct platform_driver battery_meter_dts_driver = {
.probe = battery_meter_dts_probe,
.remove = NULL,
.shutdown = NULL,
.suspend = NULL,
.resume = NULL,
.driver = {
.name = "battery_meter_dts",
#ifdef CONFIG_OF
.of_match_table = mt_bat_meter_of_match,
#endif
},
};
void bmd_ctrl_cmd_from_user(void *nl_data, struct fgd_nl_msg_t *ret_msg)
{
struct fgd_nl_msg_t *msg;
msg = nl_data;
ret_msg->fgd_cmd = msg->fgd_cmd;
switch (msg->fgd_cmd) {
case FG_DAEMON_CMD_GET_INIT_FLAG: {
ret_msg->fgd_data_len += sizeof(init_flag);
memcpy(ret_msg->fgd_data, &init_flag, sizeof(init_flag));
bm_debug("[fg_res] init_flag = %d\n", init_flag);
} break;
case FG_DAEMON_CMD_GET_SOC: {
ret_msg->fgd_data_len += sizeof(gFG_capacity_by_c);
memcpy(ret_msg->fgd_data, &gFG_capacity_by_c,
sizeof(gFG_capacity_by_c));
bm_debug("[fg_res] gFG_capacity_by_c = %d\n",
gFG_capacity_by_c);
} break;
case FG_DAEMON_CMD_GET_DOD0: {
if (init_flag == KAL_FALSE) {
gFG_DOD0 = dod_init_in_kernel();
bm_print(BM_LOG_CRTI,
"[fg_res][D0_init_in_kernel] gFG_DOD0 = %d\n",
gFG_DOD0);
}
ret_msg->fgd_data_len += sizeof(gFG_DOD0);
memcpy(ret_msg->fgd_data, &gFG_DOD0, sizeof(gFG_DOD0));
bm_debug("[fg_res] gFG_DOD0 = %d\n", gFG_DOD0);
} break;
case FG_DAEMON_CMD_GET_DOD1: {
ret_msg->fgd_data_len += sizeof(gFG_DOD1);
memcpy(ret_msg->fgd_data, &gFG_DOD1, sizeof(gFG_DOD1));
bm_debug("[fg_res] gFG_DOD1 = %d\n", gFG_DOD1);
} break;
case FG_DAEMON_CMD_GET_HW_OCV: {
signed int voltage = 0;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &voltage);
ret_msg->fgd_data_len += sizeof(voltage);
memcpy(ret_msg->fgd_data, &voltage, sizeof(voltage));
bm_debug("[fg_res] voltage = %d\n", voltage);
gFG_hwocv = voltage;
} break;
case FG_DAEMON_CMD_GET_HW_FG_INIT_CURRENT: {
ret_msg->fgd_data_len += sizeof(gFG_current_init);
memcpy(ret_msg->fgd_data, &gFG_current_init,
sizeof(gFG_current_init));
bm_debug("[fg_res] init fg_current = %d\n", gFG_current_init);
gFG_current = gFG_current_init;
} break;
case FG_DAEMON_CMD_GET_HW_FG_CURRENT: {
signed int fg_current = 0;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT,
&fg_current);
ret_msg->fgd_data_len += sizeof(fg_current);
memcpy(ret_msg->fgd_data, &fg_current, sizeof(fg_current));
bm_debug("[fg_res] fg_current = %d\n", fg_current);
gFG_current = fg_current;
} break;
case FG_DAEMON_CMD_GET_HW_FG_INIT_CURRENT_SIGN: {
ret_msg->fgd_data_len += sizeof(gFG_Is_Charging_init);
memcpy(ret_msg->fgd_data, &gFG_Is_Charging_init,
sizeof(gFG_Is_Charging_init));
bm_debug("[fg_res] current_state = %d\n", gFG_Is_Charging_init);
gFG_Is_Charging = gFG_Is_Charging_init;
} break;
case FG_DAEMON_CMD_GET_HW_FG_CURRENT_SIGN: {
kal_bool current_state = KAL_FALSE;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN,
&current_state);
ret_msg->fgd_data_len += sizeof(current_state);
memcpy(ret_msg->fgd_data, &current_state,
sizeof(current_state));
bm_debug("[fg_res] current_state = %d\n", current_state);
gFG_Is_Charging = current_state;
} break;
case FG_DAEMON_CMD_GET_HW_FG_CAR_ACT: {
signed int fg_coulomb = 0;
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT,
&fg_coulomb);
ret_msg->fgd_data_len += sizeof(fg_coulomb);
memcpy(ret_msg->fgd_data, &fg_coulomb, sizeof(fg_coulomb));
bm_debug("[fg_res] fg_coulomb = %d\n", fg_coulomb);
gFG_coulomb_act = fg_coulomb;
break;
}
case FG_DAEMON_CMD_GET_TEMPERTURE: {
kal_bool update;
int temperture = 0;
memcpy(&update, &msg->fgd_data[0], sizeof(update));
bm_debug("[fg_res] update = %d\n", update);
temperture = force_get_tbat(update);
bm_debug("[fg_res] temperture = %d\n", temperture);
ret_msg->fgd_data_len += sizeof(temperture);
memcpy(ret_msg->fgd_data, &temperture, sizeof(temperture));
gFG_temp = temperture;
} break;
case FG_DAEMON_CMD_DUMP_REGISTER:
battery_meter_ctrl(BATTERY_METER_CMD_DUMP_REGISTER, NULL);
break;
case FG_DAEMON_CMD_CHARGING_ENABLE: {
kal_bool charging_enable = KAL_FALSE;
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
ret_msg->fgd_data_len += sizeof(charging_enable);
memcpy(ret_msg->fgd_data, &charging_enable,
sizeof(charging_enable));
bm_debug("[fg_res] charging_enable = %d\n", charging_enable);
} break;
case FG_DAEMON_CMD_GET_BATTERY_INIT_VOLTAGE: {
ret_msg->fgd_data_len += sizeof(gFG_voltage_init);
memcpy(ret_msg->fgd_data, &gFG_voltage_init,
sizeof(gFG_voltage_init));
bm_debug("[fg_res] voltage = %d\n", gFG_voltage_init);
} break;
case FG_DAEMON_CMD_GET_BATTERY_VOLTAGE: {
signed int update;
int voltage = 0;
memcpy(&update, &msg->fgd_data[0], sizeof(update));
bm_debug("[fg_res] update = %d\n", update);
if (update == 1)
voltage = battery_meter_get_battery_voltage(KAL_TRUE);
else
voltage = BMT_status.bat_vol;
ret_msg->fgd_data_len += sizeof(voltage);
memcpy(ret_msg->fgd_data, &voltage, sizeof(voltage));
bm_debug("[fg_res] voltage = %d\n", voltage);
} break;
case FG_DAEMON_CMD_FGADC_RESET:
bm_debug("[fg_res] fgadc_reset\n");
battery_meter_ctrl(BATTERY_METER_CMD_HW_RESET, NULL);
#ifdef FG_BAT_INT
reset_fg_bat_int = KAL_TRUE;
#endif
#ifdef USING_SMOOTH_UI_SOC2
pre_cc_act = 0;
#endif
break;
case FG_DAEMON_CMD_GET_BATTERY_PLUG_STATUS: {
int plugout_status = 0;
battery_meter_ctrl(BATTERY_METER_CMD_GET_BATTERY_PLUG_STATUS,
&plugout_status);
ret_msg->fgd_data_len += sizeof(plugout_status);
memcpy(ret_msg->fgd_data, &plugout_status,
sizeof(plugout_status));
bm_debug("[fg_res] plugout_status = %d\n", plugout_status);
gFG_plugout_status = plugout_status;
} break;
case FG_DAEMON_CMD_GET_RTC_SPARE_FG_VALUE: {
signed int rtc_fg_soc = 0;
rtc_fg_soc = get_rtc_spare_fg_value();
ret_msg->fgd_data_len += sizeof(rtc_fg_soc);
memcpy(ret_msg->fgd_data, &rtc_fg_soc, sizeof(rtc_fg_soc));
bm_debug("[fg_res] rtc_fg_soc = %d\n", rtc_fg_soc);
} break;
case FG_DAEMON_CMD_IS_CHARGER_EXIST: {
kal_bool charger_exist = KAL_FALSE;
charger_exist = bat_is_charger_exist();
ret_msg->fgd_data_len += sizeof(charger_exist);
memcpy(ret_msg->fgd_data, &charger_exist,
sizeof(charger_exist));
bm_debug("[fg_res] charger_exist = %d\n", charger_exist);
} break;
case FG_DAEMON_CMD_IS_BATTERY_FULL: {
kal_bool battery_full = KAL_FALSE;
battery_full = BMT_status.bat_full;
ret_msg->fgd_data_len += sizeof(battery_full);
memcpy(ret_msg->fgd_data, &battery_full, sizeof(battery_full));
bm_debug("[fg_res] battery_full = %d\n", battery_full);
} break;
case FG_DAEMON_CMD_GET_BOOT_REASON: {
signed int boot_reason = get_boot_reason();
ret_msg->fgd_data_len += sizeof(boot_reason);
memcpy(ret_msg->fgd_data, &boot_reason, sizeof(boot_reason));
bm_debug(" ret_msg->fgd_data_len %d\n", ret_msg->fgd_data_len);
bm_debug("[fg_res] g_boot_reason = %d\n", boot_reason);
} break;
case FG_DAEMON_CMD_GET_CHARGING_CURRENT: {
signed int ICharging = battery_meter_get_charging_current();
ret_msg->fgd_data_len += sizeof(ICharging);
memcpy(ret_msg->fgd_data, &ICharging, sizeof(ICharging));
bm_debug("[fg_res] ICharging = %d\n", ICharging);
} break;
case FG_DAEMON_CMD_GET_CHARGER_VOLTAGE: {
signed int charger_vol = battery_meter_get_charger_voltage();
ret_msg->fgd_data_len += sizeof(charger_vol);
memcpy(ret_msg->fgd_data, &charger_vol, sizeof(charger_vol));
bm_debug("[fg_res] charger_vol = %d\n", charger_vol);
} break;
case FG_DAEMON_CMD_GET_SHUTDOWN_COND: {
unsigned int shutdown_cond =
0; /* mt_battery_shutdown_check(); move to user space */
ret_msg->fgd_data_len += sizeof(shutdown_cond);
memcpy(ret_msg->fgd_data, &shutdown_cond,
sizeof(shutdown_cond));
bm_debug("[fg_res] shutdown_cond = %d\n", shutdown_cond);
} break;
case FG_DAEMON_CMD_GET_CUSTOM_SETTING: {
kal_bool version;
memcpy(&version, &msg->fgd_data[0], sizeof(version));
bm_debug("[fg_res] version = %d\n", version);
if (version != CUST_SETTING_VERSION) {
bm_debug("ERROR version 0x%x, expect 0x%x\n", version,
CUST_SETTING_VERSION);
break;
}
memcpy(ret_msg->fgd_data, &batt_meter_cust_data,
sizeof(batt_meter_cust_data));
ret_msg->fgd_data_len += sizeof(batt_meter_cust_data);
memcpy(&ret_msg->fgd_data[ret_msg->fgd_data_len],
&batt_meter_table_cust_data,
sizeof(batt_meter_table_cust_data));
ret_msg->fgd_data_len += sizeof(batt_meter_table_cust_data);
bm_debug(
"k fgauge_construct_profile_init1 %d:%d %d:%d %d:%d %d:%d %d:%d\n",
batt_meter_table_cust_data.battery_profile_t0[0]
.percentage,
batt_meter_table_cust_data.battery_profile_t0[0]
.voltage,
batt_meter_table_cust_data.battery_profile_t0[10]
.percentage,
batt_meter_table_cust_data.battery_profile_t0[10]
.voltage,
batt_meter_table_cust_data.battery_profile_t0[20]
.percentage,
batt_meter_table_cust_data.battery_profile_t0[20]
.voltage,
batt_meter_table_cust_data.battery_profile_t0[30]
.percentage,
batt_meter_table_cust_data.battery_profile_t0[30]
.voltage,
batt_meter_table_cust_data.battery_profile_t0[40]
.percentage,
batt_meter_table_cust_data.battery_profile_t0[40]
.voltage);
} break;
case FG_DAEMON_CMD_GET_UI_SOC: {
ret_msg->fgd_data_len += sizeof(BMT_status.UI_SOC);
memcpy(ret_msg->fgd_data, &(BMT_status.UI_SOC),
sizeof(BMT_status.UI_SOC));
bm_debug("[fg_res] ui soc = %d\n", BMT_status.UI_SOC);
} break;
case FG_DAEMON_CMD_GET_CV_VALUE: {
unsigned int cv_voltage;
cv_voltage = get_cv_voltage();
ret_msg->fgd_data_len += sizeof(cv_voltage);
memcpy(ret_msg->fgd_data, &cv_voltage, sizeof(cv_voltage));
bm_debug("[fg_res] cv value = %d\n", cv_voltage);
} break;
case FG_DAEMON_CMD_GET_DURATION_TIME: {
int duration_time = 0;
BATTERY_TIME_ENUM duration_type;
memcpy(&duration_type, &msg->fgd_data[0],
sizeof(duration_type));
bm_debug("[fg_res] duration_type = %d\n", duration_type);
duration_time = mt_battery_get_duration_time(duration_type);
ret_msg->fgd_data_len += sizeof(duration_time);
memcpy(ret_msg->fgd_data, &duration_time,
sizeof(duration_time));
bm_debug("[fg_res] duration time = %d\n", duration_time);
} break;
case FG_DAEMON_CMD_GET_TRACKING_TIME: {
ret_msg->fgd_data_len += sizeof(battery_tracking_time);
memcpy(ret_msg->fgd_data, &battery_tracking_time,
sizeof(battery_tracking_time));
bm_debug("[fg_res] tracking time = %d\n",
battery_tracking_time);
} break;
case FG_DAEMON_CMD_GET_CURRENT_TH: {
ret_msg->fgd_data_len += sizeof(suspend_current_threshold);
memcpy(ret_msg->fgd_data, &suspend_current_threshold,
sizeof(suspend_current_threshold));
bm_debug("[fg_res] suspend_current_threshold = %d\n",
suspend_current_threshold);
} break;
case FG_DAEMON_CMD_GET_CHECK_TIME: {
ret_msg->fgd_data_len += sizeof(ocv_check_time);
memcpy(ret_msg->fgd_data, &ocv_check_time,
sizeof(ocv_check_time));
bm_debug("[fg_res] check time = %d\n", ocv_check_time);
} break;
case FG_DAEMON_CMD_GET_DIFFERENCE_VOLTAGE_UPDATE: {
ret_msg->fgd_data_len += sizeof(difference_voltage_update);
memcpy(ret_msg->fgd_data, &difference_voltage_update,
sizeof(difference_voltage_update));
bm_debug("[fg_res] difference_voltage_update = %d\n",
difference_voltage_update);
} break;
case FG_DAEMON_CMD_GET_AGING1_LOAD_SOC: {
ret_msg->fgd_data_len += sizeof(aging1_load_soc);
memcpy(ret_msg->fgd_data, &aging1_load_soc,
sizeof(aging1_load_soc));
bm_debug("[fg_res] aging1_load_soc = %d\n", aging1_load_soc);
} break;
case FG_DAEMON_CMD_GET_AGING1_UPDATE_SOC: {
ret_msg->fgd_data_len += sizeof(aging1_update_soc);
memcpy(ret_msg->fgd_data, &aging1_update_soc,
sizeof(aging1_update_soc));
bm_debug("[fg_res] aging1_update_soc = %d\n",
aging1_update_soc);
} break;
case FG_DAEMON_CMD_GET_SHUTDOWN_SYSTEM_VOLTAGE: {
ret_msg->fgd_data_len += sizeof(shutdown_system_voltage);
memcpy(ret_msg->fgd_data, &shutdown_system_voltage,
sizeof(shutdown_system_voltage));
bm_debug("[fg_res] shutdown_system_voltage = %d\n",
shutdown_system_voltage);
} break;
case FG_DAEMON_CMD_GET_CHARGE_TRACKING_TIME: {
ret_msg->fgd_data_len += sizeof(charge_tracking_time);
memcpy(ret_msg->fgd_data, &charge_tracking_time,
sizeof(charge_tracking_time));
bm_debug("[fg_res] charge_tracking_time = %d\n",
charge_tracking_time);
} break;
case FG_DAEMON_CMD_GET_DISCHARGE_TRACKING_TIME: {
ret_msg->fgd_data_len += sizeof(discharge_tracking_time);
memcpy(ret_msg->fgd_data, &discharge_tracking_time,
sizeof(discharge_tracking_time));
bm_debug("[fg_res] discharge_tracking_time = %d\n",
discharge_tracking_time);
} break;
case FG_DAEMON_CMD_GET_SHUTDOWN_GAUGE0: {
ret_msg->fgd_data_len += sizeof(shutdown_gauge0);
memcpy(ret_msg->fgd_data, &shutdown_gauge0,
sizeof(shutdown_gauge0));
bm_debug("[fg_res] shutdown_gauge0 = %d\n", shutdown_gauge0);
} break;
case FG_DAEMON_CMD_GET_SHUTDOWN_GAUGE1_XMINS: {
ret_msg->fgd_data_len += sizeof(shutdown_gauge1_xmins);
memcpy(ret_msg->fgd_data, &shutdown_gauge1_xmins,
sizeof(shutdown_gauge1_xmins));
bm_debug("[fg_res] shutdown_gauge1_xmins = %d\n",
shutdown_gauge1_xmins);
} break;
case FG_DAEMON_CMD_GET_SHUTDOWN_GAUGE1_MINS: {
ret_msg->fgd_data_len += sizeof(shutdown_gauge1_mins);
memcpy(ret_msg->fgd_data, &shutdown_gauge1_mins,
sizeof(shutdown_gauge1_mins));
bm_debug("[fg_res] shutdown_gauge1_mins = %d\n",
shutdown_gauge1_mins);
} break;
case FG_DAEMON_CMD_SET_SUSPEND_TIME:
bm_debug("[fg_res] set suspend time\n");
get_monotonic_boottime(&suspend_time);
break;
case FG_DAEMON_CMD_SET_WAKEUP_SMOOTH_TIME: {
memcpy(&wake_up_smooth_time, &msg->fgd_data[0],
sizeof(wake_up_smooth_time));
bm_debug("[fg_res] wake_up_smooth_time = %d\n",
wake_up_smooth_time);
} break;
case FG_DAEMON_CMD_SET_IS_CHARGING: {
memcpy(&gFG_coulomb_is_charging, &msg->fgd_data[0],
sizeof(gFG_coulomb_is_charging));
bm_debug("[fg_res] is_charging = %d\n",
gFG_coulomb_is_charging);
} break;
case FG_DAEMON_CMD_SET_RBAT: {
memcpy(&gFG_resistance_bat, &msg->fgd_data[0],
sizeof(gFG_resistance_bat));
bm_debug("[fg_res] gFG_resistance_bat = %d\n",
gFG_resistance_bat);
} break;
case FG_DAEMON_CMD_SET_SWOCV: {
memcpy(&gFG_voltage, &msg->fgd_data[0], sizeof(gFG_voltage));
bm_debug("[fg_res] gFG_voltage = %d\n", gFG_voltage);
} break;
case FG_DAEMON_CMD_SET_DOD0: {
memcpy(&gFG_DOD0, &msg->fgd_data[0], sizeof(gFG_DOD0));
bm_debug("[fg_res] gFG_DOD0 = %d\n", gFG_DOD0);
} break;
case FG_DAEMON_CMD_SET_DOD1: {
memcpy(&gFG_DOD1, &msg->fgd_data[0], sizeof(gFG_DOD1));
bm_debug("[fg_res] gFG_DOD1 = %d\n", gFG_DOD1);
} break;
case FG_DAEMON_CMD_SET_QMAX: {
memcpy(&gFG_BATT_CAPACITY_aging, &msg->fgd_data[0],
sizeof(gFG_BATT_CAPACITY_aging));
bm_debug("[fg_res] QMAX = %d\n", gFG_BATT_CAPACITY_aging);
} break;
case FG_DAEMON_CMD_SET_BATTERY_FULL: {
signed int battery_full;
memcpy(&battery_full, &msg->fgd_data[0], sizeof(battery_full));
BMT_status.bat_full = (kal_bool)battery_full;
bm_debug("[fg_res] set bat_full = %d\n", BMT_status.bat_full);
} break;
case FG_DAEMON_CMD_SET_RTC: {
signed int rtcvalue;
memcpy(&rtcvalue, &msg->fgd_data[0], sizeof(rtcvalue));
set_rtc_spare_fg_value(rtcvalue);
bm_notice("[fg_res] set rtc = %d\n", rtcvalue);
} break;
case FG_DAEMON_CMD_SET_POWEROFF: {
bm_debug("[fg_res] FG_DAEMON_CMD_SET_POWEROFF\n");
kernel_power_off();
} break;
case FG_DAEMON_CMD_SET_INIT_FLAG: {
memcpy(&init_flag, &msg->fgd_data[0], sizeof(init_flag));
bm_notice("[fg_res] init_flag = %d\n", init_flag);
} break;
case FG_DAEMON_CMD_IS_KPOC: {
signed int kpoc = bat_is_kpoc();
ret_msg->fgd_data_len += sizeof(kpoc);
memcpy(ret_msg->fgd_data, &kpoc, sizeof(kpoc));
bm_debug("[fg_res] query kpoc = %d\n", kpoc);
} break;
case FG_DAEMON_CMD_SET_SOC: {
memcpy(&gFG_capacity_by_c, &msg->fgd_data[0],
sizeof(gFG_capacity_by_c));
bm_debug("[fg_res] SOC = %d\n", gFG_capacity_by_c);
BMT_status.SOC = gFG_capacity_by_c;
} break;
case FG_DAEMON_CMD_SET_UI_SOC: {
signed int UI_SOC;
memcpy(&UI_SOC, &msg->fgd_data[0], sizeof(UI_SOC));
bm_debug("[fg_res] UI_SOC = %d\n", UI_SOC);
BMT_status.UI_SOC = UI_SOC;
} break;
case FG_DAEMON_CMD_SET_UI_SOC2: {
signed int UI_SOC;
memcpy(&UI_SOC, &msg->fgd_data[0], sizeof(UI_SOC));
bm_debug("[fg_res] UI_SOC2 = %d\n", UI_SOC);
#ifdef USING_SMOOTH_UI_SOC2
temp_UI_SOC2 = UI_SOC;
#else
BMT_status.UI_SOC2 = UI_SOC;
#endif
if (!g_battery_soc_ready) {
g_battery_soc_ready = KAL_TRUE;
gfg_percent_check_point = UI_SOC;
}
bat_update_thread_wakeup();
/* wake_up_bat(); */
} break;
case FG_DAEMON_CMD_CHECK_FG_DAEMON_VERSION: {
memcpy(&g_fgd_version, &msg->fgd_data[0],
sizeof(g_fgd_version));
bm_debug("[fg_res] g_fgd_pid = %d\n", g_fgd_version);
if (g_fgd_version != FGD_CHECK_VERSION) {
bm_err("bad FG_DAEMON_VERSION 0x%x, 0x%x\n",
FGD_CHECK_VERSION, g_fgd_version);
} else {
bm_debug("FG_DAEMON_VERSION OK\n");
}
} break;
case FG_DAEMON_CMD_SET_DAEMON_PID: {
memcpy(&g_fgd_pid, &msg->fgd_data[0], sizeof(g_fgd_pid));
bm_debug("[fg_res] g_fgd_pid = %d\n", g_fgd_pid);
} break;
case FG_DAEMON_CMD_SET_OAM_V_OCV: {
signed int tmp;
memcpy(&tmp, &msg->fgd_data[0], sizeof(tmp));
bm_print(BM_LOG_CRTI, "[fg_res] OAM_V_OCV = %d\n", tmp);
oam_v_ocv = tmp;
} break;
case FG_DAEMON_CMD_SET_OAM_R: {
signed int tmp;
memcpy(&tmp, &msg->fgd_data[0], sizeof(tmp));
bm_print(BM_LOG_CRTI, "[fg_res] OAM_R = %d\n", tmp);
oam_r = tmp;
} break;
case FG_DAEMON_CMD_GET_SUSPEND_TIME: {
ret_msg->fgd_data_len += sizeof(swfg_ap_suspend_time);
memcpy(ret_msg->fgd_data, &swfg_ap_suspend_time,
sizeof(swfg_ap_suspend_time));
bm_print(BM_LOG_CRTI, "[fg_res] suspend_time = %d\n",
swfg_ap_suspend_time);
swfg_ap_suspend_time = 0;
} break;
case FG_DAEMON_CMD_GET_SUSPEND_CAR: {
signed int car = ap_suspend_car / 3600;
ret_msg->fgd_data_len += sizeof(car);
memcpy(ret_msg->fgd_data, &car, sizeof(car));
bm_print(
BM_LOG_CRTI,
"[fg_res] ap_suspend_car:(%d:%d) t:%d hwocv:%d ocv:%d i:%d stime:%d:%d\n",
ap_suspend_car, car, swfg_ap_suspend_time, last_hwocv,
oam_v_ocv, last_i, total_suspend_times,
this_suspend_times);
ap_suspend_car = ap_suspend_car % 3600;
this_suspend_times = 0;
} break;
case FG_DAEMON_CMD_IS_HW_OCV_UPDATE: {
ret_msg->fgd_data_len += sizeof(is_hwocv_update);
memcpy(ret_msg->fgd_data, &is_hwocv_update,
sizeof(is_hwocv_update));
bm_print(BM_LOG_CRTI, "[fg_res] is_hwocv_update = %d\n",
is_hwocv_update);
is_hwocv_update = KAL_FALSE;
} break;
case FG_DAEMON_CMD_SET_SWSOC: {
signed int SWSOC;
memcpy(&SWSOC, &msg->fgd_data[0], sizeof(SWSOC));
bm_print(BM_LOG_CRTI, "[fg_res] SWSOC = %d\n", SWSOC);
gFG_sw_soc = SWSOC;
} break;
case FG_DAEMON_CMD_SET_HWSOC: {
signed int HWSOC;
memcpy(&HWSOC, &msg->fgd_data[0], sizeof(HWSOC));
bm_print(BM_LOG_CRTI, "[fg_res] HWSOC = %d\n", HWSOC);
gFG_hw_soc = HWSOC;
} break;
case FG_DAEMON_CMD_SET_VBATSOC: {
signed int VBATSOC;
memcpy(&VBATSOC, &msg->fgd_data[0], sizeof(VBATSOC));
bm_print(BM_LOG_CRTI, "[fg_res] VBATSOC = %d\n", VBATSOC);
gFG_vbat_soc = VBATSOC;
} break;
case FG_DAEMON_CMD_SET_CAR_TUNE_VALUE: {
signed int NVRAM_CAR_TUNE_VALUE;
memcpy(&NVRAM_CAR_TUNE_VALUE, &msg->fgd_data[0],
sizeof(NVRAM_CAR_TUNE_VALUE));
bm_notice("[fg_res] NVRAM_CAR_TUNE_VALUE = %d\n",
NVRAM_CAR_TUNE_VALUE);
batt_meter_cust_data.car_tune_value = NVRAM_CAR_TUNE_VALUE;
} break;
default:
bm_debug("bad FG_DAEMON_CTRL_CMD_FROM_USER 0x%x\n",
msg->fgd_cmd);
break;
} /* switch() */
}
int dod_init_in_kernel(void)
{
#if defined(FORCE_D0_IN_KERNEL)
int preD0 = 0;
int plugout_status = 0;
int rtc_fg_soc = 0;
bool chargerexist = KAL_FALSE;
battery_meter_ctrl(BATTERY_METER_CMD_GET_BATTERY_PLUG_STATUS,
&plugout_status);
rtc_fg_soc = get_rtc_spare_fg_value();
chargerexist = bat_is_charger_exist();
if (plugout_status == 0 && chargerexist == KAL_FALSE) {
if (rtc_fg_soc == 0) {
preD0 = gFG_sw_soc;
bm_print(BM_LOG_CRTI,
"[%s]use gFG_sw_soc\n", __func__);
} else {
preD0 = rtc_fg_soc;
bm_print(BM_LOG_CRTI,
"[%s]use rtc_fg_soc\n", __func__);
}
} else {
if ((abs(gFG_hw_soc - rtc_fg_soc) > 30) &&
(abs(gFG_hw_soc - gFG_sw_soc) <
abs(gFG_sw_soc - rtc_fg_soc))) {
if (abs(gFG_hw_soc - gFG_sw_soc) > 10) {
preD0 = gFG_sw_soc;
bm_print(
BM_LOG_CRTI,
"[%s]use gFG_sw_soc\n", __func__);
} else {
/* use hw ocv; */
preD0 = gFG_hw_soc;
bm_print(
BM_LOG_CRTI,
"[%s]use gFG_hw_soc\n", __func__);
}
} else {
if ((abs(rtc_fg_soc - gFG_sw_soc) > 10) ||
rtc_fg_soc == 0) {
preD0 = gFG_sw_soc;
bm_print(
BM_LOG_CRTI,
"[%s]use gFG_sw_soc\n", __func__);
} else {
preD0 = rtc_fg_soc;
bm_print(
BM_LOG_CRTI,
"[%s]use rtc_fg_soc\n", __func__);
}
}
}
bm_print(
BM_LOG_CRTI,
"[%s] rtc_fg_soc=%d, gFG_sw_soc=%d, gFG_hw_soc=%d, preD0=%d, plugout_status=%d, chargerexist=%d\n",
__func__, rtc_fg_soc, gFG_sw_soc,
gFG_hw_soc, preD0, plugout_status,
chargerexist);
gFG_DOD0 = 100 - preD0;
#else
gFG_DOD0 = 200;
#endif
bm_print(BM_LOG_CRTI, "[%s]gFG_DOD0 = %d\n", __func__, gFG_DOD0);
return gFG_DOD0;
}
static void nl_send_to_user(u32 pid, int seq, struct fgd_nl_msg_t *reply_msg)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
/* int size=sizeof(struct fgd_nl_msg_t); */
int size = reply_msg->fgd_data_len + FGD_NL_MSG_T_HDR_LEN;
int len = NLMSG_SPACE(size);
void *data;
int ret;
skb = alloc_skb(len, GFP_ATOMIC);
if (!skb)
return;
nlh = nlmsg_put(skb, pid, seq, 0, size, 0);
data = NLMSG_DATA(nlh);
memcpy(data, reply_msg, size);
NETLINK_CB(skb).portid = 0; /* from kernel */
NETLINK_CB(skb).dst_group = 0; /* unicast */
/* bm_debug("[Netlink] nl_reply_user: */
/* netlink_unicast size=%d fgd_cmd=%d */
/* pid=%d\n", */
/* /size, reply_msg->fgd_cmd, pid); */
ret = netlink_unicast(daemo_nl_sk, skb, pid, MSG_DONTWAIT);
if (ret < 0) {
bm_err("[Netlink] send failed %d\n", ret);
return;
}
/*bm_debug("[Netlink] reply_user: netlink_unicast- ret=%d\n", ret); */
}
static void nl_data_handler(struct sk_buff *skb)
{
u32 pid;
kuid_t uid;
int seq;
void *data;
struct nlmsghdr *nlh;
struct fgd_nl_msg_t *fgd_msg, *fgd_ret_msg;
int size = 0;
nlh = (struct nlmsghdr *)skb->data;
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
seq = nlh->nlmsg_seq;
/*bm_debug("[Netlink] recv skb from user space uid:%d pid:%d */
/* seq:%d\n",uid,pid,seq); */
data = NLMSG_DATA(nlh);
fgd_msg = (struct fgd_nl_msg_t *)data;
size = fgd_msg->fgd_ret_data_len + FGD_NL_MSG_T_HDR_LEN;
fgd_ret_msg = vmalloc(size);
if (!fgd_ret_msg) {
/* bm_err("Error: nl_data_handler() vmalloc fail!!!\n"); */
return;
}
memset(fgd_ret_msg, 0, size);
bmd_ctrl_cmd_from_user(data, fgd_ret_msg);
nl_send_to_user(pid, seq, fgd_ret_msg);
/*bm_print(BM_LOG_CRTI,"[Netlink] send to user space process done\n");*/
vfree(fgd_ret_msg);
}
int wakeup_fg_algo(int flow_state)
{
update_fg_dbg_tool_value();
if (gDisableFG) {
bm_notice("FG daemon is disabled\n");
return -1;
}
if (g_fgd_pid != 0) {
struct fgd_nl_msg_t *fgd_msg;
int size = FGD_NL_MSG_T_HDR_LEN + sizeof(flow_state);
fgd_msg = vmalloc(size);
if (!fgd_msg)
return -1;
bm_debug("[battery_meter_driver] malloc size=%d\n", size);
memset(fgd_msg, 0, size);
fgd_msg->fgd_cmd = FG_DAEMON_CMD_NOTIFY_DAEMON;
memcpy(fgd_msg->fgd_data, &flow_state, sizeof(flow_state));
fgd_msg->fgd_data_len += sizeof(flow_state);
nl_send_to_user(g_fgd_pid, 0, fgd_msg);
vfree(fgd_msg);
return 0;
} else {
return -1;
}
}
static int __init battery_meter_init(void)
{
int ret;
/* add by willcai for the userspace to kernelspace */
struct netlink_kernel_cfg cfg = {
.input = nl_data_handler,
};
/* end */
#ifdef CONFIG_OF
/* */
#else
ret = platform_device_register(&battery_meter_device);
if (ret) {
bm_err("[battery_meter_driver] Unable to device register(%d)\n",
ret);
return ret;
}
#endif
ret = platform_driver_register(&battery_meter_driver);
if (ret) {
bm_err("[battery_meter_driver] Unable to register driver (%d)\n",
ret);
return ret;
}
#ifdef CONFIG_OF
ret = platform_driver_register(&battery_meter_dts_driver);
#endif
/* add by willcai for the userspace to kernelspace */
/* daemo_nl_sk = netlink_kernel_create */
/* (&init_net, NETLINK_TEST, 0, nl_data_handler, NULL, THIS_MODULE); */
daemo_nl_sk = netlink_kernel_create(&init_net, NETLINK_FGD, &cfg);
bm_debug("netlink_kernel_create protol= %d\n", NETLINK_FGD);
if (daemo_nl_sk == NULL) {
bm_err("netlink_kernel_create error\n");
return -1;
}
bm_debug("netlink_kernel_create ok\n");
bm_debug("[battery_meter_driver] Initialization : DONE\n");
return 0;
}
#ifdef BATTERY_MODULE_INIT
device_initcall(battery_meter_init);
#else
static void __exit battery_meter_exit(void)
{
}
module_init(battery_meter_init);
/* module_exit(battery_meter_exit); */
#endif
MODULE_AUTHOR("James Lo");
MODULE_DESCRIPTION("Battery Meter Device Driver");
MODULE_LICENSE("GPL");