c05564c4d8
Android 13
5172 lines
121 KiB
C
Executable file
5172 lines
121 KiB
C
Executable file
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2021 MediaTek Inc.
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Filename:
|
|
* ---------
|
|
* mtk_battery.c
|
|
*
|
|
* Project:
|
|
* --------
|
|
* Android_Software
|
|
*
|
|
* Description:
|
|
* ------------
|
|
* This Module defines functions of the Anroid Battery service for
|
|
* updating the battery status
|
|
*
|
|
* Author:
|
|
* -------
|
|
* Weiching Lin
|
|
*
|
|
****************************************************************************/
|
|
#include <linux/init.h> /* For init/exit macros */
|
|
#include <linux/module.h> /* For MODULE_ marcros */
|
|
#include <linux/wait.h> /* For wait queue*/
|
|
#include <linux/sched.h> /* For wait queue*/
|
|
#include <linux/kthread.h> /* For Kthread_run */
|
|
#include <linux/platform_device.h> /* platform device */
|
|
#include <linux/time.h>
|
|
|
|
#include <linux/netlink.h> /* netlink */
|
|
#include <linux/kernel.h>
|
|
#include <linux/socket.h> /* netlink */
|
|
#include <linux/skbuff.h> /* netlink */
|
|
#include <net/sock.h> /* netlink */
|
|
#include <linux/cdev.h> /* cdev */
|
|
|
|
#include <linux/err.h> /* IS_ERR, PTR_ERR */
|
|
#include <linux/reboot.h> /*kernel_power_off*/
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/of_fdt.h> /*of_dt API*/
|
|
#include <linux/of_platform.h> /*of_find_node_by_name*/
|
|
#include <linux/irq.h>
|
|
#include <linux/irqdesc.h> /*irq_to_desc*/
|
|
#include <linux/mfd/mt6358/core.h> /*mt6358_irq_get_virq*/
|
|
#include <linux/vmalloc.h>
|
|
|
|
|
|
#include <linux/math64.h> /*div_s64*/
|
|
|
|
#include <mt-plat/aee.h>
|
|
#include <mt-plat/v1/charger_type.h>
|
|
#include <mt-plat/v1/mtk_charger.h>
|
|
#include <mt-plat/v1/mtk_battery.h>
|
|
#include <mt-plat/mtk_boot.h>
|
|
|
|
#include <mtk_gauge_class.h>
|
|
#include "mtk_battery_internal.h"
|
|
#include <mach/mtk_battery_property.h>
|
|
#include <mtk_gauge_time_service.h>
|
|
#include <mt-plat/upmu_common.h>
|
|
#include <pmic_lbat_service.h>
|
|
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
#include <../drivers/battery/common/sec_charging_common.h>
|
|
#define SEC_BATTERY_FAKE_CAPACITY 0
|
|
#endif
|
|
|
|
/* ============================================================ */
|
|
/* define */
|
|
/* ============================================================ */
|
|
#define NETLINK_FGD 26
|
|
|
|
|
|
/************ adc_cali *******************/
|
|
#define ADC_CALI_DEVNAME "MT_pmic_adc_cali"
|
|
#define TEST_ADC_CALI_PRINT _IO('k', 0)
|
|
#define SET_ADC_CALI_Slop _IOW('k', 1, int)
|
|
#define SET_ADC_CALI_Offset _IOW('k', 2, int)
|
|
#define SET_ADC_CALI_Cal _IOW('k', 3, int)
|
|
#define ADC_CHANNEL_READ _IOW('k', 4, int)
|
|
#define BAT_STATUS_READ _IOW('k', 5, int)
|
|
#define Set_Charger_Current _IOW('k', 6, int)
|
|
/* add for meta tool----------------------------------------- */
|
|
#define Get_META_BAT_VOL _IOW('k', 10, int)
|
|
#define Get_META_BAT_SOC _IOW('k', 11, int)
|
|
#define Get_META_BAT_CAR_TUNE_VALUE _IOW('k', 12, int)
|
|
#define Set_META_BAT_CAR_TUNE_VALUE _IOW('k', 13, int)
|
|
#define Set_BAT_DISABLE_NAFG _IOW('k', 14, int)
|
|
#define Set_CARTUNE_TO_KERNEL _IOW('k', 15, int)
|
|
/* add for meta tool----------------------------------------- */
|
|
|
|
static struct class *adc_cali_class;
|
|
static int adc_cali_major;
|
|
static dev_t adc_cali_devno;
|
|
static struct cdev *adc_cali_cdev;
|
|
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
static void disable_fg(void);
|
|
#endif
|
|
|
|
static int adc_cali_slop[14] = {
|
|
1000, 1000, 1000, 1000, 1000, 1000,
|
|
1000, 1000, 1000, 1000, 1000, 1000,
|
|
1000, 1000
|
|
};
|
|
static int adc_cali_offset[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
static int adc_cali_cal[1] = { 0 };
|
|
static int battery_in_data[1] = { 0 };
|
|
static int battery_out_data[1] = { 0 };
|
|
static bool g_ADC_Cali;
|
|
|
|
static enum power_supply_property battery_props[] = {
|
|
POWER_SUPPLY_PROP_STATUS,
|
|
POWER_SUPPLY_PROP_HEALTH,
|
|
POWER_SUPPLY_PROP_PRESENT,
|
|
POWER_SUPPLY_PROP_TECHNOLOGY,
|
|
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
|
POWER_SUPPLY_PROP_CAPACITY,
|
|
POWER_SUPPLY_PROP_CURRENT_NOW,
|
|
POWER_SUPPLY_PROP_CURRENT_AVG,
|
|
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
|
POWER_SUPPLY_PROP_CHARGE_FULL,
|
|
POWER_SUPPLY_PROP_CHARGE_COUNTER,
|
|
POWER_SUPPLY_PROP_TEMP,
|
|
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
|
POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
|
|
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
|
|
};
|
|
|
|
/* boot mode */
|
|
struct tag_bootmode {
|
|
u32 size;
|
|
u32 tag;
|
|
u32 bootmode;
|
|
u32 boottype;
|
|
};
|
|
|
|
/* weak function */
|
|
int __attribute__ ((weak))
|
|
do_ptim_gauge(
|
|
bool isSuspend, unsigned int *bat, signed int *cur, bool *is_charging)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int __attribute__ ((weak))
|
|
get_rac(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int __attribute__ ((weak))
|
|
get_imix(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void __attribute__ ((weak))
|
|
battery_dump_nag(void)
|
|
{
|
|
}
|
|
|
|
enum charger_type __attribute__ ((weak))
|
|
mt_get_charger_type(void)
|
|
{
|
|
return CHARGER_UNKNOWN;
|
|
}
|
|
|
|
int __attribute__ ((weak))
|
|
charger_manager_get_zcv(
|
|
struct charger_consumer *consumer, int idx, u32 *uV)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
struct charger_consumer __attribute__ ((weak))
|
|
*charger_manager_get_by_name(struct device *dev,
|
|
const char *supply_name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int __attribute__ ((weak))
|
|
register_charger_manager_notifier(struct charger_consumer *consumer,
|
|
struct notifier_block *nb)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void __attribute__ ((weak)) enable_bat_temp_det(bool en)
|
|
{
|
|
pr_notice("[%s] not support!\n", __func__);
|
|
}
|
|
|
|
unsigned int __attribute__ ((weak)) mt6358_irq_get_virq(struct device *dev,
|
|
unsigned int hwirq)
|
|
{
|
|
pr_notice_once("%s: API not ready!\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/* weak function end */
|
|
|
|
|
|
int gauge_enable_interrupt(int intr_number, int en)
|
|
{
|
|
struct irq_desc *desc;
|
|
unsigned int depth = 0;
|
|
unsigned int irq = 0;
|
|
|
|
if (intr_number == INT_ENUM_MAX) {
|
|
bm_debug("[%s] intr_number = INT_ENUM_MAX, no interrupt, do nothing %d\n",
|
|
__func__, INT_ENUM_MAX);
|
|
return 0;
|
|
}
|
|
|
|
if (gm.pdev_node == NULL)
|
|
gm.pdev_node = of_find_node_by_name(NULL, "mt-pmic");
|
|
|
|
if (gm.pdevice == NULL)
|
|
gm.pdevice = of_find_device_by_node(gm.pdev_node);
|
|
|
|
if (gm.pmic_dev == NULL && gm.pdevice != NULL)
|
|
gm.pmic_dev = &gm.pdevice->dev;
|
|
|
|
if (gm.pmic_dev == NULL)
|
|
return -EINVAL;
|
|
|
|
irq = mt6358_irq_get_virq(gm.pmic_dev->parent, intr_number);
|
|
|
|
desc = irq_to_desc(irq);
|
|
|
|
if (!desc)
|
|
return -EINVAL;
|
|
|
|
|
|
mutex_lock(&gm.pmic_intr_mutex);
|
|
depth = desc->depth;
|
|
|
|
if (en == 1) {
|
|
if (desc->depth == 1) {
|
|
pmic_enable_interrupt(intr_number, en, "GM30");
|
|
bm_debug("[%s]intr_number:%d %d en = %d, depth b[%d],a[%d]\n",
|
|
__func__, intr_number, irq, en,
|
|
depth, desc->depth);
|
|
} else {
|
|
/* do nothing */
|
|
bm_debug("[%s]do nothing, intr_number:%d %d en = %d, depth:%d %d\n",
|
|
__func__, intr_number, irq, en,
|
|
depth, desc->depth);
|
|
}
|
|
} else if (en == 0) {
|
|
if (desc->depth == 0) {
|
|
pmic_enable_interrupt(intr_number, en, "GM30");
|
|
bm_debug("[%s]intr_number:%d %d en = %d, depth b[%d],a[%d]\n",
|
|
__func__, intr_number, irq, en,
|
|
depth, desc->depth);
|
|
} else {
|
|
/* do nothing */
|
|
bm_debug("[%s]do nothing, intr_number:%d %d en = %d, depth:%d %d\n",
|
|
__func__, intr_number, irq, en,
|
|
depth, desc->depth);
|
|
}
|
|
}
|
|
mutex_unlock(&gm.pmic_intr_mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool is_battery_init_done(void)
|
|
{
|
|
return gm.is_probe_done;
|
|
}
|
|
|
|
bool is_recovery_mode(void)
|
|
{
|
|
int boot_mode = battery_get_boot_mode();
|
|
|
|
if (is_fg_disabled())
|
|
return false;
|
|
|
|
bm_debug("mtk_battery boot mode =%d\n", boot_mode);
|
|
if (boot_mode == RECOVERY_BOOT) {
|
|
gm.log_level = BMLOG_DEBUG_LEVEL;
|
|
fg_cust_data.daemon_log_level = BMLOG_DEBUG_LEVEL;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int battery_get_boot_mode(void)
|
|
{
|
|
struct device *dev = NULL;
|
|
struct device_node *boot_node = NULL;
|
|
struct tag_bootmode *tag = NULL;
|
|
int boot_mode = 11;//UNKNOWN_BOOT
|
|
|
|
dev = gm.gdev->dev.parent;
|
|
if (dev != NULL) {
|
|
boot_node = of_parse_phandle(dev->of_node, "bootmode", 0);
|
|
if (!boot_node) {
|
|
bm_err("%s: failed to get boot mode phandle\n", __func__);
|
|
} else {
|
|
tag = (struct tag_bootmode *)of_get_property(boot_node,
|
|
"atag,boot", NULL);
|
|
if (!tag)
|
|
bm_err("%s: failed to get atag,boot\n", __func__);
|
|
else {
|
|
boot_mode = tag->bootmode;
|
|
gm.boot_mode = tag->bootmode;
|
|
}
|
|
}
|
|
}
|
|
bm_debug("%s: boot mode=%d\n", __func__, boot_mode);
|
|
return boot_mode;
|
|
}
|
|
|
|
bool is_fg_disabled(void)
|
|
{
|
|
return gm.disableGM30;
|
|
}
|
|
|
|
|
|
bool set_charge_power_sel(enum CHARGE_SEL select)
|
|
{
|
|
/* select gm.charge_power_sel to CHARGE_NORMAL ,CHARGE_R1,CHARGE_R2 */
|
|
/* example: gm.charge_power_sel = CHARGE_NORMAL */
|
|
|
|
gm.charge_power_sel = select;
|
|
|
|
wakeup_fg_algo_cmd(FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_FORCE_BAT_TEMP, select);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dump_pseudo100(enum CHARGE_SEL select)
|
|
{
|
|
int i = 0;
|
|
|
|
bm_err("%s:select=%d\n", __func__, select);
|
|
|
|
if (select > MAX_CHARGE_RDC || select < 0)
|
|
return 0;
|
|
|
|
for (i = 0; i < MAX_TABLE; i++) {
|
|
bm_err("%6d\n",
|
|
fg_table_cust_data.fg_profile[i].r_pseudo100.pseudo[select]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int register_battery_notifier(struct notifier_block *nb)
|
|
{
|
|
int ret = 0;
|
|
|
|
mutex_lock(&gm.notify_mutex);
|
|
ret = srcu_notifier_chain_register(&gm.gm_notify, nb);
|
|
mutex_unlock(&gm.notify_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int unregister_battery_notifier(struct notifier_block *nb)
|
|
{
|
|
int ret = 0;
|
|
|
|
mutex_lock(&gm.notify_mutex);
|
|
ret = srcu_notifier_chain_unregister(&gm.gm_notify, nb);
|
|
mutex_unlock(&gm.notify_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int battery_notifier(int event)
|
|
{
|
|
return srcu_notifier_call_chain(&gm.gm_notify, event, NULL);
|
|
}
|
|
|
|
/* ============================================================ */
|
|
/* functions for fg hal*/
|
|
/* ============================================================ */
|
|
void set_hw_ocv_unreliable(bool _flag_unreliable)
|
|
{
|
|
gm.hw_status.flag_hw_ocv_unreliable
|
|
= _flag_unreliable;
|
|
}
|
|
|
|
|
|
/* ============================================================ */
|
|
/* functions */
|
|
/* ============================================================ */
|
|
|
|
signed int battery_meter_get_tempR(signed int dwVolt)
|
|
{
|
|
|
|
int TRes;
|
|
|
|
TRes = 0;
|
|
|
|
if (is_fg_disabled())
|
|
return 0;
|
|
|
|
TRes = (gm.rbat.rbat_pull_up_r * dwVolt) /
|
|
(gm.rbat.rbat_pull_up_volt - dwVolt);
|
|
return TRes;
|
|
}
|
|
|
|
signed int battery_meter_get_tempV(void)
|
|
{
|
|
|
|
int val = 0;
|
|
|
|
if (is_fg_disabled())
|
|
return 0;
|
|
|
|
val = pmic_get_v_bat_temp();
|
|
return val;
|
|
}
|
|
|
|
signed int battery_meter_get_VSense(void)
|
|
{
|
|
if (is_fg_disabled())
|
|
return 0;
|
|
else
|
|
return pmic_get_ibus();
|
|
}
|
|
|
|
int check_cap_level(int uisoc)
|
|
{
|
|
if (uisoc >= 100)
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
|
else if (uisoc >= 80 && uisoc < 100)
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
|
|
else if (uisoc >= 20 && uisoc < 80)
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
|
|
else if (uisoc > 0 && uisoc < 20)
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
|
else if (uisoc == 0)
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
|
|
else
|
|
return POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
|
|
}
|
|
|
|
void battery_update_psd(struct battery_data *bat_data)
|
|
{
|
|
bat_data->BAT_batt_vol = battery_get_bat_voltage();
|
|
bat_data->BAT_batt_temp = battery_get_bat_temperature();
|
|
}
|
|
|
|
#if defined(CONFIG_USB_FACTORY_MODE)
|
|
#if defined(CONFIG_SEC_FACTORY)
|
|
extern int mt6360_read_vsys_uvolt(void);
|
|
static int vsys_to_vsoc_for_factory_mode(void)
|
|
{
|
|
int vsys_volt = 0;
|
|
int index_value, vsoc_value = 0;
|
|
|
|
vsys_volt = mt6360_read_vsys_uvolt() / 1000;
|
|
|
|
for (index_value = 0; index_value < 100; index_value++) {
|
|
if ((fg_table_cust_data.fg_profile[1].fg_profile[index_value].voltage / 10) < vsys_volt) {
|
|
vsoc_value = 100 - index_value;
|
|
break;
|
|
}
|
|
}
|
|
pr_info("%s vsys_volt: %d, VSOC[%d] : %d\n", __func__,
|
|
vsys_volt, vsoc_value,
|
|
fg_table_cust_data.fg_profile[1].fg_profile[index_value].voltage / 10);
|
|
|
|
return vsoc_value;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
static int battery_get_property(struct power_supply *psy,
|
|
enum power_supply_property psp,
|
|
union power_supply_propval *val)
|
|
{
|
|
int ret = 0;
|
|
int fgcurrent = 0;
|
|
bool b_ischarging = 0;
|
|
#if defined(CONFIG_USB_FACTORY_MODE)
|
|
union power_supply_propval value = {0, };
|
|
enum power_supply_ext_property ext_psp = (enum power_supply_ext_property) psp;
|
|
#endif
|
|
|
|
struct battery_data *data =
|
|
container_of(psy->desc, struct battery_data, psd);
|
|
|
|
#if defined(CONFIG_BATTERY_GKI)
|
|
switch ((int)psp) {
|
|
#else
|
|
switch (psp) {
|
|
#endif
|
|
case POWER_SUPPLY_PROP_STATUS:
|
|
val->intval = data->BAT_STATUS;
|
|
break;
|
|
case POWER_SUPPLY_PROP_HEALTH:
|
|
val->intval = data->BAT_HEALTH;/* do not change before*/
|
|
break;
|
|
case POWER_SUPPLY_PROP_PRESENT:
|
|
val->intval = data->BAT_PRESENT;/* do not change before*/
|
|
break;
|
|
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
|
val->intval = data->BAT_TECHNOLOGY;
|
|
break;
|
|
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
|
val->intval = gm.bat_cycle;
|
|
break;
|
|
case POWER_SUPPLY_PROP_CAPACITY:
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
if (val->intval == SEC_FUELGAUGE_CAPACITY_TYPE_RAW) {
|
|
val->intval = gm.precise_soc * 10;
|
|
} else if (val->intval == SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE) {
|
|
val->intval = battery_get_precise_uisoc();
|
|
pr_info("%s : ui SOC(%d%%)\n", __func__, val->intval);
|
|
} else {
|
|
#endif
|
|
/* 1 = META_BOOT, 4 = FACTORY_BOOT 5=ADVMETA_BOOT */
|
|
/* 6= ATE_factory_boot */
|
|
if (gm.boot_mode == 1 || gm.boot_mode == 4
|
|
|| gm.boot_mode == 5 || gm.boot_mode == 6) {
|
|
val->intval = 75;
|
|
break;
|
|
}
|
|
|
|
if (gm.fixed_uisoc != 0xffff)
|
|
val->intval = gm.fixed_uisoc;
|
|
else
|
|
val->intval = data->BAT_CAPACITY;
|
|
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
if (val->intval < 0) {
|
|
val->intval = battery_get_soc();
|
|
pr_info("%s : real / fake capacity(%d%%/%d%%)\n",
|
|
__func__, val->intval,
|
|
SEC_BATTERY_FAKE_CAPACITY);
|
|
val->intval = SEC_BATTERY_FAKE_CAPACITY;
|
|
gm.is_fake_soc = 1;
|
|
}
|
|
#endif
|
|
#if defined(CONFIG_SEC_FACTORY)
|
|
if (data->f_mode == OB_MODE)
|
|
val->intval = vsys_to_vsoc_for_factory_mode();
|
|
#endif
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
}
|
|
#endif
|
|
break;
|
|
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
|
b_ischarging = gauge_get_current(&fgcurrent);
|
|
if (b_ischarging == false)
|
|
fgcurrent = 0 - fgcurrent;
|
|
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
if (val->intval == SEC_BATTERY_CURRENT_UA)
|
|
val->intval = fgcurrent * 100;
|
|
else
|
|
val->intval = fgcurrent / 10;
|
|
#else
|
|
val->intval = fgcurrent * 100;
|
|
#endif
|
|
break;
|
|
case POWER_SUPPLY_PROP_CURRENT_AVG:
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
if (val->intval == SEC_BATTERY_CURRENT_UA)
|
|
val->intval = battery_get_bat_avg_current() * 100;
|
|
else
|
|
val->intval = battery_get_bat_avg_current() / 10;
|
|
#else
|
|
val->intval = battery_get_bat_avg_current() * 100;
|
|
#endif
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
|
val->intval =
|
|
fg_table_cust_data.fg_profile[gm.battery_id].q_max
|
|
* 1000;
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
|
|
val->intval = gm.ui_soc *
|
|
fg_table_cust_data.fg_profile[gm.battery_id].q_max
|
|
* 1000 / 100;
|
|
break;
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
|
|
#endif
|
|
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
|
#if defined(CONFIG_USB_FACTORY_MODE)
|
|
if (data->f_mode == OB_MODE) {
|
|
psy_do_property("mtk-charger", get,
|
|
POWER_SUPPLY_EXT_PROP_BATT_VSYS, value);
|
|
val->intval = value.intval;
|
|
} else
|
|
val->intval = battery_get_bat_voltage();
|
|
#else
|
|
val->intval = data->BAT_batt_vol * 1000;
|
|
#endif
|
|
break;
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
|
#endif
|
|
case POWER_SUPPLY_PROP_TEMP:
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
force_get_tbat_adc();
|
|
val->intval = gm.tbat_adc;
|
|
pr_info("%s : val->intval (%d)\n", __func__, val->intval);
|
|
#else
|
|
val->intval = gm.tbat_precise;
|
|
#endif
|
|
break;
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
case POWER_SUPPLY_PROP_ENERGY_NOW:
|
|
switch (val->intval) {
|
|
case SEC_BATTERY_CAPACITY_FULL:
|
|
val->intval = fg_table_cust_data.fg_profile[gm.battery_id].q_max;
|
|
pr_info("[%s] fg_table_cust_data.fg_profile[gm.battery_id].q_max %d\n",
|
|
__func__, fg_table_cust_data.fg_profile[gm.battery_id].q_max);
|
|
break;
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_PROP_ENERGY_FULL:
|
|
val->intval = gm.aging_factor / 100;
|
|
break;
|
|
#endif
|
|
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
|
val->intval = check_cap_level(data->BAT_CAPACITY);
|
|
break;
|
|
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
|
|
/* full or unknown must return 0 */
|
|
ret = check_cap_level(data->BAT_CAPACITY);
|
|
if ((ret == POWER_SUPPLY_CAPACITY_LEVEL_FULL) ||
|
|
(ret == POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN))
|
|
val->intval = 0;
|
|
else {
|
|
int q_max_now = fg_table_cust_data.fg_profile[
|
|
gm.battery_id].q_max;
|
|
int remain_ui = 100 - data->BAT_CAPACITY;
|
|
int remain_mah = remain_ui * q_max_now / 10;
|
|
int time_to_full = 0;
|
|
|
|
gauge_get_current(&fgcurrent);
|
|
|
|
if (fgcurrent != 0)
|
|
time_to_full = remain_mah * 3600 / fgcurrent;
|
|
|
|
bm_debug("time_to_full:%d, remain:ui:%d mah:%d, fgcurrent:%d, qmax:%d\n",
|
|
time_to_full, remain_ui, remain_mah,
|
|
fgcurrent, q_max_now);
|
|
|
|
val->intval = abs(time_to_full);
|
|
}
|
|
ret = 0;
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
|
if (check_cap_level(data->BAT_CAPACITY) ==
|
|
POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN)
|
|
val->intval = 0;
|
|
else {
|
|
int q_max_mah = 0;
|
|
int q_max_uah = 0;
|
|
|
|
q_max_mah =
|
|
fg_table_cust_data.fg_profile[
|
|
gm.battery_id].q_max / 10;
|
|
|
|
q_max_uah = q_max_mah * 1000;
|
|
if (q_max_uah <= 100000) {
|
|
bm_debug("%s q_max_mah:%d q_max_uah:%d\n",
|
|
__func__, q_max_mah, q_max_uah);
|
|
q_max_uah = 100001;
|
|
}
|
|
val->intval = q_max_uah;
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
|
val->intval = gm.dynamic_cv;
|
|
break;
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
|
|
break;
|
|
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
|
break;
|
|
case POWER_SUPPLY_PROP_MAX ... POWER_SUPPLY_EXT_PROP_MAX:
|
|
switch (ext_psp) {
|
|
case POWER_SUPPLY_EXT_PROP_PMIC_BAT_VOLTAGE:
|
|
{
|
|
int j, k, ocv, ocv_data[10];
|
|
|
|
for (j = 0; j < 10; j++)
|
|
ocv_data[j] = pmic_get_battery_voltage();
|
|
for (j = 1; j < 10; j++) {
|
|
ocv = ocv_data[j];
|
|
k = j;
|
|
while (k > 0 && ocv_data[k-1] > ocv) {
|
|
ocv_data[k] = ocv_data[k-1];
|
|
k--;
|
|
}
|
|
ocv_data[k] = ocv;
|
|
}
|
|
for (j = 0; j < 10; j++)
|
|
pr_info("%s: [%d] %d\n", __func__, j, ocv_data[j]);
|
|
|
|
ocv = 0;
|
|
for (j = 2; j < 8; j++)
|
|
ocv += ocv_data[j];
|
|
|
|
val->intval = ocv / 6;
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_EXT_PROP_MONITOR_WORK:
|
|
break;
|
|
case POWER_SUPPLY_EXT_PROP_BATTERY_ID:
|
|
val->intval = gm.battery_id;
|
|
break;
|
|
case POWER_SUPPLY_EXT_PROP_BATT_DUMP:
|
|
{
|
|
memset(data->d_buf, 0x0, sizeof(data->d_buf));
|
|
|
|
/* capacity_max not supported, set to 0 */
|
|
snprintf(data->d_buf + strlen(data->d_buf), sizeof(data->d_buf),
|
|
"%d,%d,%d",
|
|
pmic_get_battery_voltage(),
|
|
gm.precise_soc * 10,
|
|
0);
|
|
val->strval = data->d_buf;
|
|
}
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if defined(CONFIG_USB_FACTORY_MODE)
|
|
extern void set_g_low_battery_stop(int val);
|
|
#endif
|
|
|
|
static int battery_set_property(struct power_supply *psy,
|
|
enum power_supply_property psp,
|
|
const union power_supply_propval *val)
|
|
{
|
|
int ret = 0;
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
enum power_supply_ext_property ext_psp = (enum power_supply_ext_property) psp;
|
|
struct battery_data *data =
|
|
container_of(psy->desc, struct battery_data, psd);
|
|
#endif
|
|
|
|
#if defined(CONFIG_BATTERY_GKI)
|
|
switch ((int)psp) {
|
|
#else
|
|
switch (psp) {
|
|
#endif
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
case POWER_SUPPLY_PROP_STATUS:
|
|
if (val->intval == POWER_SUPPLY_STATUS_FULL) {
|
|
notify_fg_chr_full();
|
|
gm.is_full = 0;
|
|
pr_info("%s: Battery Full!\n", __func__);
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
|
/* No need to run if SOC is already 100% */
|
|
if (val->intval == 100)
|
|
break;
|
|
if (gm.is_full != 1) {
|
|
notify_fg_chr_full();
|
|
gm.is_full = 1;
|
|
pr_info("%s: Force Battery Full!\n", __func__);
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
|
|
if (val->intval == SEC_BAT_CHG_MODE_CHARGING) {
|
|
pr_info("%s: Battery Charging!\n", __func__);
|
|
fg_sw_bat_cycle_accu();
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
|
|
battery_update(&battery_main);
|
|
} else {
|
|
pr_info("%s: Battery Discharging!\n", __func__);
|
|
gm.is_full = 0;
|
|
fg_sw_bat_cycle_accu();
|
|
battery_main.BAT_STATUS =
|
|
POWER_SUPPLY_STATUS_DISCHARGING;
|
|
battery_update(&battery_main);
|
|
}
|
|
break;
|
|
case POWER_SUPPLY_PROP_TEMP:
|
|
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
|
case POWER_SUPPLY_PROP_ONLINE:
|
|
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
|
break;
|
|
case POWER_SUPPLY_PROP_MAX ... POWER_SUPPLY_EXT_PROP_MAX:
|
|
switch (ext_psp) {
|
|
#if IS_ENABLED(CONFIG_BATTERY_GKI)
|
|
case POWER_SUPPLY_EXT_PROP_CHARGING_ENABLED:
|
|
if (val->intval == SEC_BAT_CHG_MODE_CHARGING) {
|
|
pr_info("%s: Battery Charging!\n", __func__);
|
|
fg_sw_bat_cycle_accu();
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
|
|
battery_update(&battery_main);
|
|
} else {
|
|
pr_info("%s: Battery Discharging!\n", __func__);
|
|
gm.is_full = 0;
|
|
fg_sw_bat_cycle_accu();
|
|
battery_main.BAT_STATUS =
|
|
POWER_SUPPLY_STATUS_DISCHARGING;
|
|
battery_update(&battery_main);
|
|
}
|
|
break;
|
|
#endif
|
|
case POWER_SUPPLY_EXT_PROP_BATT_F_MODE:
|
|
data->f_mode = val->intval;
|
|
pr_info("%s: mtk-fg-battery: FG f_mode: %s\n", __func__,
|
|
BOOT_MODE_STRING[data->f_mode]);
|
|
#if defined(CONFIG_SEC_FACTORY)
|
|
if (data->f_mode == OB_MODE) {
|
|
set_g_low_battery_stop(1);
|
|
disable_fg();
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
#endif
|
|
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
|
if (val->intval > 0) {
|
|
gm.dynamic_cv = val->intval / 100;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_GET_DYNAMIC_CV, gm.dynamic_cv);
|
|
bm_err("[%s], dynamic_cv: %d\n", __func__, gm.dynamic_cv);
|
|
}
|
|
break;
|
|
default:
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
bm_debug("%s psp:%d ret:%d val:%d",
|
|
__func__, psp, ret, val->intval);
|
|
|
|
return ret;
|
|
}
|
|
/* battery_data initialization */
|
|
struct battery_data battery_main = {
|
|
.psd = {
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
.name = "mtk-fg-battery",
|
|
.type = POWER_SUPPLY_TYPE_UNKNOWN,
|
|
#else
|
|
.name = "battery",
|
|
.type = POWER_SUPPLY_TYPE_BATTERY,
|
|
#endif
|
|
.properties = battery_props,
|
|
.num_properties = ARRAY_SIZE(battery_props),
|
|
.get_property = battery_get_property,
|
|
.set_property = battery_set_property,
|
|
},
|
|
|
|
.BAT_STATUS = POWER_SUPPLY_STATUS_DISCHARGING,
|
|
.BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD,
|
|
.BAT_PRESENT = 1,
|
|
.BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION,
|
|
.BAT_CAPACITY = -1,
|
|
.BAT_batt_vol = 0,
|
|
.BAT_batt_temp = 0,
|
|
};
|
|
|
|
void evb_battery_init(void)
|
|
{
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_FULL;
|
|
battery_main.BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD;
|
|
battery_main.BAT_PRESENT = 1;
|
|
battery_main.BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION;
|
|
battery_main.BAT_CAPACITY = 100;
|
|
battery_main.BAT_batt_vol = 4200;
|
|
battery_main.BAT_batt_temp = 22;
|
|
}
|
|
|
|
static void disable_fg(void)
|
|
{
|
|
|
|
int fgv;
|
|
|
|
fgv = gauge_get_hw_version();
|
|
|
|
if (fgv >= GAUGE_HW_V1000
|
|
&& fgv < GAUGE_HW_V2000) {
|
|
en_intr_VBATON_UNDET(0);
|
|
}
|
|
|
|
gauge_enable_interrupt(FG_BAT1_INT_L_NO, 0);
|
|
gauge_enable_interrupt(FG_BAT1_INT_H_NO, 0);
|
|
|
|
gauge_enable_interrupt(FG_BAT0_INT_L_NO, 0);
|
|
gauge_enable_interrupt(FG_BAT0_INT_H_NO, 0);
|
|
|
|
gauge_enable_interrupt(FG_N_CHARGE_L_NO, 0);
|
|
|
|
gauge_enable_interrupt(FG_IAVG_H_NO, 0);
|
|
gauge_enable_interrupt(FG_IAVG_L_NO, 0);
|
|
|
|
gauge_enable_interrupt(FG_ZCV_NO, 0);
|
|
|
|
gauge_enable_interrupt(FG_BAT_PLUGOUT_NO, 0);
|
|
gauge_enable_interrupt(FG_RG_INT_EN_NAG_C_DLTV, 0);
|
|
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_H, 0);
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_L, 0);
|
|
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT2_H, 0);
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT2_L, 0);
|
|
gm.disableGM30 = 1;
|
|
gm.ui_soc = 50;
|
|
battery_main.BAT_CAPACITY = 50;
|
|
}
|
|
|
|
bool fg_interrupt_check(void)
|
|
{
|
|
if (is_fg_disabled()) {
|
|
disable_fg();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void battery_update(struct battery_data *bat_data)
|
|
{
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
union power_supply_propval value;
|
|
int ui_soc_value = 0;
|
|
struct power_supply *psy;
|
|
int ret = 0;
|
|
#endif
|
|
#if !defined(CONFIG_BATTERY_SAMSUNG)
|
|
struct power_supply *bat_psy = bat_data->psy;
|
|
#endif
|
|
|
|
battery_update_psd(&battery_main);
|
|
bat_data->BAT_TECHNOLOGY = POWER_SUPPLY_TECHNOLOGY_LION;
|
|
bat_data->BAT_HEALTH = POWER_SUPPLY_HEALTH_GOOD;
|
|
bat_data->BAT_PRESENT = 1;
|
|
|
|
#if defined(CONFIG_MTK_DISABLE_GAUGE)
|
|
return;
|
|
#endif
|
|
|
|
if (is_fg_disabled())
|
|
bat_data->BAT_CAPACITY = 50;
|
|
|
|
#ifdef CONFIG_BATTERY_SAMSUNG
|
|
psy = power_supply_get_by_name("battery");
|
|
if (!psy) {
|
|
pr_err("%s: Fail to get psy (battery)\n", __func__);
|
|
} else {
|
|
if (gm.is_fake_soc) {
|
|
ui_soc_value = battery_get_uisoc();
|
|
if (ui_soc_value >= 0) {
|
|
pr_info("%s : clear fake SOC\n", __func__);
|
|
value.intval = ui_soc_value;
|
|
ret = power_supply_set_property(psy,
|
|
POWER_SUPPLY_PROP_CAPACITY, &value);
|
|
if (ret < 0)
|
|
pr_err("%s: psy capacity fail(%d)\n",
|
|
__func__, ret);
|
|
|
|
#if IS_ENABLED(CONFIG_DIRECT_CHARGING)
|
|
value.intval = 1;
|
|
ret = power_supply_set_property(psy, (enum power_supply_property)
|
|
POWER_SUPPLY_EXT_PROP_MTK_FG_INIT, &value);
|
|
if (ret < 0)
|
|
pr_err("%s: psy update fg state fail(%d)\n",
|
|
__func__, ret);
|
|
#endif
|
|
|
|
gm.is_fake_soc = 0;
|
|
value.intval = 0;
|
|
ret = power_supply_set_property(psy,
|
|
POWER_SUPPLY_PROP_CHARGE_TYPE, &value);
|
|
if (ret < 0)
|
|
pr_err("%s: psy online fail(%d)\n",
|
|
__func__, ret);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !defined(CONFIG_BATTERY_SAMSUNG)
|
|
power_supply_changed(bat_psy);
|
|
#endif
|
|
}
|
|
|
|
bool is_kernel_power_off_charging(void)
|
|
{
|
|
int boot_mode = battery_get_boot_mode();
|
|
|
|
if (boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT
|
|
|| boot_mode == LOW_POWER_OFF_CHARGING_BOOT) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int bat_get_debug_level(void)
|
|
{
|
|
return gm.log_level;
|
|
}
|
|
|
|
/* ============================================================ */
|
|
/* function prototype */
|
|
/* ============================================================ */
|
|
static void nl_send_to_user(u32 pid, int seq, struct fgd_nl_msg_t *reply_msg);
|
|
|
|
struct fuel_gauge_custom_data fg_cust_data;
|
|
struct fuel_gauge_table_custom_data fg_table_cust_data;
|
|
|
|
|
|
/* ============================================================ */
|
|
/* extern function */
|
|
/* ============================================================ */
|
|
static void proc_dump_log(struct seq_file *m)
|
|
{
|
|
seq_printf(m, "subcmd:%d para1:%d\n",
|
|
gm.proc_subcmd, gm.proc_subcmd_para1);
|
|
seq_printf(m, "%s\n", gm.proc_log);
|
|
}
|
|
|
|
static void proc_dump_dtsi(struct seq_file *m)
|
|
{
|
|
int i;
|
|
|
|
seq_puts(m, "********** dump DTSI **********\n");
|
|
|
|
seq_printf(m, "Active Table :%d\n",
|
|
fg_table_cust_data.active_table_number);
|
|
|
|
for (i = 0; i < fg_table_cust_data.active_table_number; i++) {
|
|
seq_printf(m, "PMIC_MIN_VOL = %d\n",
|
|
fg_table_cust_data.fg_profile[i].pmic_min_vol);
|
|
}
|
|
for (i = 0; i < fg_table_cust_data.active_table_number; i++) {
|
|
seq_printf(m, "POWERON_SYSTEM_IBOOT = %d\n",
|
|
fg_table_cust_data.fg_profile[i].pon_iboot);
|
|
}
|
|
for (i = 0; i < fg_table_cust_data.active_table_number; i++) {
|
|
seq_printf(m, "TEMPERATURE_T%d = %d\n",
|
|
i, fg_table_cust_data.fg_profile[i].temperature);
|
|
}
|
|
for (i = 0; i < fg_table_cust_data.active_table_number; i++) {
|
|
seq_printf(m, "g_FG_PSEUDO100_%d = %d\n",
|
|
i, fg_table_cust_data.fg_profile[i].pseudo100);
|
|
}
|
|
|
|
seq_printf(m, "DIFFERENCE_FULLOCV_ITH = %d\n",
|
|
fg_cust_data.difference_fullocv_ith);
|
|
seq_printf(m, "SHUTDOWN_1_TIME = %d\n",
|
|
fg_cust_data.shutdown_1_time);
|
|
seq_printf(m, "KEEP_100_PERCENT = %d\n",
|
|
fg_cust_data.keep_100_percent_minsoc);
|
|
seq_printf(m, "R_FG_VALUE = %d\n",
|
|
fg_cust_data.r_fg_value);
|
|
seq_printf(m, "EMBEDDED_SEL = %d\n",
|
|
fg_cust_data.embedded_sel);
|
|
seq_printf(m, "PMIC_SHUTDOWN_CURRENT = %d\n",
|
|
fg_cust_data.pmic_shutdown_current);
|
|
seq_printf(m, "FG_METER_RESISTANCE = %d\n",
|
|
fg_cust_data.fg_meter_resistance);
|
|
seq_printf(m, "CAR_TUNE_VALUE = %d\n",
|
|
fg_cust_data.car_tune_value);
|
|
seq_printf(m, "SHUTDOWN_GAUGE0_VOLTAGE = %d\n",
|
|
fg_cust_data.shutdown_gauge0_voltage);
|
|
seq_printf(m, "Q_MAX_SYS_VOLTAGE = %d\n",
|
|
fg_cust_data.q_max_sys_voltage);
|
|
seq_printf(m, "COM_FG_METER_RESISTANCE = %d\n",
|
|
fg_cust_data.com_fg_meter_resistance);
|
|
seq_printf(m, "COM_R_FG_VALUE = %d\n",
|
|
fg_cust_data.com_r_fg_value);
|
|
seq_printf(m, "enable_tmp_intr_suspend = %d\n",
|
|
gm.enable_tmp_intr_suspend);
|
|
seq_printf(m, "ACTIVE_TABLE = %d\n",
|
|
fg_table_cust_data.active_table_number);
|
|
seq_printf(m, "MULTI_TEMP_GAUGE0 = %d\n",
|
|
fg_cust_data.multi_temp_gauge0);
|
|
seq_printf(m, "SHUTDOWN_GAUGE0 = %d\n",
|
|
fg_cust_data.shutdown_gauge0);
|
|
seq_printf(m, "SHUTDOWN_GAUGE1_XMINS = %d\n",
|
|
fg_cust_data.shutdown_gauge1_xmins);
|
|
seq_printf(m, "SHUTDOWN_GAUGE1_VBAT_EN = %d\n",
|
|
fg_cust_data.shutdown_gauge1_vbat_en);
|
|
seq_printf(m, "SHUTDOWN_GAUGE1_VBAT = %d\n",
|
|
fg_cust_data.shutdown_gauge1_vbat);
|
|
seq_printf(m, "PSEUDO100_EN = %d\n",
|
|
fg_cust_data.pseudo100_en);
|
|
seq_printf(m, "PSEUDO100_EN_DIS = %d\n",
|
|
fg_cust_data.pseudo100_en_dis);
|
|
|
|
|
|
|
|
seq_printf(m, "CHARGE_PSEUDO_FULL_LEVEL = %d\n",
|
|
fg_cust_data.charge_pseudo_full_level);
|
|
seq_printf(m, "FULL_TRACKING_BAT_INT2_MULTIPLY = %d\n",
|
|
fg_cust_data.full_tracking_bat_int2_multiply);
|
|
seq_printf(m, "DISCHARGE_TRACKING_TIME = %d\n",
|
|
fg_cust_data.discharge_tracking_time);
|
|
seq_printf(m, "CHARGE_TRACKING_TIME = %d\n",
|
|
fg_cust_data.charge_tracking_time);
|
|
seq_printf(m, "DIFFERENCE_FULLOCV_VTH = %d\n",
|
|
fg_cust_data.difference_fullocv_vth);
|
|
seq_printf(m, "HWOCV_SWOCV_DIFF = %d\n",
|
|
fg_cust_data.hwocv_swocv_diff);
|
|
seq_printf(m, "HWOCV_SWOCV_DIFF_LT = %d\n",
|
|
fg_cust_data.hwocv_swocv_diff_lt);
|
|
seq_printf(m, "HWOCV_SWOCV_DIFF_LT_TEMP = %d\n",
|
|
fg_cust_data.hwocv_swocv_diff_lt_temp);
|
|
seq_printf(m, "HWOCV_OLDOCV_DIFF = %d\n",
|
|
fg_cust_data.hwocv_oldocv_diff);
|
|
seq_printf(m, "HWOCV_OLDOCV_DIFF_CHR = %d\n",
|
|
fg_cust_data.hwocv_oldocv_diff_chr);
|
|
seq_printf(m, "VBAT_OLDOCV_DIFF = %d\n",
|
|
fg_cust_data.vbat_oldocv_diff);
|
|
seq_printf(m, "SWOCV_OLDOCV_DIFF_EMB = %d\n",
|
|
fg_cust_data.swocv_oldocv_diff_emb);
|
|
seq_printf(m, "TNEW_TOLD_PON_DIFF = %d\n",
|
|
fg_cust_data.tnew_told_pon_diff);
|
|
seq_printf(m, "TNEW_TOLD_PON_DIFF2 = %d\n",
|
|
fg_cust_data.tnew_told_pon_diff2);
|
|
seq_printf(m, "PMIC_SHUTDOWN_TIME = %d\n",
|
|
fg_cust_data.pmic_shutdown_time);
|
|
seq_printf(m, "EXT_HWOCV_SWOCV = %d\n",
|
|
gm.ext_hwocv_swocv);
|
|
seq_printf(m, "EXT_HWOCV_SWOCV_LT = %d\n",
|
|
gm.ext_hwocv_swocv_lt);
|
|
seq_printf(m, "EXT_HWOCV_SWOCV_LT_TEMP = %d\n",
|
|
gm.ext_hwocv_swocv_lt_temp);
|
|
seq_printf(m, "DIFFERENCE_FGC_FGV_TH1 = %d\n",
|
|
fg_cust_data.difference_fgc_fgv_th1);
|
|
seq_printf(m, "DIFFERENCE_FGC_FGV_TH2 = %d\n",
|
|
fg_cust_data.difference_fgc_fgv_th2);
|
|
seq_printf(m, "DIFFERENCE_FGC_FGV_TH3 = %d\n",
|
|
fg_cust_data.difference_fgc_fgv_th3);
|
|
seq_printf(m, "DIFFERENCE_FGC_FGV_TH_SOC1 = %d\n",
|
|
fg_cust_data.difference_fgc_fgv_th_soc1);
|
|
seq_printf(m, "DIFFERENCE_FGC_FGV_TH_SOC2 = %d\n",
|
|
fg_cust_data.difference_fgc_fgv_th_soc2);
|
|
seq_printf(m, "PMIC_SHUTDOWN_SW_EN = %d\n",
|
|
fg_cust_data.pmic_shutdown_sw_en);
|
|
seq_printf(m, "FORCE_VC_MODE = %d\n",
|
|
fg_cust_data.force_vc_mode);
|
|
seq_printf(m, "ZCV_SUSPEND_TIME = %d\n",
|
|
fg_cust_data.zcv_suspend_time);
|
|
seq_printf(m, "SLEEP_CURRENT_AVG = %d\n",
|
|
fg_cust_data.sleep_current_avg);
|
|
seq_printf(m, "ZCV_CAR_GAP_PERCENTAGE = %d\n",
|
|
fg_cust_data.zcv_car_gap_percentage);
|
|
seq_printf(m, "UI_FULL_LIMIT_EN = %d\n",
|
|
fg_cust_data.ui_full_limit_en);
|
|
seq_printf(m, "UI_FULL_LIMIT_SOC0 = %d\n",
|
|
fg_cust_data.ui_full_limit_soc0);
|
|
seq_printf(m, "UI_FULL_LIMIT_ITH0 = %d\n",
|
|
fg_cust_data.ui_full_limit_ith0);
|
|
seq_printf(m, "UI_FULL_LIMIT_SOC1 = %d\n",
|
|
fg_cust_data.ui_full_limit_soc1);
|
|
seq_printf(m, "UI_FULL_LIMIT_ITH1 = %d\n",
|
|
fg_cust_data.ui_full_limit_ith1);
|
|
seq_printf(m, "UI_FULL_LIMIT_SOC2 = %d\n",
|
|
fg_cust_data.ui_full_limit_soc2);
|
|
seq_printf(m, "UI_FULL_LIMIT_ITH2 = %d\n",
|
|
fg_cust_data.ui_full_limit_ith2);
|
|
seq_printf(m, "UI_FULL_LIMIT_SOC3 = %d\n",
|
|
fg_cust_data.ui_full_limit_soc3);
|
|
seq_printf(m, "UI_FULL_LIMIT_ITH3 = %d\n",
|
|
fg_cust_data.ui_full_limit_ith3);
|
|
seq_printf(m, "UI_FULL_LIMIT_SOC4 = %d\n",
|
|
fg_cust_data.ui_full_limit_soc4);
|
|
seq_printf(m, "UI_FULL_LIMIT_ITH4 = %d\n",
|
|
fg_cust_data.ui_full_limit_ith4);
|
|
seq_printf(m, "UI_FULL_LIMIT_TIME = %d\n",
|
|
fg_cust_data.ui_full_limit_time);
|
|
|
|
seq_printf(m, "UI_LOW_LIMIT_EN = %d\n",
|
|
fg_cust_data.ui_low_limit_en);
|
|
seq_printf(m, "UI_LOW_LIMIT_SOC0 = %d\n",
|
|
fg_cust_data.ui_low_limit_soc0);
|
|
seq_printf(m, "UI_LOW_LIMIT_VTH0 = %d\n",
|
|
fg_cust_data.ui_low_limit_vth0);
|
|
seq_printf(m, "UI_LOW_LIMIT_SOC1 = %d\n",
|
|
fg_cust_data.ui_low_limit_soc1);
|
|
seq_printf(m, "UI_LOW_LIMIT_VTH1 = %d\n",
|
|
fg_cust_data.ui_low_limit_vth1);
|
|
seq_printf(m, "UI_LOW_LIMIT_SOC2 = %d\n",
|
|
fg_cust_data.ui_low_limit_soc2);
|
|
seq_printf(m, "UI_LOW_LIMIT_VTH2 = %d\n",
|
|
fg_cust_data.ui_low_limit_vth2);
|
|
seq_printf(m, "UI_LOW_LIMIT_SOC3 = %d\n",
|
|
fg_cust_data.ui_low_limit_soc3);
|
|
seq_printf(m, "UI_LOW_LIMIT_VTH3 = %d\n",
|
|
fg_cust_data.ui_low_limit_vth3);
|
|
seq_printf(m, "UI_LOW_LIMIT_SOC4 = %d\n",
|
|
fg_cust_data.ui_low_limit_soc4);
|
|
seq_printf(m, "UI_LOW_LIMIT_VTH4 = %d\n",
|
|
fg_cust_data.ui_low_limit_vth4);
|
|
seq_printf(m, "UI_LOW_LIMIT_TIME = %d\n",
|
|
fg_cust_data.ui_low_limit_time);
|
|
seq_printf(m, "FG_PRE_TRACKING_EN = %d\n",
|
|
fg_cust_data.fg_pre_tracking_en);
|
|
seq_printf(m, "VBAT2_DET_TIME = %d\n",
|
|
fg_cust_data.vbat2_det_time);
|
|
seq_printf(m, "VBAT2_DET_COUNTERE = %d\n",
|
|
fg_cust_data.vbat2_det_counter);
|
|
seq_printf(m, "VBAT2_DET_VOLTAGE1 = %d\n",
|
|
fg_cust_data.vbat2_det_voltage1);
|
|
seq_printf(m, "VBAT2_DET_VOLTAGE2 = %d\n",
|
|
fg_cust_data.vbat2_det_voltage2);
|
|
seq_printf(m, "VBAT2_DET_VOLTAGE3 = %d\n",
|
|
fg_cust_data.vbat2_det_voltage3);
|
|
seq_printf(m, "AGING_FACTOR_MIN = %d\n",
|
|
fg_cust_data.aging_factor_min);
|
|
seq_printf(m, "AGING_FACTOR_DIFF = %d\n",
|
|
fg_cust_data.aging_factor_diff);
|
|
seq_printf(m, "DIFFERENCE_VOLTAGE_UPDATE = %d\n",
|
|
fg_cust_data.difference_voltage_update);
|
|
seq_printf(m, "AGING_ONE_EN = %d\n",
|
|
fg_cust_data.aging_one_en);
|
|
seq_printf(m, "AGING1_UPDATE_SOC = %d\n",
|
|
fg_cust_data.aging1_update_soc);
|
|
seq_printf(m, "AGING1_LOAD_SOC = %d\n",
|
|
fg_cust_data.aging1_load_soc);
|
|
|
|
seq_printf(m, "AGING4_UPDATE_SOC = %d\n",
|
|
fg_cust_data.aging4_update_soc);
|
|
seq_printf(m, "AGING4_LOAD_SOC = %d\n",
|
|
fg_cust_data.aging4_load_soc);
|
|
seq_printf(m, "AGING5_UPDATE_SOC = %d\n",
|
|
fg_cust_data.aging5_update_soc);
|
|
seq_printf(m, "AGING5_LOAD_SOC = %d\n",
|
|
fg_cust_data.aging5_load_soc);
|
|
seq_printf(m, "AGING6_UPDATE_SOC = %d\n",
|
|
fg_cust_data.aging6_update_soc);
|
|
seq_printf(m, "AGING6_LOAD_SOC = %d\n",
|
|
fg_cust_data.aging6_load_soc);
|
|
|
|
seq_printf(m, "AGING_TEMP_DIFF = %d\n",
|
|
fg_cust_data.aging_temp_diff);
|
|
seq_printf(m, "AGING_100_EN = %d\n",
|
|
fg_cust_data.aging_100_en);
|
|
seq_printf(m, "AGING_TWO_EN = %d\n",
|
|
fg_cust_data.aging_two_en);
|
|
seq_printf(m, "AGING_THIRD_EN = %d\n",
|
|
fg_cust_data.aging_third_en);
|
|
seq_printf(m, "AGING_4_EN = %d\n",
|
|
fg_cust_data.aging_4_en);
|
|
seq_printf(m, "AGING_5_EN = %d\n",
|
|
fg_cust_data.aging_5_en);
|
|
seq_printf(m, "AGING_6_EN = %d\n",
|
|
fg_cust_data.aging_6_en);
|
|
seq_printf(m, "DIFF_SOC_SETTING = %d\n",
|
|
fg_cust_data.diff_soc_setting);
|
|
seq_printf(m, "DIFF_BAT_TEMP_SETTING = %d\n",
|
|
fg_cust_data.diff_bat_temp_setting);
|
|
seq_printf(m, "DIFF_BAT_TEMP_SETTING_C = %d\n",
|
|
fg_cust_data.diff_bat_temp_setting_c);
|
|
seq_printf(m, "DIFF_IAVG_TH = %d\n",
|
|
fg_cust_data.diff_iavg_th);
|
|
seq_printf(m, "FG_TRACKING_CURRENT = %d\n",
|
|
fg_cust_data.fg_tracking_current);
|
|
seq_printf(m, "FG_TRACKING_CURRENT_IBOOT_EN = %d\n",
|
|
fg_cust_data.fg_tracking_current_iboot_en);
|
|
seq_printf(m, "UISOC_UPDATE_TYPE = %d\n",
|
|
fg_cust_data.uisoc_update_type);
|
|
seq_printf(m, "OVER_DISCHARGE_LEVEL = %d\n",
|
|
fg_cust_data.over_discharge_level);
|
|
seq_printf(m, "NAFG_TIME_SETTING = %d\n",
|
|
fg_cust_data.nafg_time_setting);
|
|
seq_printf(m, "NAFG_RATIO = %d\n",
|
|
fg_cust_data.nafg_ratio);
|
|
|
|
|
|
seq_printf(m, "NAFG_RATIO_EN = %d\n",
|
|
fg_cust_data.nafg_ratio_en);
|
|
seq_printf(m, "NAFG_RATIO_TMP_THR = %d\n",
|
|
fg_cust_data.nafg_ratio_tmp_thr);
|
|
seq_printf(m, "D0_SEL = %d\n",
|
|
fg_cust_data.d0_sel);
|
|
seq_printf(m, "IBOOT_SEL = %d\n",
|
|
fg_cust_data.iboot_sel);
|
|
seq_printf(m, "SHUTDOWN_SYSTEM_IBOOT = %d\n",
|
|
fg_cust_data.shutdown_system_iboot);
|
|
seq_printf(m, "DIFFERENCE_FULL_CV = %d\n",
|
|
fg_cust_data.difference_full_cv);
|
|
seq_printf(m, "PSEUDO1_EN = %d\n",
|
|
fg_cust_data.pseudo1_en);
|
|
seq_printf(m, "LOADING_1_EN = %d\n",
|
|
fg_cust_data.loading_1_en);
|
|
seq_printf(m, "LOADING_2_EN = %d\n",
|
|
fg_cust_data.loading_2_en);
|
|
seq_printf(m, "PSEUDO1_SEL = %d\n",
|
|
fg_cust_data.pseudo1_sel);
|
|
seq_printf(m, "UI_FAST_TRACKING_EN = %d\n",
|
|
fg_cust_data.ui_fast_tracking_en);
|
|
seq_printf(m, "UI_FAST_TRACKING_GAP = %d\n",
|
|
fg_cust_data.ui_fast_tracking_gap);
|
|
seq_printf(m, "KEEP_100_PERCENT_MINSOC = %d\n",
|
|
fg_cust_data.keep_100_percent_minsoc);
|
|
seq_printf(m, "NO_BAT_TEMP_COMPENSATE = %d\n",
|
|
gm.no_bat_temp_compensate);
|
|
seq_printf(m, "LOW_TEMP_MODE = %d\n",
|
|
fg_cust_data.low_temp_mode);
|
|
seq_printf(m, "LOW_TEMP_MODE_TEMP = %d\n",
|
|
fg_cust_data.low_temp_mode_temp);
|
|
seq_printf(m, "Q_MAX_L_CURRENT = %d\n",
|
|
fg_cust_data.q_max_L_current);
|
|
seq_printf(m, "Q_MAX_H_CURRENT = %d\n",
|
|
fg_cust_data.q_max_H_current);
|
|
seq_printf(m, "pl_two_sec_reboot = %d\n", gm.pl_two_sec_reboot);
|
|
#ifdef SHUTDOWN_CONDITION_LOW_BAT_VOLT
|
|
seq_puts(m, "SHUTDOWN_CONDITION_LOW_BAT_VOLT = 1\n");
|
|
seq_printf(m, "lbat_def: %d %d %d\n",
|
|
VBAT2_DET_VOLTAGE1, VBAT2_DET_VOLTAGE2, VBAT2_DET_VOLTAGE3);
|
|
seq_printf(m, "lbat: %d %d %d\n", fg_cust_data.vbat2_det_voltage1,
|
|
fg_cust_data.vbat2_det_voltage2,
|
|
fg_cust_data.vbat2_det_voltage3);
|
|
#else
|
|
seq_puts(m, "SHUTDOWN_CONDITION_LOW_BAT_VOLT = 0\n");
|
|
#endif
|
|
seq_printf(m, "hw_version = %d\n", gauge_get_hw_version());
|
|
seq_printf(m, "DYNAMIC_CV_FACTOR = %d\n",
|
|
fg_cust_data.dynamic_cv_factor);
|
|
seq_printf(m, "CHARGER_IEOC = %d\n",
|
|
fg_cust_data.charger_ieoc);
|
|
|
|
}
|
|
|
|
static void dump_daemon_table(struct seq_file *m)
|
|
{
|
|
int i, j;
|
|
struct FUELGAUGE_PROFILE_STRUCT *ptr;
|
|
struct fuel_gauge_table_custom_data *ptable2;
|
|
struct fuel_gauge_table *pfgt;
|
|
|
|
ptable2 = &gm.fg_data.fg_table_cust_data;
|
|
|
|
for (j = 0; j < fg_table_cust_data.active_table_number; j++) {
|
|
pfgt = &gm.fg_data.fg_table_cust_data.fg_profile[j];
|
|
seq_printf(m, "daemon table idx:%d size:%d\n",
|
|
j,
|
|
pfgt->size);
|
|
|
|
seq_printf(m,
|
|
"tmp:%d qmax:%d %d pseudo1:%d pseudo100:%d\n",
|
|
pfgt->temperature,
|
|
pfgt->q_max,
|
|
pfgt->q_max_h_current,
|
|
pfgt->pseudo1,
|
|
pfgt->pseudo100);
|
|
|
|
seq_printf(m,
|
|
"pmic_min_vol:%d pon_iboot:%d qmax_sys_vol:%d sd_hl_zcv:%d\n",
|
|
pfgt->pmic_min_vol,
|
|
pfgt->pon_iboot,
|
|
pfgt->qmax_sys_vol,
|
|
pfgt->shutdown_hl_zcv);
|
|
|
|
seq_puts(m, "idx: maH, voltage, R1, R2, percentage\n");
|
|
ptr = &ptable2->fg_profile[j].fg_profile[0];
|
|
for (i = 0; i < 100; i++) {
|
|
seq_printf(m, "%d: %d %d %d %d %d\n",
|
|
i,
|
|
ptr[i].mah,
|
|
ptr[i].voltage,
|
|
ptr[i].resistance,
|
|
ptr[i].charge_r.rdc[0],
|
|
ptr[i].percentage);
|
|
}
|
|
}
|
|
|
|
seq_printf(m, "\ndaemon table idx:tmp0 size:%d\n",
|
|
gm.fg_data.fg_table_cust_data.fg_profile_temperature_0_size);
|
|
seq_puts(m, "idx: maH, voltage, R1, R2, percentage\n");
|
|
ptr = &gm.fg_data.fg_table_cust_data.fg_profile_temperature_0[0];
|
|
for (i = 0; i < 100; i++) {
|
|
seq_printf(m, "%d: %d %d %d %d %d\n",
|
|
i,
|
|
ptr[i].mah,
|
|
ptr[i].voltage,
|
|
ptr[i].resistance,
|
|
ptr[i].charge_r.rdc[0],
|
|
ptr[i].percentage);
|
|
|
|
}
|
|
|
|
seq_printf(m, "\ndaemon table idx:tmp1 size:%d\n",
|
|
gm.fg_data.fg_table_cust_data.fg_profile_temperature_1_size);
|
|
seq_puts(m, "idx: maH, voltage, R, R2, percentage\n");
|
|
ptr = &gm.fg_data.fg_table_cust_data.fg_profile_temperature_1[0];
|
|
for (i = 0; i < 100; i++) {
|
|
seq_printf(m, "%d: %d %d %d %d %d\n",
|
|
i,
|
|
ptr[i].mah,
|
|
ptr[i].voltage,
|
|
ptr[i].resistance,
|
|
ptr[i].charge_r.rdc[0],
|
|
ptr[i].percentage);
|
|
}
|
|
|
|
}
|
|
|
|
static void dump_kernel_table(struct seq_file *m)
|
|
{
|
|
int i, j;
|
|
struct FUELGAUGE_PROFILE_STRUCT *ptr;
|
|
struct fuel_gauge_table_custom_data *ptable1;
|
|
struct fuel_gauge_table *pfgt;
|
|
|
|
ptable1 = &fg_table_cust_data;
|
|
|
|
seq_printf(m, "tables no:%d table size:%d\n",
|
|
fg_table_cust_data.active_table_number,
|
|
fg_table_cust_data.fg_profile[0].size);
|
|
|
|
for (j = 0; j < fg_table_cust_data.active_table_number; j++) {
|
|
pfgt = &ptable1->fg_profile[j];
|
|
ptr = &ptable1->fg_profile[j].fg_profile[0];
|
|
seq_printf(m, "table idx:%d size:%d\n",
|
|
j,
|
|
pfgt->size);
|
|
|
|
seq_printf(m,
|
|
"tmp:%d qmax:%d %d pseudo1:%d pseudo100:%d\n",
|
|
pfgt->temperature,
|
|
pfgt->q_max,
|
|
pfgt->q_max_h_current,
|
|
pfgt->pseudo1,
|
|
pfgt->pseudo100);
|
|
|
|
seq_printf(m,
|
|
"pmic_min_vol:%d pon_iboot:%d qmax_sys_vol:%d sd_hl_zcv:%d\n",
|
|
pfgt->pmic_min_vol,
|
|
pfgt->pon_iboot,
|
|
pfgt->qmax_sys_vol,
|
|
pfgt->shutdown_hl_zcv);
|
|
|
|
seq_puts(m, "idx: maH, voltage, R1, R2, percentage\n");
|
|
for (i = 0; i < 100; i++) {
|
|
seq_printf(m, "%d: %d %d %d %d %d\n",
|
|
i,
|
|
ptr[i].mah,
|
|
ptr[i].voltage,
|
|
ptr[i].resistance,
|
|
ptr[i].charge_r.rdc[0],
|
|
ptr[i].percentage);
|
|
}
|
|
}
|
|
|
|
seq_puts(m, "\n");
|
|
|
|
if (is_recovery_mode() == false) {
|
|
dump_daemon_table(m);
|
|
} else {
|
|
|
|
ptr = &ptable1->fg_profile_temperature_1[0];
|
|
seq_puts(m, "tmp1 idx: maH, voltage, R1, R2, percentage\n");
|
|
for (i = 0; i < 100; i++) {
|
|
seq_printf(m, "%d: %d %d %d %d %d\n",
|
|
i,
|
|
ptr[i].mah,
|
|
ptr[i].voltage,
|
|
ptr[i].resistance,
|
|
ptr[i].charge_r.rdc[0],
|
|
ptr[i].percentage);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static int proc_dump_log_show(struct seq_file *m, void *v)
|
|
{
|
|
int i;
|
|
|
|
seq_puts(m, "********** Gauge Dump **********\n");
|
|
|
|
seq_puts(m, "Command Table list\n");
|
|
seq_puts(m, "0: dump dtsi\n");
|
|
seq_puts(m, "1: dump v-mode table\n");
|
|
seq_puts(m, "101: dump gauge hw register\n");
|
|
seq_puts(m, "102: kernel table\n");
|
|
seq_puts(m, "103: send CHR FULL\n");
|
|
seq_puts(m, "104: disable NAFG interrupt\n");
|
|
seq_puts(m, "105: show daemon pid\n");
|
|
|
|
seq_printf(m, "current command:%d\n", gm.proc_cmd_id);
|
|
|
|
switch (gm.proc_cmd_id) {
|
|
case 0:
|
|
proc_dump_dtsi(m);
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD, FG_KERNEL_CMD_DUMP_LOG,
|
|
gm.proc_cmd_id);
|
|
for (i = 0; i < 5; i++) {
|
|
msleep(500);
|
|
if (gm.proc_subcmd_para1 == 1)
|
|
break;
|
|
}
|
|
proc_dump_log(m);
|
|
break;
|
|
case 101:
|
|
gauge_dev_dump(gm.gdev, m, 0);
|
|
break;
|
|
case 102:
|
|
dump_kernel_table(m);
|
|
break;
|
|
case 103:
|
|
wakeup_fg_algo(FG_INTR_CHR_FULL);
|
|
break;
|
|
case 104:
|
|
gauge_set_nag_en(false);
|
|
gm.disable_nafg_int = true;
|
|
break;
|
|
case 105:
|
|
seq_printf(m, "Gauge daemon pid:%d\n", gm.g_fgd_pid);
|
|
break;
|
|
default:
|
|
seq_printf(m, "do not support command:%d\n", gm.proc_cmd_id);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
/*battery_dump_info(m);*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t proc_write(
|
|
struct file *file, const char __user *buffer,
|
|
size_t count, loff_t *f_pos)
|
|
{
|
|
int cmd = 0;
|
|
char num[10];
|
|
|
|
memset(num, 0, 10);
|
|
|
|
if (!count)
|
|
return 0;
|
|
|
|
if (count > (sizeof(num) - 1))
|
|
return -EINVAL;
|
|
|
|
if (copy_from_user(num, buffer, count))
|
|
return -EFAULT;
|
|
|
|
if (kstrtoint(num, 10, &cmd) == 0)
|
|
gm.proc_cmd_id = cmd;
|
|
else {
|
|
gm.proc_cmd_id = 0;
|
|
return -EFAULT;
|
|
}
|
|
|
|
bm_err("%s success %d\n",
|
|
__func__, cmd);
|
|
return count;
|
|
}
|
|
|
|
|
|
static int proc_dump_log_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, proc_dump_log_show, NULL);
|
|
}
|
|
|
|
static const struct file_operations battery_dump_log_proc_fops = {
|
|
.open = proc_dump_log_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = proc_write,
|
|
};
|
|
|
|
void battery_debug_init(void)
|
|
{
|
|
struct proc_dir_entry *battery_dir;
|
|
|
|
battery_dir = proc_mkdir("battery", NULL);
|
|
if (!battery_dir) {
|
|
bm_err("fail to mkdir /proc/battery\n");
|
|
return;
|
|
}
|
|
|
|
proc_create("dump_log", 0644,
|
|
battery_dir, &battery_dump_log_proc_fops);
|
|
}
|
|
|
|
static ssize_t show_Battery_Temperature(
|
|
struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
bm_err("%s: %d %d\n",
|
|
__func__,
|
|
battery_main.BAT_batt_temp, gm.fixed_bat_tmp);
|
|
return sprintf(buf, "%d\n", gm.fixed_bat_tmp);
|
|
}
|
|
|
|
static ssize_t store_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 > 58 || temp < -10) {
|
|
bm_err(
|
|
"%s: setting tmp:%d!,reject set\n",
|
|
__func__,
|
|
temp);
|
|
return size;
|
|
}
|
|
|
|
gm.fixed_bat_tmp = temp;
|
|
if (gm.fixed_bat_tmp == 0xffff)
|
|
fg_bat_temp_int_internal();
|
|
else {
|
|
gauge_dev_enable_battery_tmp_lt_interrupt(
|
|
gm.gdev, 0, 0);
|
|
gauge_dev_enable_battery_tmp_ht_interrupt(
|
|
gm.gdev, 0, 0);
|
|
wakeup_fg_algo(FG_INTR_BAT_TMP_C_HT);
|
|
wakeup_fg_algo(FG_INTR_BAT_TMP_HT);
|
|
}
|
|
battery_main.BAT_batt_temp = force_get_tbat(true);
|
|
bm_err(
|
|
"%s: fixed_bat_tmp:%d ,tmp:%d!\n",
|
|
__func__,
|
|
temp, battery_main.BAT_batt_temp);
|
|
battery_update(&battery_main);
|
|
} else {
|
|
bm_err("%s: format error!\n", __func__);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(Battery_Temperature, 0664, show_Battery_Temperature,
|
|
store_Battery_Temperature);
|
|
|
|
static ssize_t show_UI_SOC(
|
|
struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
bm_err("%s: %d %d\n",
|
|
__func__,
|
|
gm.ui_soc, gm.fixed_uisoc);
|
|
return sprintf(buf, "%d\n", gm.fixed_uisoc);
|
|
}
|
|
|
|
static ssize_t store_UI_SOC(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
signed int temp;
|
|
|
|
if (kstrtoint(buf, 10, &temp) == 0) {
|
|
|
|
gm.fixed_uisoc = temp;
|
|
|
|
bm_err("%s: %d %d\n",
|
|
__func__,
|
|
gm.ui_soc, gm.fixed_uisoc);
|
|
|
|
battery_update(&battery_main);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(UI_SOC, 0664, show_UI_SOC,
|
|
store_UI_SOC);
|
|
|
|
|
|
/* ============================================================ */
|
|
/* Internal function */
|
|
/* ============================================================ */
|
|
void fg_custom_data_check(void)
|
|
{
|
|
struct fuel_gauge_custom_data *p;
|
|
|
|
p = &fg_cust_data;
|
|
fgauge_get_profile_id();
|
|
|
|
bm_err("FGLOG MultiGauge0[%d] BATID[%d] pmic_min_vol[%d,%d,%d,%d,%d]\n",
|
|
p->multi_temp_gauge0, gm.battery_id,
|
|
fg_table_cust_data.fg_profile[0].pmic_min_vol,
|
|
fg_table_cust_data.fg_profile[1].pmic_min_vol,
|
|
fg_table_cust_data.fg_profile[2].pmic_min_vol,
|
|
fg_table_cust_data.fg_profile[3].pmic_min_vol,
|
|
fg_table_cust_data.fg_profile[4].pmic_min_vol);
|
|
bm_err("FGLOG pon_iboot[%d,%d,%d,%d,%d] qmax_sys_vol[%d %d %d %d %d]\n",
|
|
fg_table_cust_data.fg_profile[0].pon_iboot,
|
|
fg_table_cust_data.fg_profile[1].pon_iboot,
|
|
fg_table_cust_data.fg_profile[2].pon_iboot,
|
|
fg_table_cust_data.fg_profile[3].pon_iboot,
|
|
fg_table_cust_data.fg_profile[4].pon_iboot,
|
|
fg_table_cust_data.fg_profile[0].qmax_sys_vol,
|
|
fg_table_cust_data.fg_profile[1].qmax_sys_vol,
|
|
fg_table_cust_data.fg_profile[2].qmax_sys_vol,
|
|
fg_table_cust_data.fg_profile[3].qmax_sys_vol,
|
|
fg_table_cust_data.fg_profile[4].qmax_sys_vol);
|
|
|
|
}
|
|
|
|
int interpolation(int i1, int b1, int i2, int b2, int i)
|
|
{
|
|
int ret;
|
|
|
|
ret = (b2 - b1) * (i - i1) / (i2 - i1) + b1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
unsigned int TempConverBattThermistor(int temp)
|
|
{
|
|
int RES1 = 0, RES2 = 0;
|
|
int TMP1 = 0, TMP2 = 0;
|
|
int i;
|
|
unsigned int TBatt_R_Value = 0xffff;
|
|
|
|
if (temp >= Fg_Temperature_Table[20].BatteryTemp) {
|
|
TBatt_R_Value = Fg_Temperature_Table[20].TemperatureR;
|
|
} else if (temp <= Fg_Temperature_Table[0].BatteryTemp) {
|
|
TBatt_R_Value = Fg_Temperature_Table[0].TemperatureR;
|
|
} else {
|
|
RES1 = Fg_Temperature_Table[0].TemperatureR;
|
|
TMP1 = Fg_Temperature_Table[0].BatteryTemp;
|
|
|
|
for (i = 0; i <= 20; i++) {
|
|
if (temp <= Fg_Temperature_Table[i].BatteryTemp) {
|
|
RES2 = Fg_Temperature_Table[i].TemperatureR;
|
|
TMP2 = Fg_Temperature_Table[i].BatteryTemp;
|
|
break;
|
|
}
|
|
{ /* hidden else */
|
|
RES1 = Fg_Temperature_Table[i].TemperatureR;
|
|
TMP1 = Fg_Temperature_Table[i].BatteryTemp;
|
|
}
|
|
}
|
|
|
|
|
|
TBatt_R_Value = interpolation(TMP1, RES1, TMP2, RES2, temp);
|
|
}
|
|
|
|
bm_warn(
|
|
"[%s] [%d] %d %d %d %d %d\n",
|
|
__func__,
|
|
TBatt_R_Value, TMP1,
|
|
RES1, TMP2, RES2, temp);
|
|
|
|
return TBatt_R_Value;
|
|
}
|
|
|
|
int BattThermistorConverTemp(int Res)
|
|
{
|
|
int i = 0;
|
|
int RES1 = 0, RES2 = 0;
|
|
int TBatt_Value = -2000, TMP1 = 0, TMP2 = 0;
|
|
|
|
if (Res >= Fg_Temperature_Table[0].TemperatureR) {
|
|
TBatt_Value = -400;
|
|
} else if (Res <= Fg_Temperature_Table[20].TemperatureR) {
|
|
TBatt_Value = 600;
|
|
} else {
|
|
RES1 = Fg_Temperature_Table[0].TemperatureR;
|
|
TMP1 = Fg_Temperature_Table[0].BatteryTemp;
|
|
|
|
for (i = 0; i <= 20; i++) {
|
|
if (Res >= Fg_Temperature_Table[i].TemperatureR) {
|
|
RES2 = Fg_Temperature_Table[i].TemperatureR;
|
|
TMP2 = Fg_Temperature_Table[i].BatteryTemp;
|
|
break;
|
|
}
|
|
{ /* hidden else */
|
|
RES1 = Fg_Temperature_Table[i].TemperatureR;
|
|
TMP1 = Fg_Temperature_Table[i].BatteryTemp;
|
|
}
|
|
}
|
|
|
|
TBatt_Value = (((Res - RES2) * TMP1) +
|
|
((RES1 - Res) * TMP2)) * 10 / (RES1 - RES2);
|
|
}
|
|
bm_trace(
|
|
"[%s] %d %d %d %d %d %d\n",
|
|
__func__,
|
|
RES1, RES2, Res, TMP1,
|
|
TMP2, TBatt_Value);
|
|
|
|
return TBatt_Value;
|
|
}
|
|
|
|
unsigned int TempToBattVolt(int temp, int update)
|
|
{
|
|
unsigned int R_NTC = TempConverBattThermistor(temp);
|
|
long long Vin = 0;
|
|
long long V_IR_comp = 0;
|
|
/*int vbif28 = pmic_get_auxadc_value(AUXADC_LIST_VBIF);*/
|
|
int vbif28 = gm.rbat.rbat_pull_up_volt;
|
|
static int fg_current_temp;
|
|
static bool fg_current_state;
|
|
int fg_r_value = fg_cust_data.com_r_fg_value;
|
|
int fg_meter_res_value = 0;
|
|
|
|
if (gm.no_bat_temp_compensate == 0)
|
|
fg_meter_res_value = fg_cust_data.com_fg_meter_resistance;
|
|
else
|
|
fg_meter_res_value = 0;
|
|
|
|
#ifdef RBAT_PULL_UP_VOLT_BY_BIF
|
|
vbif28 = pmic_get_vbif28_volt();
|
|
#endif
|
|
Vin = (long long)R_NTC * vbif28 * 10; /* 0.1 mV */
|
|
|
|
#if defined(__LP64__) || defined(_LP64)
|
|
do_div(Vin, (R_NTC + gm.rbat.rbat_pull_up_r));
|
|
#else
|
|
Vin = div_s64(Vin, (R_NTC + gm.rbat.rbat_pull_up_r));
|
|
#endif
|
|
|
|
if (update == true)
|
|
fg_current_state = gauge_get_current(&fg_current_temp);
|
|
|
|
if (fg_current_state == true) {
|
|
V_IR_comp = Vin;
|
|
V_IR_comp +=
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value)) / 10000);
|
|
} else {
|
|
V_IR_comp = Vin;
|
|
V_IR_comp -=
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value)) / 10000);
|
|
}
|
|
|
|
bm_notice("[%s] temp %d R_NTC %d V(%lld %lld) I %d CHG %d\n",
|
|
__func__,
|
|
temp, R_NTC, Vin, V_IR_comp, fg_current_temp, fg_current_state);
|
|
|
|
return (unsigned int) V_IR_comp;
|
|
}
|
|
|
|
int BattVoltToTemp(int dwVolt, int volt_cali)
|
|
{
|
|
long long TRes_temp;
|
|
long long TRes;
|
|
int sBaTTMP = -100;
|
|
int vbif28 = gm.rbat.rbat_pull_up_volt;
|
|
int delta_v;
|
|
|
|
TRes_temp = (gm.rbat.rbat_pull_up_r * (long long) dwVolt);
|
|
#ifdef RBAT_PULL_UP_VOLT_BY_BIF
|
|
vbif28 = pmic_get_vbif28_volt() + volt_cali;
|
|
delta_v = abs(vbif28 - dwVolt);
|
|
if (delta_v == 0)
|
|
delta_v = 1;
|
|
|
|
#if defined(__LP64__) || defined(_LP64)
|
|
do_div(TRes_temp, delta_v);
|
|
#else
|
|
TRes_temp = div_s64(TRes_temp, delta_v);
|
|
#endif
|
|
|
|
if (vbif28 > 3000 || vbif28 < 2500)
|
|
bm_err(
|
|
"[RBAT_PULL_UP_VOLT_BY_BIF] vbif28:%d\n",
|
|
pmic_get_vbif28_volt());
|
|
#else
|
|
delta_v = abs(gm.rbat.rbat_pull_up_volt - dwVolt);
|
|
if (delta_v == 0)
|
|
delta_v = 1;
|
|
#if defined(__LP64__) || defined(_LP64)
|
|
do_div(TRes_temp, delta_v);
|
|
#else
|
|
TRes_temp = div_s64(TRes_temp, delta_v);
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef RBAT_PULL_DOWN_R
|
|
TRes = (TRes_temp * RBAT_PULL_DOWN_R);
|
|
|
|
#if defined(__LP64__) || defined(_LP64)
|
|
do_div(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));
|
|
#else
|
|
TRes_temp = div_s64(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));
|
|
#endif
|
|
|
|
#else
|
|
TRes = TRes_temp;
|
|
#endif
|
|
|
|
/* convert register to temperature */
|
|
if (!pmic_is_bif_exist())
|
|
sBaTTMP = BattThermistorConverTemp((int)TRes);
|
|
else
|
|
sBaTTMP = BattThermistorConverTemp((int)TRes -
|
|
gm.rbat.bif_ntc_r);
|
|
|
|
bm_notice(
|
|
"[%s] %d %d %d %d\n",
|
|
__func__,
|
|
dwVolt, gm.rbat.rbat_pull_up_r,
|
|
vbif28, volt_cali);
|
|
return sBaTTMP;
|
|
}
|
|
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
void force_get_tbat_adc(void)
|
|
{
|
|
int bat_temperature_volt = 0;
|
|
int fg_r_value = 0;
|
|
int fg_meter_res_value = 0;
|
|
int fg_current_temp = 0;
|
|
bool fg_current_state = false;
|
|
int bat_temperature_volt_temp = 0;
|
|
int vol_cali = 0;
|
|
|
|
/* Get V_BAT_Temperature */
|
|
bat_temperature_volt = 2;
|
|
bat_temperature_volt = pmic_get_v_bat_temp();
|
|
|
|
if (bat_temperature_volt != 0) {
|
|
fg_r_value = fg_cust_data.com_r_fg_value;
|
|
if (gm.no_bat_temp_compensate == 0)
|
|
fg_meter_res_value =
|
|
fg_cust_data.com_fg_meter_resistance;
|
|
else
|
|
fg_meter_res_value = 0;
|
|
|
|
gauge_dev_get_current(
|
|
gm.gdev, &fg_current_state, &fg_current_temp);
|
|
fg_current_temp = fg_current_temp / 10;
|
|
|
|
if (fg_current_state == true) {
|
|
bat_temperature_volt_temp =
|
|
bat_temperature_volt;
|
|
bat_temperature_volt =
|
|
bat_temperature_volt -
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
vol_cali =
|
|
-((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
} else {
|
|
bat_temperature_volt_temp =
|
|
bat_temperature_volt;
|
|
bat_temperature_volt =
|
|
bat_temperature_volt +
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value)) / 10000);
|
|
vol_cali =
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
}
|
|
}
|
|
pr_info("%s: %d,%d,%d,%d,%d r:%d %d %d\n",
|
|
__func__,
|
|
bat_temperature_volt_temp, bat_temperature_volt,
|
|
fg_current_state, fg_current_temp,
|
|
fg_r_value,
|
|
fg_meter_res_value, fg_r_value, gm.no_bat_temp_compensate);
|
|
|
|
gm.tbat_adc = bat_temperature_volt;
|
|
}
|
|
#endif
|
|
|
|
int force_get_tbat_internal(bool update)
|
|
{
|
|
int bat_temperature_volt = 0;
|
|
int bat_temperature_val = 0;
|
|
static int pre_bat_temperature_val = -1;
|
|
int fg_r_value = 0;
|
|
int fg_meter_res_value = 0;
|
|
int fg_current_temp = 0;
|
|
bool fg_current_state = false;
|
|
int bat_temperature_volt_temp = 0;
|
|
int vol_cali = 0;
|
|
|
|
static int pre_bat_temperature_volt_temp, pre_bat_temperature_volt;
|
|
static int pre_fg_current_temp;
|
|
static int pre_fg_current_state;
|
|
static int pre_fg_r_value;
|
|
static int pre_bat_temperature_val2;
|
|
static struct timespec pre_time;
|
|
struct timespec ctime, dtime;
|
|
|
|
if (is_battery_init_done() == false) {
|
|
gm.tbat_precise = 250;
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
pr_info("[%s] fixed T=25\n", __func__);
|
|
#endif
|
|
return 25;
|
|
}
|
|
|
|
if (gm.fixed_bat_tmp != 0xffff) {
|
|
gm.tbat_precise = gm.fixed_bat_tmp * 10;
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
pr_info("[%s] fixed T=gm.fixed_bat_tmp: %d\n",
|
|
__func__, gm.tbat_precise);
|
|
#endif
|
|
return gm.fixed_bat_tmp;
|
|
}
|
|
|
|
if (get_ec()->fixed_temp_en) {
|
|
gm.tbat_precise = get_ec()->fixed_temp_value * 10;
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
pr_info("[%s] fixed T=get_ec()->fixed_temp_value: %d\n",
|
|
__func__, gm.tbat_precise);
|
|
#endif
|
|
return get_ec()->fixed_temp_value;
|
|
}
|
|
|
|
if (update == true || pre_bat_temperature_val == -1) {
|
|
/* Get V_BAT_Temperature */
|
|
bat_temperature_volt = 2;
|
|
bat_temperature_volt = pmic_get_v_bat_temp();
|
|
|
|
if (bat_temperature_volt != 0) {
|
|
fg_r_value = fg_cust_data.com_r_fg_value;
|
|
if (gm.no_bat_temp_compensate == 0)
|
|
fg_meter_res_value =
|
|
fg_cust_data.com_fg_meter_resistance;
|
|
else
|
|
fg_meter_res_value = 0;
|
|
|
|
|
|
gauge_dev_get_current(
|
|
gm.gdev, &fg_current_state, &fg_current_temp);
|
|
fg_current_temp = fg_current_temp / 10;
|
|
|
|
if (fg_current_state == true) {
|
|
bat_temperature_volt_temp =
|
|
bat_temperature_volt;
|
|
bat_temperature_volt =
|
|
bat_temperature_volt -
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
vol_cali =
|
|
-((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
} else {
|
|
bat_temperature_volt_temp =
|
|
bat_temperature_volt;
|
|
bat_temperature_volt =
|
|
bat_temperature_volt +
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value)) / 10000);
|
|
vol_cali =
|
|
((fg_current_temp *
|
|
(fg_meter_res_value + fg_r_value))
|
|
/ 10000);
|
|
}
|
|
|
|
bat_temperature_val =
|
|
BattVoltToTemp(bat_temperature_volt, vol_cali);
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_BIF_SUPPORT
|
|
/* CHARGING_CMD_GET_BIF_TBAT need fix */
|
|
#endif
|
|
bm_notice("[force_get_tbat] %d,%d,%d,%d,%d,%d r:%d %d %d\n",
|
|
bat_temperature_volt_temp, bat_temperature_volt,
|
|
fg_current_state, fg_current_temp,
|
|
fg_r_value, bat_temperature_val,
|
|
fg_meter_res_value, fg_r_value, gm.no_bat_temp_compensate);
|
|
|
|
if (pre_bat_temperature_val2 == 0) {
|
|
pre_bat_temperature_volt_temp =
|
|
bat_temperature_volt_temp;
|
|
pre_bat_temperature_volt = bat_temperature_volt;
|
|
pre_fg_current_temp = fg_current_temp;
|
|
pre_fg_current_state = fg_current_state;
|
|
pre_fg_r_value = fg_r_value;
|
|
pre_bat_temperature_val2 = bat_temperature_val;
|
|
get_monotonic_boottime(&pre_time);
|
|
} else {
|
|
get_monotonic_boottime(&ctime);
|
|
dtime = timespec_sub(ctime, pre_time);
|
|
|
|
if (((dtime.tv_sec <= 20) &&
|
|
(abs(pre_bat_temperature_val2 -
|
|
bat_temperature_val) >= 50)) ||
|
|
bat_temperature_val >= 580) {
|
|
bm_err(
|
|
"[force_get_tbat][err] current:%d,%d,%d,%d,%d,%d pre:%d,%d,%d,%d,%d,%d\n",
|
|
bat_temperature_volt_temp,
|
|
bat_temperature_volt,
|
|
fg_current_state,
|
|
fg_current_temp,
|
|
fg_r_value,
|
|
bat_temperature_val,
|
|
pre_bat_temperature_volt_temp,
|
|
pre_bat_temperature_volt,
|
|
pre_fg_current_state,
|
|
pre_fg_current_temp,
|
|
pre_fg_r_value,
|
|
pre_bat_temperature_val2);
|
|
/*pmic_auxadc_debug(1);*/
|
|
WARN_ON_ONCE(1);
|
|
}
|
|
|
|
pre_bat_temperature_volt_temp =
|
|
bat_temperature_volt_temp;
|
|
pre_bat_temperature_volt = bat_temperature_volt;
|
|
pre_fg_current_temp = fg_current_temp;
|
|
pre_fg_current_state = fg_current_state;
|
|
pre_fg_r_value = fg_r_value;
|
|
pre_bat_temperature_val2 = bat_temperature_val;
|
|
pre_time = ctime;
|
|
bm_trace(
|
|
"[force_get_tbat] current:%d,%d,%d,%d,%d,%d pre:%d,%d,%d,%d,%d,%d time:%d\n",
|
|
bat_temperature_volt_temp, bat_temperature_volt,
|
|
fg_current_state, fg_current_temp,
|
|
fg_r_value, bat_temperature_val,
|
|
pre_bat_temperature_volt_temp, pre_bat_temperature_volt,
|
|
pre_fg_current_state, pre_fg_current_temp,
|
|
pre_fg_r_value,
|
|
pre_bat_temperature_val2, (int)dtime.tv_sec);
|
|
}
|
|
} else {
|
|
bat_temperature_val = pre_bat_temperature_val;
|
|
}
|
|
|
|
gm.tbat_precise = bat_temperature_val;
|
|
|
|
return bat_temperature_val / 10;
|
|
}
|
|
|
|
int force_get_tbat(bool update)
|
|
{
|
|
int bat_temperature_val = 0;
|
|
int counts = 0;
|
|
|
|
if (is_fg_disabled()) {
|
|
bm_debug("[%s] fixed TBAT=25 t\n",
|
|
__func__);
|
|
gm.tbat_precise = 250;
|
|
return 25;
|
|
}
|
|
|
|
#if defined(FIXED_TBAT_25)
|
|
bm_debug("[%s] fixed TBAT=25 t\n", __func__);
|
|
gm.tbat_precise = 250;
|
|
return 25;
|
|
#else
|
|
|
|
bat_temperature_val = force_get_tbat_internal(update);
|
|
|
|
while (counts < 5 && bat_temperature_val >= 60) {
|
|
bm_err("[%s]over60 count=%d, bat_temp=%d\n",
|
|
__func__,
|
|
counts, bat_temperature_val);
|
|
bat_temperature_val = force_get_tbat_internal(true);
|
|
counts++;
|
|
}
|
|
|
|
if (bat_temperature_val <=
|
|
BATTERY_TMP_TO_DISABLE_GM30 && gm.disableGM30 == false) {
|
|
bm_err(
|
|
"battery temperature is too low %d and disable GM3.0\n",
|
|
bat_temperature_val);
|
|
disable_fg();
|
|
if (gm.disableGM30 == true)
|
|
battery_main.BAT_CAPACITY = 50;
|
|
battery_update(&battery_main);
|
|
}
|
|
|
|
if (bat_temperature_val <= BATTERY_TMP_TO_DISABLE_NAFG) {
|
|
int fgv;
|
|
|
|
fgv = gauge_get_hw_version();
|
|
if (fgv >= GAUGE_HW_V1000
|
|
&& fgv < GAUGE_HW_V2000) {
|
|
en_intr_VBATON_UNDET(0);
|
|
}
|
|
|
|
gm.ntc_disable_nafg = true;
|
|
bm_err("[%s] ntc_disable_nafg %d %d\n",
|
|
__func__,
|
|
bat_temperature_val,
|
|
DEFAULT_BATTERY_TMP_WHEN_DISABLE_NAFG);
|
|
|
|
gm.tbat_precise = DEFAULT_BATTERY_TMP_WHEN_DISABLE_NAFG * 10;
|
|
return DEFAULT_BATTERY_TMP_WHEN_DISABLE_NAFG;
|
|
}
|
|
|
|
gm.ntc_disable_nafg = false;
|
|
bm_debug("[%s] t:%d precise:%d\n", __func__,
|
|
bat_temperature_val, gm.tbat_precise);
|
|
|
|
return bat_temperature_val;
|
|
#endif
|
|
}
|
|
|
|
unsigned int battery_meter_get_fg_time(void)
|
|
{
|
|
unsigned int time = 0;
|
|
|
|
gauge_dev_get_time(gm.gdev, &time);
|
|
return time;
|
|
}
|
|
|
|
unsigned int battery_meter_enable_time_interrupt(unsigned int sec)
|
|
{
|
|
return gauge_dev_enable_time_interrupt(gm.gdev, sec);
|
|
}
|
|
|
|
/* ============================================================ */
|
|
/* Internal function */
|
|
/* ============================================================ */
|
|
void update_fg_dbg_tool_value(void)
|
|
{
|
|
/* Todo: backup variables */
|
|
}
|
|
|
|
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;
|
|
|
|
reply_msg->identity = FGD_NL_MAGIC;
|
|
|
|
if (in_interrupt())
|
|
skb = alloc_skb(len, GFP_ATOMIC);
|
|
else
|
|
skb = alloc_skb(len, GFP_KERNEL);
|
|
|
|
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 */
|
|
|
|
ret = netlink_unicast(gm.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;
|
|
|
|
data = NLMSG_DATA(nlh);
|
|
|
|
fgd_msg = (struct fgd_nl_msg_t *)data;
|
|
|
|
if (IS_ENABLED(CONFIG_POWER_EXT) || gm.disable_mtkbattery ||
|
|
IS_ENABLED(CONFIG_MTK_DISABLE_GAUGE)) {
|
|
bm_err("GM3 disable, nl handler rev data\n");
|
|
return;
|
|
}
|
|
|
|
if (fgd_msg->identity != FGD_NL_MAGIC) {
|
|
bm_err("[FGERR]not correct MTKFG netlink packet!%d\n",
|
|
fgd_msg->identity);
|
|
return;
|
|
}
|
|
|
|
if (gm.g_fgd_pid != pid &&
|
|
fgd_msg->fgd_cmd > FG_DAEMON_CMD_SET_DAEMON_PID) {
|
|
bm_err("drop rev netlink pid:%d:%d cmd:%d:%d\n",
|
|
pid,
|
|
gm.g_fgd_pid,
|
|
fgd_msg->fgd_cmd,
|
|
FG_DAEMON_CMD_SET_DAEMON_PID);
|
|
return;
|
|
}
|
|
|
|
size = fgd_msg->fgd_ret_data_len + FGD_NL_MSG_T_HDR_LEN;
|
|
|
|
if (size > (PAGE_SIZE << 1))
|
|
fgd_ret_msg = vmalloc(size);
|
|
else {
|
|
if (in_interrupt())
|
|
fgd_ret_msg = kmalloc(size, GFP_ATOMIC);
|
|
else
|
|
fgd_ret_msg = kmalloc(size, GFP_KERNEL);
|
|
}
|
|
|
|
if (fgd_ret_msg == NULL) {
|
|
if (size > PAGE_SIZE)
|
|
fgd_ret_msg = vmalloc(size);
|
|
|
|
if (fgd_ret_msg == NULL)
|
|
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);
|
|
|
|
kvfree(fgd_ret_msg);
|
|
}
|
|
|
|
int wakeup_fg_algo(unsigned int flow_state)
|
|
{
|
|
update_fg_dbg_tool_value();
|
|
|
|
if (gm.disableGM30) {
|
|
bm_err("FG daemon is disabled\n");
|
|
return -1;
|
|
}
|
|
|
|
if (is_recovery_mode()) {
|
|
wakeup_fg_algo_recovery(flow_state);
|
|
return 0;
|
|
}
|
|
|
|
zcv_filter_add(&gm.zcvf);
|
|
zcv_filter_dump(&gm.zcvf);
|
|
zcv_check(&gm.zcvf);
|
|
|
|
gm3_log_notify(flow_state);
|
|
|
|
if (gm.g_fgd_pid != 0) {
|
|
struct fgd_nl_msg_t *fgd_msg;
|
|
int size = FGD_NL_MSG_T_HDR_LEN + sizeof(flow_state);
|
|
|
|
if (size > (PAGE_SIZE << 1))
|
|
fgd_msg = vmalloc(size);
|
|
else {
|
|
if (in_interrupt())
|
|
fgd_msg = kmalloc(size, GFP_ATOMIC);
|
|
else
|
|
fgd_msg = kmalloc(size, GFP_KERNEL);
|
|
}
|
|
|
|
if (fgd_msg == NULL) {
|
|
if (size > PAGE_SIZE)
|
|
fgd_msg = vmalloc(size);
|
|
|
|
if (fgd_msg == NULL)
|
|
return -1;
|
|
}
|
|
|
|
bm_debug("[%s] malloc size=%d pid=%d cmd:%d\n",
|
|
__func__,
|
|
size, gm.g_fgd_pid, flow_state);
|
|
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(gm.g_fgd_pid, 0, fgd_msg);
|
|
|
|
kvfree(fgd_msg);
|
|
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int wakeup_fg_algo_cmd(unsigned int flow_state, int cmd, int para1)
|
|
{
|
|
update_fg_dbg_tool_value();
|
|
|
|
if (gm.disableGM30) {
|
|
bm_err("FG daemon is disabled\n");
|
|
return -1;
|
|
}
|
|
|
|
if (is_recovery_mode()) {
|
|
wakeup_fg_algo_recovery(flow_state);
|
|
return 0;
|
|
}
|
|
|
|
gm3_log_notify(flow_state);
|
|
|
|
if (gm.g_fgd_pid != 0) {
|
|
struct fgd_nl_msg_t *fgd_msg;
|
|
int size = FGD_NL_MSG_T_HDR_LEN + sizeof(flow_state);
|
|
|
|
if (size > (PAGE_SIZE << 1))
|
|
fgd_msg = vmalloc(size);
|
|
else {
|
|
if (in_interrupt())
|
|
fgd_msg = kmalloc(size, GFP_ATOMIC);
|
|
else
|
|
fgd_msg = kmalloc(size, GFP_KERNEL);
|
|
|
|
}
|
|
|
|
if (fgd_msg == NULL) {
|
|
if (size > PAGE_SIZE)
|
|
fgd_msg = vmalloc(size);
|
|
|
|
if (fgd_msg == NULL)
|
|
return -1;
|
|
}
|
|
|
|
bm_debug(
|
|
"[wakeup_fg_algo] malloc size=%d pid=%d cmd:%d\n",
|
|
size, gm.g_fgd_pid, flow_state);
|
|
memset(fgd_msg, 0, size);
|
|
fgd_msg->fgd_cmd = FG_DAEMON_CMD_NOTIFY_DAEMON;
|
|
fgd_msg->fgd_subcmd = cmd;
|
|
fgd_msg->fgd_subcmd_para1 = para1;
|
|
memcpy(fgd_msg->fgd_data, &flow_state, sizeof(flow_state));
|
|
fgd_msg->fgd_data_len += sizeof(flow_state);
|
|
nl_send_to_user(gm.g_fgd_pid, 0, fgd_msg);
|
|
|
|
kvfree(fgd_msg);
|
|
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int wakeup_fg_algo_atomic(unsigned int flow_state)
|
|
{
|
|
update_fg_dbg_tool_value();
|
|
|
|
if (gm.disableGM30) {
|
|
bm_err("FG daemon is disabled\n");
|
|
return -1;
|
|
}
|
|
|
|
if (is_recovery_mode()) {
|
|
wakeup_fg_algo_recovery(flow_state);
|
|
return 0;
|
|
}
|
|
|
|
gm3_log_notify(flow_state);
|
|
|
|
if (gm.g_fgd_pid != 0) {
|
|
struct fgd_nl_msg_t *fgd_msg;
|
|
int size = FGD_NL_MSG_T_HDR_LEN + sizeof(flow_state);
|
|
|
|
if (in_interrupt())
|
|
fgd_msg = kmalloc(size, GFP_ATOMIC);
|
|
else
|
|
fgd_msg = kmalloc(size, GFP_KERNEL);
|
|
|
|
if (!fgd_msg) {
|
|
/* bm_err("Error: wakeup_fg_algo() vmalloc fail!!!\n"); */
|
|
return -1;
|
|
}
|
|
|
|
bm_debug(
|
|
"[wakeup_fg_algo] malloc size=%d pid=%d cmd:%d\n",
|
|
size, gm.g_fgd_pid, flow_state);
|
|
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(gm.g_fgd_pid, 0, fgd_msg);
|
|
kfree(fgd_msg);
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
int fg_get_battery_temperature_for_zcv(void)
|
|
{
|
|
return battery_main.BAT_batt_temp;
|
|
}
|
|
|
|
int battery_get_charger_zcv(void)
|
|
{
|
|
u32 zcv = 0;
|
|
|
|
charger_manager_get_zcv(gm.pbat_consumer, MAIN_CHARGER, &zcv);
|
|
return zcv;
|
|
}
|
|
|
|
void battery_set_charger_constant_voltage(u32 cv)
|
|
{
|
|
charger_manager_set_constant_voltage(gm.pbat_consumer, MAIN_CHARGER, cv);
|
|
}
|
|
|
|
void fg_ocv_query_soc(int ocv)
|
|
{
|
|
if (ocv > 50000 || ocv <= 0)
|
|
return;
|
|
|
|
gm.algo_req_ocv = ocv;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD, FG_KERNEL_CMD_REQ_ALGO_DATA,
|
|
ocv);
|
|
|
|
bm_trace("[%s] ocv:%d\n",
|
|
__func__, ocv);
|
|
}
|
|
|
|
void fg_test_ag_cmd(int cmd)
|
|
{
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD, FG_KERNEL_CMD_AG_LOG_TEST, cmd);
|
|
|
|
bm_err("[%s]FG_KERNEL_CMD_AG_LOG_TEST:%d\n",
|
|
__func__, cmd);
|
|
}
|
|
|
|
void exec_BAT_EC(int cmd, int param)
|
|
{
|
|
int i;
|
|
|
|
bm_err("exe_BAT_EC cmd %d, param %d\n", cmd, param);
|
|
switch (cmd) {
|
|
case 101:
|
|
{
|
|
/* Force Temperature, force_get_tbat*/
|
|
if (param == 0xff) {
|
|
get_ec()->fixed_temp_en = 0;
|
|
get_ec()->fixed_temp_value = 25;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->fixed_temp_en = 1;
|
|
if (param >= 100)
|
|
get_ec()->fixed_temp_value =
|
|
0 - (param - 100);
|
|
else
|
|
get_ec()->fixed_temp_value = param;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 102:
|
|
{
|
|
/* force PTIM RAC */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_rac_en = 0;
|
|
get_ec()->debug_rac_value = 0;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_rac_en = 1;
|
|
get_ec()->debug_rac_value = param;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 103:
|
|
{
|
|
/* force PTIM V */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_ptim_v_en = 0;
|
|
get_ec()->debug_ptim_v_value = 0;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_ptim_v_en = 1;
|
|
get_ec()->debug_ptim_v_value = param;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case 104:
|
|
{
|
|
/* force PTIM R_current */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_ptim_r_en = 0;
|
|
get_ec()->debug_ptim_r_value = 0;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_ptim_r_en = 1;
|
|
get_ec()->debug_ptim_r_value = param;
|
|
bm_err("exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 105:
|
|
{
|
|
/* force interrupt trigger */
|
|
switch (param) {
|
|
case 1:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_TIMER_UPDATE);
|
|
}
|
|
break;
|
|
case 4096:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_NAG_C_DLTV);
|
|
}
|
|
break;
|
|
case 8192:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_FG_ZCV);
|
|
}
|
|
break;
|
|
case 32768:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_RESET_NVRAM);
|
|
}
|
|
break;
|
|
case 65536:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_BAT_PLUGOUT);
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
{
|
|
|
|
}
|
|
break;
|
|
}
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, force interrupt\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 106:
|
|
{
|
|
/* force FG Current */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_fg_curr_en = 0;
|
|
get_ec()->debug_fg_curr_value = 0;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_fg_curr_en = 1;
|
|
get_ec()->debug_fg_curr_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 107:
|
|
{
|
|
/* force Battery ID */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_bat_id_en = 0;
|
|
get_ec()->debug_bat_id_value = 0;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
} else {
|
|
get_ec()->debug_bat_id_en = 1;
|
|
get_ec()->debug_bat_id_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
fg_custom_init_from_header();
|
|
}
|
|
}
|
|
break;
|
|
case 108:
|
|
{
|
|
/* Set D0_C_CUST */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_d0_c_en = 0;
|
|
get_ec()->debug_d0_c_value = 0;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_d0_c_en = 1;
|
|
get_ec()->debug_d0_c_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 109:
|
|
{
|
|
/* Set D0_V_CUST */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_d0_v_en = 0;
|
|
get_ec()->debug_d0_v_value = 0;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_d0_v_en = 1;
|
|
get_ec()->debug_d0_v_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 110:
|
|
{
|
|
/* Set UISOC_CUST */
|
|
if (param == 0xff) {
|
|
get_ec()->debug_uisoc_en = 0;
|
|
get_ec()->debug_uisoc_value = 0;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, disable\n",
|
|
cmd, param);
|
|
|
|
} else {
|
|
get_ec()->debug_uisoc_en = 1;
|
|
get_ec()->debug_uisoc_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, enable\n",
|
|
cmd, param);
|
|
}
|
|
}
|
|
break;
|
|
case 600:
|
|
{
|
|
fg_cust_data.aging_diff_max_threshold = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, aging_diff_max_threshold:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 601:
|
|
{
|
|
fg_cust_data.aging_diff_max_level = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, aging_diff_max_level:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 602:
|
|
{
|
|
fg_cust_data.aging_factor_t_min = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, aging_factor_t_min:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 603:
|
|
{
|
|
fg_cust_data.cycle_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, cycle_diff:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 604:
|
|
{
|
|
fg_cust_data.aging_count_min = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, aging_count_min:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 605:
|
|
{
|
|
fg_cust_data.default_score = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, default_score:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 606:
|
|
{
|
|
fg_cust_data.default_score_quantity = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, default_score_quantity:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 607:
|
|
{
|
|
fg_cust_data.fast_cycle_set = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fast_cycle_set:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 608:
|
|
{
|
|
fg_cust_data.level_max_change_bat = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, level_max_change_bat:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 609:
|
|
{
|
|
fg_cust_data.diff_max_change_bat = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, diff_max_change_bat:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 610:
|
|
{
|
|
fg_cust_data.aging_tracking_start = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, aging_tracking_start:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 611:
|
|
{
|
|
fg_cust_data.max_aging_data = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, max_aging_data:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 612:
|
|
{
|
|
fg_cust_data.max_fast_data = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, max_fast_data:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 613:
|
|
{
|
|
fg_cust_data.fast_data_threshold_score = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fast_data_threshold_score:%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 614:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,FG_KERNEL_CMD_AG_LOG_TEST=%d\n",
|
|
cmd, param);
|
|
|
|
fg_test_ag_cmd(99);
|
|
|
|
}
|
|
break;
|
|
case 701:
|
|
{
|
|
fg_cust_data.pseudo1_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, pseudo1_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 702:
|
|
{
|
|
fg_cust_data.pseudo100_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, pseudo100_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 703:
|
|
{
|
|
fg_cust_data.qmax_sel = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, qmax_sel\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 704:
|
|
{
|
|
fg_cust_data.iboot_sel = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, iboot_sel\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 705:
|
|
{
|
|
for (i = 0;
|
|
i < fg_table_cust_data.active_table_number;
|
|
i++) {
|
|
fg_table_cust_data.fg_profile[i].pmic_min_vol =
|
|
param * UNIT_TRANS_10;
|
|
}
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, pmic_min_vol\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 706:
|
|
{
|
|
for (i = 0;
|
|
i < fg_table_cust_data.active_table_number;
|
|
i++) {
|
|
fg_table_cust_data.fg_profile[i].pon_iboot =
|
|
param * UNIT_TRANS_10;
|
|
}
|
|
bm_err("exe_BAT_EC cmd %d, param %d, poweron_system_iboot\n"
|
|
, cmd, param * UNIT_TRANS_10);
|
|
}
|
|
break;
|
|
case 707:
|
|
{
|
|
fg_cust_data.shutdown_system_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, shutdown_system_iboot\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 708:
|
|
{
|
|
fg_cust_data.com_fg_meter_resistance = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, com_fg_meter_resistance\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 709:
|
|
{
|
|
fg_cust_data.r_fg_value = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, r_fg_value\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 710:
|
|
{
|
|
fg_cust_data.q_max_sys_voltage = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, q_max_sys_voltage\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 711:
|
|
{
|
|
fg_cust_data.loading_1_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, loading_1_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 712:
|
|
{
|
|
fg_cust_data.loading_2_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, loading_2_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 713:
|
|
{
|
|
fg_cust_data.aging_temp_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, aging_temp_diff\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 714:
|
|
{
|
|
fg_cust_data.aging1_load_soc = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, aging1_load_soc\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 715:
|
|
{
|
|
fg_cust_data.aging1_update_soc = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, aging1_update_soc\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 716:
|
|
{
|
|
fg_cust_data.aging_100_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, aging_100_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 717:
|
|
{
|
|
fg_table_cust_data.active_table_number = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, additional_battery_table_en\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 718:
|
|
{
|
|
fg_cust_data.d0_sel = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, d0_sel\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 719:
|
|
{
|
|
fg_cust_data.zcv_car_gap_percentage = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, zcv_car_gap_percentage\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 720:
|
|
{
|
|
fg_cust_data.multi_temp_gauge0 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.multi_temp_gauge0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 721:
|
|
{
|
|
fg_custom_data_check();
|
|
bm_err("exe_BAT_EC cmd %d", cmd);
|
|
}
|
|
break;
|
|
case 724:
|
|
{
|
|
fg_table_cust_data.fg_profile[0].pseudo100 =
|
|
UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pseudo100_t0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 725:
|
|
{
|
|
fg_table_cust_data.fg_profile[1].pseudo100 =
|
|
UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pseudo100_t1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 726:
|
|
{
|
|
fg_table_cust_data.fg_profile[2].pseudo100 =
|
|
UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pseudo100_t2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 727:
|
|
{
|
|
fg_table_cust_data.fg_profile[3].pseudo100 =
|
|
UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pseudo100_t3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 728:
|
|
{
|
|
fg_table_cust_data.fg_profile[4].pseudo100 =
|
|
UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pseudo100_t4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 729:
|
|
{
|
|
fg_cust_data.keep_100_percent = UNIT_TRANS_100 * param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.keep_100_percent=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 730:
|
|
{
|
|
fg_cust_data.ui_full_limit_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_en=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 731:
|
|
{
|
|
fg_cust_data.ui_full_limit_soc0 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_soc0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 732:
|
|
{
|
|
fg_cust_data.ui_full_limit_ith0 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_ith0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 733:
|
|
{
|
|
fg_cust_data.ui_full_limit_soc1 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_soc1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 734:
|
|
{
|
|
fg_cust_data.ui_full_limit_ith1 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_ith1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 735:
|
|
{
|
|
fg_cust_data.ui_full_limit_soc2 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_soc2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 736:
|
|
{
|
|
fg_cust_data.ui_full_limit_ith2 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_ith2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 737:
|
|
{
|
|
fg_cust_data.ui_full_limit_soc3 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_soc3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 738:
|
|
{
|
|
fg_cust_data.ui_full_limit_ith3 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_ith3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 739:
|
|
{
|
|
fg_cust_data.ui_full_limit_soc4 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_soc4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 740:
|
|
{
|
|
fg_cust_data.ui_full_limit_ith4 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_ith4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 741:
|
|
{
|
|
fg_cust_data.ui_full_limit_time = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.ui_full_limit_time=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 743:
|
|
{
|
|
fg_table_cust_data.fg_profile[0].pmic_min_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pmic_min_vol_t0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 744:
|
|
{
|
|
fg_table_cust_data.fg_profile[1].pmic_min_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pmic_min_vol_t1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 745:
|
|
{
|
|
fg_table_cust_data.fg_profile[2].pmic_min_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pmic_min_vol_t2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 746:
|
|
{
|
|
fg_table_cust_data.fg_profile[3].pmic_min_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pmic_min_vol_t3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 747:
|
|
{
|
|
fg_table_cust_data.fg_profile[4].pmic_min_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pmic_min_vol_t4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 748:
|
|
{
|
|
fg_table_cust_data.fg_profile[0].pon_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pon_iboot_t0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 749:
|
|
{
|
|
fg_table_cust_data.fg_profile[1].pon_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pon_iboot_t1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 750:
|
|
{
|
|
fg_table_cust_data.fg_profile[2].pon_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pon_iboot_t2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 751:
|
|
{
|
|
fg_table_cust_data.fg_profile[3].pon_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pon_iboot_t3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 752:
|
|
{
|
|
fg_table_cust_data.fg_profile[4].pon_iboot = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.pon_iboot_t4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 753:
|
|
{
|
|
fg_table_cust_data.fg_profile[0].qmax_sys_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.qmax_sys_vol_t0=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 754:
|
|
{
|
|
fg_table_cust_data.fg_profile[1].qmax_sys_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.qmax_sys_vol_t1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 755:
|
|
{
|
|
fg_table_cust_data.fg_profile[2].qmax_sys_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.qmax_sys_vol_t2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 756:
|
|
{
|
|
fg_table_cust_data.fg_profile[3].qmax_sys_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.qmax_sys_vol_t3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 757:
|
|
{
|
|
fg_table_cust_data.fg_profile[4].qmax_sys_vol = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.qmax_sys_vol_t4=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 758:
|
|
{
|
|
fg_cust_data.nafg_ratio = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.nafg_ratio=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 759:
|
|
{
|
|
fg_cust_data.nafg_ratio_en = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.nafg_ratio_en=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 760:
|
|
{
|
|
fg_cust_data.nafg_ratio_tmp_thr = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.nafg_ratio_tmp_thr=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 761:
|
|
{
|
|
wakeup_fg_algo(FG_INTR_BAT_CYCLE);
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, bat_cycle intr\n", cmd);
|
|
}
|
|
break;
|
|
case 762:
|
|
{
|
|
fg_cust_data.difference_fgc_fgv_th1 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fgc_fgv_th1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 763:
|
|
{
|
|
fg_cust_data.difference_fgc_fgv_th2 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fgc_fgv_th1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 764:
|
|
{
|
|
fg_cust_data.difference_fgc_fgv_th3 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fgc_fgv_th3=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 765:
|
|
{
|
|
fg_cust_data.difference_fullocv_ith = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fullocv_ith=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 766:
|
|
{
|
|
fg_cust_data.difference_fgc_fgv_th_soc1 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fgc_fgv_th_soc1=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 767:
|
|
{
|
|
fg_cust_data.difference_fgc_fgv_th_soc2 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.difference_fgc_fgv_th_soc2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 768:
|
|
{
|
|
fg_cust_data.embedded_sel = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.embedded_sel=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 769:
|
|
{
|
|
fg_cust_data.car_tune_value = param * UNIT_TRANS_10;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.car_tune_value=%d\n",
|
|
cmd, param * UNIT_TRANS_10);
|
|
}
|
|
break;
|
|
case 770:
|
|
{
|
|
fg_cust_data.shutdown_1_time = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.shutdown_1_time=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 771:
|
|
{
|
|
fg_cust_data.tnew_told_pon_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.tnew_told_pon_diff=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 772:
|
|
{
|
|
fg_cust_data.tnew_told_pon_diff2 = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.tnew_told_pon_diff2=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 773:
|
|
{
|
|
fg_cust_data.swocv_oldocv_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.swocv_oldocv_diff=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 774:
|
|
{
|
|
fg_cust_data.hwocv_oldocv_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.hwocv_oldocv_diff=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 775:
|
|
{
|
|
fg_cust_data.hwocv_swocv_diff = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, fg_cust_data.hwocv_swocv_diff=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 776:
|
|
{
|
|
get_ec()->debug_kill_daemontest = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, debug_kill_daemontest=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 777:
|
|
{
|
|
fg_cust_data.swocv_oldocv_diff_emb = param;
|
|
bm_err("exe_BAT_EC cmd %d, swocv_oldocv_diff_emb=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 778:
|
|
{
|
|
fg_cust_data.vir_oldocv_diff_emb_lt = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, vir_oldocv_diff_emb_lt=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 779:
|
|
{
|
|
fg_cust_data.vir_oldocv_diff_emb_tmp = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, vir_oldocv_diff_emb_tmp=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 780:
|
|
{
|
|
fg_cust_data.vir_oldocv_diff_emb = param;
|
|
bm_err("exe_BAT_EC cmd %d, vir_oldocv_diff_emb=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 781:
|
|
{
|
|
get_ec()->debug_kill_daemontest = 1;
|
|
fg_cust_data.dod_init_sel = 12;
|
|
bm_err("exe_BAT_EC cmd %d,force goto dod_init12=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 782:
|
|
{
|
|
fg_cust_data.charge_pseudo_full_level = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,fg_cust_data.charge_pseudo_full_level=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 783:
|
|
{
|
|
fg_cust_data.full_tracking_bat_int2_multiply = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,fg_cust_data.full_tracking_bat_int2_multiply=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 784:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,DAEMON_PID=%d\n",
|
|
cmd, gm.g_fgd_pid);
|
|
}
|
|
break;
|
|
case 785:
|
|
{
|
|
gm.bat_cycle_thr = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,thr=%d\n",
|
|
cmd, gm.bat_cycle_thr);
|
|
}
|
|
break;
|
|
case 786:
|
|
{
|
|
gm.bat_cycle_ncar = param;
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,thr=%d\n",
|
|
cmd, gm.bat_cycle_ncar);
|
|
}
|
|
break;
|
|
case 787:
|
|
{
|
|
fg_ocv_query_soc(param);
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,[fg_ocv_query_soc]ocv=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 788:
|
|
{
|
|
fg_cust_data.record_log = param;
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,record_log=%d\n",
|
|
cmd, fg_cust_data.record_log);
|
|
}
|
|
break;
|
|
case 789:
|
|
{
|
|
int zcv_avg_current = 0;
|
|
|
|
zcv_avg_current = param;
|
|
gauge_set_zcv_interrupt_en(0);
|
|
gauge_dev_set_zcv_interrupt_threshold(gm.gdev,
|
|
zcv_avg_current);
|
|
gauge_set_zcv_interrupt_en(1);
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,zcv_avg_current =%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 790:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,force DLPT shutdown", cmd);
|
|
|
|
notify_fg_dlpt_sd();
|
|
}
|
|
break;
|
|
case 791:
|
|
{
|
|
gm.enable_tmp_intr_suspend = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,gm.enable_tmp_intr_suspend =%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 792:
|
|
{
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_BUILD_SEL_BATTEMP,
|
|
param);
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,req bat table temp =%d\n",
|
|
cmd, param);
|
|
|
|
}
|
|
break;
|
|
case 793:
|
|
{
|
|
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_UPDATE_AVG_BATTEMP,
|
|
param);
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,update mavg temp\n",
|
|
cmd);
|
|
|
|
}
|
|
break;
|
|
case 794:
|
|
{
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_SAVE_DEBUG_PARAM,
|
|
param);
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,FG_KERNEL_CMD_SAVE_DEBUG_PARAM\n",
|
|
cmd);
|
|
}
|
|
break;
|
|
case 795:
|
|
{
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_REQ_CHANGE_AGING_DATA,
|
|
param * 100);
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,change aging to=%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 796:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,FG_KERNEL_CMD_AG_LOG_TEST=%d\n",
|
|
cmd, param);
|
|
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_AG_LOG_TEST, param);
|
|
}
|
|
break;
|
|
case 797:
|
|
{
|
|
gm.soc_decimal_rate = param;
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,soc_decimal_rate=%d\n",
|
|
cmd, param);
|
|
|
|
}
|
|
break;
|
|
case 798:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,FG_KERNEL_CMD_CHG_DECIMAL_RATE=%d\n",
|
|
cmd, param);
|
|
|
|
gm.soc_decimal_rate = param;
|
|
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_CHG_DECIMAL_RATE, param);
|
|
}
|
|
break;
|
|
case 799:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, Send INTR_CHR_FULL to daemon, force_full =%d\n",
|
|
cmd, param);
|
|
|
|
gm.is_force_full = param;
|
|
wakeup_fg_algo(FG_INTR_CHR_FULL);
|
|
}
|
|
break;
|
|
case 800:
|
|
{
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, charge_power_sel =%d\n",
|
|
cmd, param);
|
|
|
|
set_charge_power_sel(param);
|
|
}
|
|
break;
|
|
case 801:
|
|
{
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, charge_power_sel =%d\n",
|
|
cmd, param);
|
|
|
|
dump_pseudo100(param);
|
|
}
|
|
break;
|
|
case 802:
|
|
{
|
|
fg_cust_data.zcv_com_vol_limit = param;
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,zcv_com_vol_limit =%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
case 803:
|
|
{
|
|
fg_cust_data.sleep_current_avg = param;
|
|
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d,sleep_current_avg =%d\n",
|
|
cmd, param);
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
bm_err(
|
|
"exe_BAT_EC cmd %d, param %d, default\n",
|
|
cmd, param);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static ssize_t show_FG_daemon_disable(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG] show FG disable : %d\n", gm.disableGM30);
|
|
return sprintf(buf, "%d\n", gm.disableGM30);
|
|
}
|
|
|
|
static ssize_t store_FG_daemon_disable(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
bm_err("[disable FG daemon]\n");
|
|
disable_fg();
|
|
if (gm.disableGM30 == true)
|
|
battery_main.BAT_CAPACITY = 50;
|
|
battery_update(&battery_main);
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(
|
|
FG_daemon_disable, 0664,
|
|
show_FG_daemon_disable, store_FG_daemon_disable);
|
|
|
|
static ssize_t show_FG_meter_resistance(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace(
|
|
"[FG] show com_fg_meter_resistance : %d\n",
|
|
fg_cust_data.com_fg_meter_resistance);
|
|
return sprintf(buf, "%d\n", fg_cust_data.com_fg_meter_resistance);
|
|
}
|
|
|
|
static ssize_t store_FG_meter_resistance(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
} else
|
|
fg_cust_data.com_fg_meter_resistance = val;
|
|
|
|
bm_err(
|
|
"[%s] com FG_meter_resistance = %d\n",
|
|
__func__,
|
|
(int)val);
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
static DEVICE_ATTR(
|
|
FG_meter_resistance, 0664,
|
|
show_FG_meter_resistance, store_FG_meter_resistance);
|
|
|
|
static ssize_t show_FG_nafg_disable(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG] show nafg disable : %d\n", gm.cmd_disable_nafg);
|
|
return sprintf(buf, "%d\n", gm.cmd_disable_nafg);
|
|
}
|
|
|
|
static ssize_t store_FG_nafg_disable(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
|
|
if (val == 0)
|
|
gm.cmd_disable_nafg = false;
|
|
else
|
|
gm.cmd_disable_nafg = true;
|
|
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD, FG_KERNEL_CMD_DISABLE_NAFG, val);
|
|
|
|
bm_err(
|
|
"[%s] FG_nafg_disable = %d\n",
|
|
__func__,
|
|
(int)val);
|
|
}
|
|
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(
|
|
disable_nafg, 0664,
|
|
show_FG_nafg_disable, store_FG_nafg_disable);
|
|
|
|
static ssize_t show_FG_ntc_disable_nafg(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG]%s: %d\n", __func__, gm.ntc_disable_nafg);
|
|
return sprintf(buf, "%d\n", gm.ntc_disable_nafg);
|
|
}
|
|
|
|
static ssize_t store_FG_ntc_disable_nafg(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n", __func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n", __func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
|
|
if (val == 0) {
|
|
gm.ntc_disable_nafg = false;
|
|
get_ec()->fixed_temp_en = 0;
|
|
get_ec()->fixed_temp_value = 25;
|
|
} else if (val == 1) {
|
|
get_ec()->fixed_temp_en = 1;
|
|
get_ec()->fixed_temp_value =
|
|
BATTERY_TMP_TO_DISABLE_NAFG;
|
|
gm.ntc_disable_nafg = true;
|
|
wakeup_fg_algo(FG_INTR_NAG_C_DLTV);
|
|
}
|
|
|
|
bm_err(
|
|
"[%s]val=%d, temp:%d %d, %d\n",
|
|
__func__,
|
|
(int)val,
|
|
get_ec()->fixed_temp_en,
|
|
get_ec()->fixed_temp_value,
|
|
gm.ntc_disable_nafg);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(
|
|
ntc_disable_nafg, 0664,
|
|
show_FG_ntc_disable_nafg, store_FG_ntc_disable_nafg);
|
|
|
|
|
|
static ssize_t show_uisoc_update_type(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG] %s : %d\n",
|
|
__func__,
|
|
fg_cust_data.uisoc_update_type);
|
|
return sprintf(buf, "%d\n", fg_cust_data.uisoc_update_type);
|
|
}
|
|
|
|
static ssize_t store_uisoc_update_type(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
|
|
if (val >= 0 && val <= 2) {
|
|
fg_cust_data.uisoc_update_type = val;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_UISOC_UPDATE_TYPE,
|
|
val);
|
|
bm_err(
|
|
"[%s] type = %d\n",
|
|
__func__,
|
|
(int)val);
|
|
} else
|
|
bm_err(
|
|
"[%s] invalid type:%d\n",
|
|
__func__,
|
|
(int)val);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(uisoc_update_type, 0664,
|
|
show_uisoc_update_type, store_uisoc_update_type);
|
|
|
|
static ssize_t show_FG_daemon_log_level(
|
|
struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
static int loglevel_count;
|
|
|
|
loglevel_count++;
|
|
if (loglevel_count % 5 == 0)
|
|
bm_err(
|
|
"[FG] show FG_daemon_log_level : %d\n",
|
|
fg_cust_data.daemon_log_level);
|
|
|
|
return sprintf(buf, "%d\n", fg_cust_data.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_err("[FG_daemon_log_level]\n");
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[FG_daemon_log_level] buf is %s\n", buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[FG_daemon_log_level] val is %d ??\n",
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
|
|
if (val < 10 && val >= 0) {
|
|
fg_cust_data.daemon_log_level = val;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_CHANG_LOGLEVEL,
|
|
val
|
|
);
|
|
|
|
gm.d_log_level = val;
|
|
gm.log_level = val;
|
|
}
|
|
if (val >= 7)
|
|
gauge_coulomb_set_log_level(3);
|
|
else
|
|
gauge_coulomb_set_log_level(0);
|
|
|
|
bm_err(
|
|
"[FG_daemon_log_level]fg_cust_data.daemon_log_level=%d\n",
|
|
fg_cust_data.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_shutdown_cond_enable(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace(
|
|
"[FG] %s : %d\n",
|
|
__func__,
|
|
get_shutdown_cond_flag());
|
|
return sprintf(buf, "%d\n", get_shutdown_cond_flag());
|
|
}
|
|
|
|
static ssize_t store_shutdown_cond_enable(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
|
|
set_shutdown_cond_flag(val);
|
|
|
|
bm_err(
|
|
"[%s] shutdown_cond_enabled=%d\n",
|
|
__func__,
|
|
get_shutdown_cond_flag());
|
|
}
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(
|
|
shutdown_condition_enable, 0664,
|
|
show_shutdown_cond_enable, store_shutdown_cond_enable);
|
|
|
|
static ssize_t show_reset_battery_cycle(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG] %s : %d\n",
|
|
__func__,
|
|
gm.is_reset_battery_cycle);
|
|
return sprintf(buf, "%d\n", gm.is_reset_battery_cycle);
|
|
}
|
|
|
|
static ssize_t store_reset_battery_cycle(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
if (val == 0)
|
|
gm.is_reset_battery_cycle = false;
|
|
else {
|
|
gm.is_reset_battery_cycle = true;
|
|
wakeup_fg_algo(FG_INTR_BAT_CYCLE);
|
|
}
|
|
bm_err(
|
|
"%s=%d\n",
|
|
__func__,
|
|
gm.is_reset_battery_cycle);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(
|
|
reset_battery_cycle, 0664,
|
|
show_reset_battery_cycle, store_reset_battery_cycle);
|
|
|
|
static ssize_t show_reset_aging_factor(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_trace("[FG] %s : %d\n",
|
|
__func__,
|
|
gm.is_reset_aging_factor);
|
|
return sprintf(buf, "%d\n", gm.is_reset_aging_factor);
|
|
}
|
|
|
|
static ssize_t store_reset_aging_factor(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
unsigned long val = 0;
|
|
int ret;
|
|
|
|
bm_err("[%s]\n", __func__);
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("[%s] buf is %s\n",
|
|
__func__, buf);
|
|
ret = kstrtoul(buf, 10, &val);
|
|
if (val < 0) {
|
|
bm_err(
|
|
"[%s] val is %d ??\n",
|
|
__func__,
|
|
(int)val);
|
|
val = 0;
|
|
}
|
|
if (val == 0)
|
|
gm.is_reset_aging_factor = false;
|
|
else if (val == 1) {
|
|
gm.is_reset_aging_factor = true;
|
|
wakeup_fg_algo_cmd(FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_RESET_AGING_FACTOR, 0);
|
|
}
|
|
bm_err(
|
|
"%s=%d\n",
|
|
__func__,
|
|
gm.is_reset_aging_factor);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(
|
|
reset_aging_factor, 0664,
|
|
show_reset_aging_factor, store_reset_aging_factor);
|
|
|
|
|
|
static ssize_t show_BAT_EC(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_err("%s\n", __func__);
|
|
|
|
return sprintf(buf, "%d:%d\n", gm.BAT_EC_cmd, gm.BAT_EC_param);
|
|
}
|
|
|
|
static ssize_t store_BAT_EC(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
int ret1 = 0, ret2 = 0;
|
|
char cmd_buf[4], param_buf[16];
|
|
|
|
bm_err("%s\n", __func__);
|
|
cmd_buf[3] = '\0';
|
|
param_buf[15] = '\0';
|
|
|
|
if (size < 4 || size > 20) {
|
|
bm_err("%s error, size mismatch\n",
|
|
__func__);
|
|
return -1;
|
|
}
|
|
|
|
if (buf != NULL && size != 0) {
|
|
bm_err("buf is %s\n", buf);
|
|
cmd_buf[0] = buf[0];
|
|
cmd_buf[1] = buf[1];
|
|
cmd_buf[2] = buf[2];
|
|
cmd_buf[3] = '\0';
|
|
|
|
if ((size - 4) > 0) {
|
|
strncpy(param_buf, buf + 4, size - 4);
|
|
param_buf[size - 4 - 1] = '\0';
|
|
bm_err("[FG_IT]cmd_buf %s, param_buf %s\n",
|
|
cmd_buf, param_buf);
|
|
ret2 = kstrtouint(param_buf, 10, &gm.BAT_EC_param);
|
|
}
|
|
|
|
ret1 = kstrtouint(cmd_buf, 10, &gm.BAT_EC_cmd);
|
|
|
|
if (ret1 != 0 || ret2 != 0) {
|
|
bm_err("ERROR! not valid number! %d %d\n",
|
|
ret1, ret2);
|
|
return -1;
|
|
}
|
|
bm_err("CMD is:%d, param:%d\n",
|
|
gm.BAT_EC_cmd, gm.BAT_EC_param);
|
|
}
|
|
|
|
|
|
exec_BAT_EC(gm.BAT_EC_cmd, gm.BAT_EC_param);
|
|
|
|
return size;
|
|
}
|
|
static DEVICE_ATTR(BAT_EC, 0664, show_BAT_EC, store_BAT_EC);
|
|
|
|
|
|
|
|
static ssize_t show_BAT_HEALTH(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
bm_err("%s\n", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static ssize_t store_BAT_HEALTH(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
char copy_str[7], buf_str[350];
|
|
char *s = buf_str, *pch;
|
|
/* char *ori = buf_str; */
|
|
int chr_size = 0;
|
|
int i = 0, j = 0, count = 0, value[50];
|
|
|
|
|
|
bm_err("%s, size =%d, str=%s\n", __func__, size, buf);
|
|
|
|
if (size < 90 || size > 350) {
|
|
bm_err("%s error, size mismatch\n", __func__);
|
|
return -1;
|
|
} else {
|
|
for (i = 0; i < strlen(buf); i++) {
|
|
if (buf[i] == ',')
|
|
j++;
|
|
}
|
|
if (j != 46) {
|
|
bm_err("%s error, invalid input\n", __func__);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
strncpy(buf_str, buf, size);
|
|
/* bm_err("%s, copy str=%s\n", __func__, buf_str); */
|
|
|
|
if (buf != NULL && size != 0) {
|
|
|
|
pch = strchr(s, ',');
|
|
while (pch != NULL) {
|
|
memset(copy_str, 0, 7);
|
|
copy_str[6] = '\0';
|
|
|
|
chr_size = pch - s;
|
|
if (count == 0)
|
|
strncpy(copy_str, s, chr_size);
|
|
else
|
|
strncpy(copy_str, s+1, chr_size-1);
|
|
|
|
kstrtoint(copy_str, 10, &value[count]);
|
|
/* bm_err("::%s::count:%d,%d\n", copy_str, count, value[count]); */
|
|
s = pch;
|
|
pch = strchr(pch + 1, ',');
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count == 46) {
|
|
for (i = 0; i < 43; i++)
|
|
gm.bh_data.data[i] = value[i];
|
|
|
|
for (i = 0; i < 3; i++)
|
|
gm.bh_data.times[i].tv_sec = value[i+43];
|
|
|
|
bm_err("%s count=%d,serial=%d,source=%d,42:%d, value43:[%d, %ld],value45[%d %ld]\n",
|
|
__func__,
|
|
count, gm.bh_data.data[0], gm.bh_data.data[1],
|
|
gm.bh_data.data[42],
|
|
value[43], gm.bh_data.times[0].tv_sec,
|
|
value[45], gm.bh_data.times[2].tv_sec);
|
|
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_SEND_BH_DATA, 0);
|
|
|
|
mdelay(4);
|
|
bm_err("%s wakeup DONE~~~\n", __func__);
|
|
} else
|
|
bm_err("%s count=%d, number not match\n", __func__, count);
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
static DEVICE_ATTR(BAT_HEALTH, 0664, show_BAT_HEALTH, store_BAT_HEALTH);
|
|
|
|
static ssize_t show_FG_Battery_CurrentConsumption(
|
|
struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
int ret_value = 8888;
|
|
|
|
ret_value = battery_get_bat_avg_current();
|
|
bm_err("[EM] FG_Battery_CurrentConsumption : %d .1mA\n", ret_value);
|
|
return sprintf(buf, "%d\n", ret_value);
|
|
}
|
|
|
|
static ssize_t store_FG_Battery_CurrentConsumption(struct device *dev,
|
|
struct device_attribute *attr, const char *buf,
|
|
size_t size)
|
|
{
|
|
bm_err("[EM] Not Support Write Function\n");
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(
|
|
FG_Battery_CurrentConsumption, 0664, show_FG_Battery_CurrentConsumption,
|
|
store_FG_Battery_CurrentConsumption);
|
|
|
|
/* /////////////////////////////////////*/
|
|
/* // Create File For EM : Power_On_Voltage */
|
|
/* /////////////////////////////////////*/
|
|
static ssize_t show_Power_On_Voltage(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
int ret_value = 1;
|
|
|
|
ret_value = 3450;
|
|
bm_err("[EM] Power_On_Voltage : %d\n", ret_value);
|
|
return sprintf(buf, "%u\n", ret_value);
|
|
}
|
|
|
|
static ssize_t store_Power_On_Voltage(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
bm_err("[EM] Not Support Write Function\n");
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(
|
|
Power_On_Voltage, 0664, show_Power_On_Voltage, store_Power_On_Voltage);
|
|
|
|
/* /////////////////////////////////////////// */
|
|
/* // Create File For EM : Power_Off_Voltage */
|
|
/* /////////////////////////////////////////// */
|
|
static ssize_t show_Power_Off_Voltage(
|
|
struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
int ret_value = 1;
|
|
|
|
ret_value = 3400;
|
|
bm_err("[EM] Power_Off_Voltage : %d\n", ret_value);
|
|
return sprintf(buf, "%u\n", ret_value);
|
|
}
|
|
|
|
static ssize_t store_Power_Off_Voltage(
|
|
struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t size)
|
|
{
|
|
bm_err("[EM] Not Support Write Function\n");
|
|
return size;
|
|
}
|
|
|
|
static DEVICE_ATTR(
|
|
Power_Off_Voltage, 0664,
|
|
show_Power_Off_Voltage, store_Power_Off_Voltage);
|
|
|
|
|
|
static int battery_callback(
|
|
struct notifier_block *nb, unsigned long event, void *v)
|
|
{
|
|
bm_err("%s:%ld\n",
|
|
__func__, event);
|
|
switch (event) {
|
|
case CHARGER_NOTIFY_EOC:
|
|
{
|
|
/* CHARGING FULL */
|
|
#if !defined(CONFIG_BATTERY_SAMSUNG)
|
|
/* Moved to use sec_battery.c set property */
|
|
notify_fg_chr_full();
|
|
#endif
|
|
}
|
|
break;
|
|
case CHARGER_NOTIFY_START_CHARGING:
|
|
{
|
|
/* START CHARGING */
|
|
#if !defined(CONFIG_BATTERY_SAMSUNG)
|
|
/* Moved to use sec_battery.c set property */
|
|
fg_sw_bat_cycle_accu();
|
|
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
|
|
battery_update(&battery_main);
|
|
#endif
|
|
}
|
|
break;
|
|
case CHARGER_NOTIFY_STOP_CHARGING:
|
|
{
|
|
/* STOP CHARGING */
|
|
#if !defined(CONFIG_BATTERY_SAMSUNG)
|
|
/* Moved to use sec_battery.c set property */
|
|
fg_sw_bat_cycle_accu();
|
|
battery_main.BAT_STATUS =
|
|
POWER_SUPPLY_STATUS_DISCHARGING;
|
|
battery_update(&battery_main);
|
|
#endif
|
|
}
|
|
break;
|
|
case CHARGER_NOTIFY_ERROR:
|
|
{
|
|
/* charging enter error state */
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
|
battery_update(&battery_main);
|
|
}
|
|
break;
|
|
case CHARGER_NOTIFY_NORMAL:
|
|
{
|
|
/* charging leave error state */
|
|
battery_main.BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING;
|
|
battery_update(&battery_main);
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
/********** adc_cdev*******************/
|
|
signed int battery_meter_meta_tool_cali_car_tune(int meta_current)
|
|
{
|
|
int cali_car_tune = 0;
|
|
int ret = 0;
|
|
|
|
if (meta_current == 0)
|
|
return fg_cust_data.car_tune_value * 10;
|
|
|
|
ret = gauge_dev_enable_car_tune_value_calibration(
|
|
gm.gdev, meta_current, &cali_car_tune);
|
|
|
|
return cali_car_tune; /* 1000 base */
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_COMPAT)
|
|
static long compat_adc_cali_ioctl(
|
|
struct file *filp, unsigned int cmd, unsigned long arg)
|
|
{
|
|
int adc_out_datas[2] = { 1, 1 };
|
|
|
|
bm_notice("%s 32bit IOCTL, cmd=0x%08x\n",
|
|
__func__, cmd);
|
|
if (!filp->f_op || !filp->f_op->unlocked_ioctl) {
|
|
bm_err("%s file has no f_op or no f_op->unlocked_ioctl.\n",
|
|
__func__);
|
|
return -ENOTTY;
|
|
}
|
|
|
|
if (sizeof(arg) != sizeof(adc_out_datas))
|
|
return -EFAULT;
|
|
|
|
switch (cmd) {
|
|
case BAT_STATUS_READ:
|
|
case ADC_CHANNEL_READ:
|
|
case Get_META_BAT_VOL:
|
|
case Get_META_BAT_SOC:
|
|
case Get_META_BAT_CAR_TUNE_VALUE:
|
|
case Set_META_BAT_CAR_TUNE_VALUE:
|
|
case Set_BAT_DISABLE_NAFG:
|
|
case Set_CARTUNE_TO_KERNEL: {
|
|
bm_notice(
|
|
"%s send to unlocked_ioctl cmd=0x%08x\n",
|
|
__func__,
|
|
cmd);
|
|
return filp->f_op->unlocked_ioctl(
|
|
filp, cmd,
|
|
(unsigned long)compat_ptr(arg));
|
|
}
|
|
break;
|
|
default:
|
|
bm_err("%s unknown IOCTL: 0x%08x, %d\n",
|
|
__func__, cmd, adc_out_datas[0]);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static long adc_cali_ioctl(
|
|
struct file *file, unsigned int cmd, unsigned long arg)
|
|
{
|
|
int *user_data_addr;
|
|
int *naram_data_addr;
|
|
int i = 0;
|
|
int ret = 0;
|
|
int adc_in_data[2] = { 1, 1 };
|
|
int adc_out_data[2] = { 1, 1 };
|
|
int temp_car_tune;
|
|
int isdisNAFG = 0;
|
|
|
|
bm_notice("%s enter\n", __func__);
|
|
mutex_lock(&gm.fg_mutex);
|
|
user_data_addr = (int *)arg;
|
|
ret = copy_from_user(adc_in_data, user_data_addr, sizeof(adc_in_data));
|
|
if (adc_in_data[1] < 0) {
|
|
bm_err("%s unknown data: %d\n", __func__, adc_in_data[1]);
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
switch (cmd) {
|
|
case TEST_ADC_CALI_PRINT:
|
|
g_ADC_Cali = false;
|
|
break;
|
|
|
|
case SET_ADC_CALI_Slop:
|
|
naram_data_addr = (int *)arg;
|
|
ret = copy_from_user(adc_cali_slop, naram_data_addr, 36);
|
|
g_ADC_Cali = false;
|
|
/* Protection */
|
|
for (i = 0; i < 14; i++) {
|
|
if ((*(adc_cali_slop + i) == 0)
|
|
|| (*(adc_cali_slop + i) == 1))
|
|
*(adc_cali_slop + i) = 1000;
|
|
}
|
|
for (i = 0; i < 14; i++)
|
|
bm_notice("adc_cali_slop[%d] = %d\n", i,
|
|
*(adc_cali_slop + i));
|
|
bm_notice("**** unlocked_ioctl : SET_ADC_CALI_Slop Done!\n");
|
|
break;
|
|
|
|
case SET_ADC_CALI_Offset:
|
|
naram_data_addr = (int *)arg;
|
|
ret = copy_from_user(adc_cali_offset, naram_data_addr, 36);
|
|
g_ADC_Cali = false;
|
|
for (i = 0; i < 14; i++)
|
|
bm_notice("adc_cali_offset[%d] = %d\n", i,
|
|
*(adc_cali_offset + i));
|
|
bm_notice("**** unlocked_ioctl : SET_ADC_CALI_Offset Done!\n");
|
|
break;
|
|
|
|
case SET_ADC_CALI_Cal:
|
|
naram_data_addr = (int *)arg;
|
|
ret = copy_from_user(adc_cali_cal, naram_data_addr, 4);
|
|
g_ADC_Cali = true;
|
|
if (adc_cali_cal[0] == 1)
|
|
g_ADC_Cali = true;
|
|
else
|
|
g_ADC_Cali = false;
|
|
|
|
for (i = 0; i < 1; i++)
|
|
bm_notice("adc_cali_cal[%d] = %d\n", i,
|
|
*(adc_cali_cal + i));
|
|
bm_notice("**** unlocked_ioctl : SET_ADC_CALI_Cal Done!\n");
|
|
break;
|
|
|
|
case ADC_CHANNEL_READ:
|
|
/* g_ADC_Cali = KAL_FALSE; *//* 20100508 Infinity */
|
|
if (adc_in_data[0] == 0) {
|
|
/* I_SENSE */
|
|
adc_out_data[0] =
|
|
battery_get_bat_voltage() * adc_in_data[1];
|
|
} else if (adc_in_data[0] == 1) {
|
|
/* BAT_SENSE */
|
|
adc_out_data[0] =
|
|
battery_get_bat_voltage() * adc_in_data[1];
|
|
} else if (adc_in_data[0] == 3) {
|
|
/* V_Charger */
|
|
adc_out_data[0] = battery_get_vbus() * adc_in_data[1];
|
|
/* adc_out_data[0] = adc_out_data[0] / 100; */
|
|
} else if (adc_in_data[0] == 30) {
|
|
/* V_Bat_temp magic number */
|
|
adc_out_data[0] =
|
|
battery_get_bat_temperature() * adc_in_data[1];
|
|
} else if (adc_in_data[0] == 66)
|
|
adc_out_data[0] = (battery_get_bat_current()) / 10;
|
|
else {
|
|
bm_notice("unknown channel(%d,%d)\n",
|
|
adc_in_data[0], adc_in_data[1]);
|
|
}
|
|
|
|
if (adc_out_data[0] < 0)
|
|
adc_out_data[1] = 1; /* failed */
|
|
else
|
|
adc_out_data[1] = 0; /* success */
|
|
|
|
if (adc_in_data[0] == 30)
|
|
adc_out_data[1] = 0; /* success */
|
|
|
|
if (adc_in_data[0] == 66)
|
|
adc_out_data[1] = 0; /* success */
|
|
|
|
ret = copy_to_user(user_data_addr, adc_out_data, 8);
|
|
bm_notice(
|
|
"**** unlocked_ioctl : Channel %d * %d times = %d\n",
|
|
adc_in_data[0], adc_in_data[1], adc_out_data[0]);
|
|
break;
|
|
|
|
case BAT_STATUS_READ:
|
|
user_data_addr = (int *)arg;
|
|
ret = copy_from_user(battery_in_data, user_data_addr, 4);
|
|
/* [0] is_CAL */
|
|
if (g_ADC_Cali)
|
|
battery_out_data[0] = 1;
|
|
else
|
|
battery_out_data[0] = 0;
|
|
ret = copy_to_user(user_data_addr, battery_out_data, 4);
|
|
bm_notice(
|
|
"unlocked_ioctl : CAL:%d\n", battery_out_data[0]);
|
|
break;
|
|
#if 0
|
|
case Set_Charger_Current: /* For Factory Mode */
|
|
user_data_addr = (int *)arg;
|
|
ret = copy_from_user(charging_level_data, user_data_addr, 4);
|
|
g_ftm_battery_flag = KAL_TRUE;
|
|
if (charging_level_data[0] == 0)
|
|
charging_level_data[0] = CHARGE_CURRENT_70_00_MA;
|
|
else if (charging_level_data[0] == 1)
|
|
charging_level_data[0] = CHARGE_CURRENT_200_00_MA;
|
|
else if (charging_level_data[0] == 2)
|
|
charging_level_data[0] = CHARGE_CURRENT_400_00_MA;
|
|
else if (charging_level_data[0] == 3)
|
|
charging_level_data[0] = CHARGE_CURRENT_450_00_MA;
|
|
else if (charging_level_data[0] == 4)
|
|
charging_level_data[0] = CHARGE_CURRENT_550_00_MA;
|
|
else if (charging_level_data[0] == 5)
|
|
charging_level_data[0] = CHARGE_CURRENT_650_00_MA;
|
|
else if (charging_level_data[0] == 6)
|
|
charging_level_data[0] = CHARGE_CURRENT_700_00_MA;
|
|
else if (charging_level_data[0] == 7)
|
|
charging_level_data[0] = CHARGE_CURRENT_800_00_MA;
|
|
else if (charging_level_data[0] == 8)
|
|
charging_level_data[0] = CHARGE_CURRENT_900_00_MA;
|
|
else if (charging_level_data[0] == 9)
|
|
charging_level_data[0] = CHARGE_CURRENT_1000_00_MA;
|
|
else if (charging_level_data[0] == 10)
|
|
charging_level_data[0] = CHARGE_CURRENT_1100_00_MA;
|
|
else if (charging_level_data[0] == 11)
|
|
charging_level_data[0] = CHARGE_CURRENT_1200_00_MA;
|
|
else if (charging_level_data[0] == 12)
|
|
charging_level_data[0] = CHARGE_CURRENT_1300_00_MA;
|
|
else if (charging_level_data[0] == 13)
|
|
charging_level_data[0] = CHARGE_CURRENT_1400_00_MA;
|
|
else if (charging_level_data[0] == 14)
|
|
charging_level_data[0] = CHARGE_CURRENT_1500_00_MA;
|
|
else if (charging_level_data[0] == 15)
|
|
charging_level_data[0] = CHARGE_CURRENT_1600_00_MA;
|
|
else
|
|
charging_level_data[0] = CHARGE_CURRENT_450_00_MA;
|
|
wake_up_bat();
|
|
bm_notice("**** unlocked_ioctl : set_Charger_Current:%d\n",
|
|
charging_level_data[0]);
|
|
break;
|
|
#endif
|
|
/* add for meta tool------------------------------- */
|
|
case Get_META_BAT_VOL:
|
|
adc_out_data[0] = battery_get_bat_voltage();
|
|
if (copy_to_user(user_data_addr, adc_out_data,
|
|
sizeof(adc_out_data))) {
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
bm_notice("**** unlocked_ioctl :Get_META_BAT_VOL Done!\n");
|
|
break;
|
|
case Get_META_BAT_SOC:
|
|
adc_out_data[0] = battery_get_uisoc();
|
|
|
|
if (copy_to_user(user_data_addr, adc_out_data,
|
|
sizeof(adc_out_data))) {
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
bm_notice("**** unlocked_ioctl :Get_META_BAT_SOC Done!\n");
|
|
break;
|
|
|
|
case Get_META_BAT_CAR_TUNE_VALUE:
|
|
adc_out_data[0] = fg_cust_data.car_tune_value;
|
|
bm_err("Get_BAT_CAR_TUNE_VALUE, res=%d\n", adc_out_data[0]);
|
|
|
|
if (copy_to_user(user_data_addr, adc_out_data,
|
|
sizeof(adc_out_data))) {
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
bm_notice("**** unlocked_ioctl :Get_META_BAT_CAR_TUNE_VALUE Done!\n");
|
|
break;
|
|
|
|
case Set_META_BAT_CAR_TUNE_VALUE:
|
|
/* meta tool input: adc_in_data[1] (mA)*/
|
|
/* Send cali_current to hal to calculate car_tune_value*/
|
|
temp_car_tune =
|
|
battery_meter_meta_tool_cali_car_tune(adc_in_data[1]);
|
|
|
|
/* return car_tune_value to meta tool in adc_out_data[0] */
|
|
if (temp_car_tune >= 900 && temp_car_tune <= 1100)
|
|
fg_cust_data.car_tune_value = temp_car_tune;
|
|
else
|
|
bm_err("car_tune_value invalid:%d\n",
|
|
temp_car_tune);
|
|
|
|
adc_out_data[0] = temp_car_tune;
|
|
|
|
if (copy_to_user(user_data_addr, adc_out_data,
|
|
sizeof(adc_out_data))) {
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EFAULT;
|
|
}
|
|
|
|
|
|
bm_err("**** unlocked_ioctl Set_BAT_CAR_TUNE_VALUE[%d], result=%d, ret=%d\n",
|
|
adc_in_data[1], adc_out_data[0], ret);
|
|
|
|
break;
|
|
|
|
case Set_BAT_DISABLE_NAFG:
|
|
isdisNAFG = adc_in_data[1];
|
|
|
|
if (isdisNAFG == 1) {
|
|
gm.cmd_disable_nafg = true;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_DISABLE_NAFG, 1);
|
|
} else if (isdisNAFG == 0) {
|
|
gm.cmd_disable_nafg = false;
|
|
wakeup_fg_algo_cmd(
|
|
FG_INTR_KERNEL_CMD,
|
|
FG_KERNEL_CMD_DISABLE_NAFG, 0);
|
|
}
|
|
bm_debug("unlocked_ioctl Set_BAT_DISABLE_NAFG,isdisNAFG=%d [%d]\n",
|
|
isdisNAFG, adc_in_data[1]);
|
|
break;
|
|
|
|
/* add bing meta tool------------------------------- */
|
|
case Set_CARTUNE_TO_KERNEL:
|
|
temp_car_tune = adc_in_data[1];
|
|
if (temp_car_tune > 500 && temp_car_tune < 1500)
|
|
fg_cust_data.car_tune_value = temp_car_tune;
|
|
|
|
bm_err("**** unlocked_ioctl Set_CARTUNE_TO_KERNEL[%d,%d], ret=%d\n",
|
|
adc_in_data[0], adc_in_data[1], ret);
|
|
break;
|
|
default:
|
|
bm_err("**** unlocked_ioctl unknown IOCTL: 0x%08x\n", cmd);
|
|
g_ADC_Cali = false;
|
|
mutex_unlock(&gm.fg_mutex);
|
|
return -EINVAL;
|
|
}
|
|
|
|
mutex_unlock(&gm.fg_mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adc_cali_open(struct inode *inode, struct file *file)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int adc_cali_release(struct inode *inode, struct file *file)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long bat_node;
|
|
|
|
static int fb_early_init_dt_get_chosen(
|
|
unsigned long node, const char *uname, int depth, void *data)
|
|
{
|
|
if (depth != 1 || (strcmp(uname, "chosen") != 0
|
|
&& strcmp(uname, "chosen@0") != 0))
|
|
return 0;
|
|
bat_node = node;
|
|
return 1;
|
|
}
|
|
|
|
|
|
static const struct file_operations adc_cali_fops = {
|
|
.owner = THIS_MODULE,
|
|
.unlocked_ioctl = adc_cali_ioctl,
|
|
#if IS_ENABLED(CONFIG_COMPAT)
|
|
.compat_ioctl = compat_adc_cali_ioctl,
|
|
#endif
|
|
.open = adc_cali_open,
|
|
.release = adc_cali_release,
|
|
};
|
|
|
|
|
|
/*************************************/
|
|
static struct wakeup_source *battery_lock;
|
|
static int __init battery_probe(struct platform_device *dev)
|
|
{
|
|
int ret_device_file = 0;
|
|
int ret;
|
|
struct class_device *class_dev = NULL;
|
|
const char *fg_swocv_v = NULL;
|
|
char fg_swocv_v_tmp[10];
|
|
int fg_swocv_v_len = 0;
|
|
const char *fg_swocv_i = NULL;
|
|
char fg_swocv_i_tmp[10];
|
|
int fg_swocv_i_len = 0;
|
|
const char *shutdown_time = NULL;
|
|
char shutdown_time_tmp[10];
|
|
int shutdown_time_len = 0;
|
|
const char *boot_voltage = NULL;
|
|
char boot_voltage_tmp[10];
|
|
int boot_voltage_len = 0;
|
|
|
|
battery_lock = wakeup_source_register(NULL, "battery wakelock");
|
|
__pm_stay_awake(battery_lock);
|
|
|
|
/********* adc_cdev **********/
|
|
ret = alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME);
|
|
if (ret)
|
|
bm_notice("Error: Can't Get Major number for adc_cali\n");
|
|
adc_cali_cdev = cdev_alloc();
|
|
adc_cali_cdev->owner = THIS_MODULE;
|
|
adc_cali_cdev->ops = &adc_cali_fops;
|
|
ret = cdev_add(adc_cali_cdev, adc_cali_devno, 1);
|
|
if (ret)
|
|
bm_notice("adc_cali Error: cdev_add\n");
|
|
adc_cali_major = MAJOR(adc_cali_devno);
|
|
adc_cali_class = class_create(THIS_MODULE, ADC_CALI_DEVNAME);
|
|
class_dev = (struct class_device *)device_create(adc_cali_class,
|
|
NULL,
|
|
adc_cali_devno,
|
|
NULL, ADC_CALI_DEVNAME);
|
|
/*****************************/
|
|
|
|
mtk_battery_init(dev);
|
|
|
|
/* Power supply class */
|
|
#if !defined(CONFIG_MTK_DISABLE_GAUGE)
|
|
battery_main.psy =
|
|
power_supply_register(
|
|
&(dev->dev), &battery_main.psd, NULL);
|
|
if (IS_ERR(battery_main.psy)) {
|
|
bm_err("[BAT_probe] power_supply_register Battery Fail !!\n");
|
|
ret = PTR_ERR(battery_main.psy);
|
|
return ret;
|
|
}
|
|
bm_err("[BAT_probe] power_supply_register Battery Success !!\n");
|
|
#endif
|
|
ret = device_create_file(&(dev->dev), &dev_attr_Battery_Temperature);
|
|
ret = device_create_file(&(dev->dev), &dev_attr_UI_SOC);
|
|
|
|
/* sysfs node */
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_uisoc_update_type);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_disable_nafg);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_ntc_disable_nafg);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_FG_meter_resistance);
|
|
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_BAT_EC);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_BAT_HEALTH);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_FG_Battery_CurrentConsumption);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_Power_On_Voltage);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_Power_Off_Voltage);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_shutdown_condition_enable);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_reset_battery_cycle);
|
|
ret_device_file = device_create_file(&(dev->dev),
|
|
&dev_attr_reset_aging_factor);
|
|
|
|
if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0)
|
|
fg_swocv_v =
|
|
of_get_flat_dt_prop(
|
|
bat_node, "atag,fg_swocv_v",
|
|
&fg_swocv_v_len);
|
|
if (fg_swocv_v == NULL) {
|
|
bm_err(" fg_swocv_v == NULL len = %d\n", fg_swocv_v_len);
|
|
} else {
|
|
snprintf(fg_swocv_v_tmp, (fg_swocv_v_len + 1),
|
|
"%s", fg_swocv_v);
|
|
ret = kstrtoint(fg_swocv_v_tmp, 10, &gm.ptim_lk_v);
|
|
bm_err(" fg_swocv_v = %s len %d fg_swocv_v_tmp %s ptim_lk_v[%d]\n",
|
|
fg_swocv_v, fg_swocv_v_len,
|
|
fg_swocv_v_tmp, gm.ptim_lk_v);
|
|
}
|
|
|
|
if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0)
|
|
fg_swocv_i = of_get_flat_dt_prop(
|
|
bat_node, "atag,fg_swocv_i", &fg_swocv_i_len);
|
|
if (fg_swocv_i == NULL) {
|
|
bm_err(" fg_swocv_i == NULL len = %d\n", fg_swocv_i_len);
|
|
} else {
|
|
snprintf(
|
|
fg_swocv_i_tmp, (fg_swocv_i_len + 1),
|
|
"%s", fg_swocv_i);
|
|
ret = kstrtoint(fg_swocv_i_tmp, 10, &gm.ptim_lk_i);
|
|
|
|
bm_err(" fg_swocv_i = %s len %d fg_swocv_i_tmp %s ptim_lk_i[%d]\n",
|
|
fg_swocv_i, fg_swocv_i_len,
|
|
fg_swocv_i_tmp, gm.ptim_lk_i);
|
|
}
|
|
|
|
if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0)
|
|
shutdown_time =
|
|
of_get_flat_dt_prop(
|
|
bat_node,
|
|
"atag,shutdown_time",
|
|
&shutdown_time_len);
|
|
if (shutdown_time == NULL) {
|
|
bm_err(" shutdown_time == NULL len = %d\n", shutdown_time_len);
|
|
} else {
|
|
snprintf(shutdown_time_tmp,
|
|
(shutdown_time_len + 1),
|
|
"%s", shutdown_time);
|
|
ret = kstrtoint(shutdown_time_tmp, 10, &gm.pl_shutdown_time);
|
|
|
|
bm_err(" shutdown_time = %s len %d shutdown_time_tmp %s pl_shutdown_time[%d]\n",
|
|
shutdown_time, shutdown_time_len,
|
|
shutdown_time_tmp, gm.pl_shutdown_time);
|
|
}
|
|
|
|
if (of_scan_flat_dt(fb_early_init_dt_get_chosen, NULL) > 0)
|
|
boot_voltage =
|
|
of_get_flat_dt_prop(
|
|
bat_node, "atag,boot_voltage",
|
|
&boot_voltage_len);
|
|
if (boot_voltage == NULL) {
|
|
bm_err(" boot_voltage == NULL len = %d\n", boot_voltage_len);
|
|
} else {
|
|
snprintf(
|
|
boot_voltage_tmp, (boot_voltage_len + 1),
|
|
"%s", boot_voltage);
|
|
ret = kstrtoint(boot_voltage_tmp, 10, &gm.pl_bat_vol);
|
|
|
|
bm_err(
|
|
"boot_voltage=%s len %d boot_voltage_tmp %s pl_bat_vol[%d]\n",
|
|
boot_voltage, boot_voltage_len,
|
|
boot_voltage_tmp, gm.pl_bat_vol);
|
|
}
|
|
|
|
gm.pbat_consumer = charger_manager_get_by_name(&(dev->dev), "charger");
|
|
if (gm.pbat_consumer != NULL) {
|
|
gm.bat_nb.notifier_call = battery_callback;
|
|
register_charger_manager_notifier(gm.pbat_consumer, &gm.bat_nb);
|
|
}
|
|
|
|
battery_debug_init();
|
|
|
|
__pm_relax(battery_lock);
|
|
|
|
if (IS_ENABLED(CONFIG_POWER_EXT) || gm.disable_mtkbattery ||
|
|
IS_ENABLED(CONFIG_MTK_DISABLE_GAUGE)) {
|
|
bm_err("disable GM 3.0\n");
|
|
disable_fg();
|
|
} else if (is_recovery_mode())
|
|
battery_recovery_init();
|
|
|
|
mtk_battery_last_init(dev);
|
|
|
|
|
|
gm.is_probe_done = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void battery_shutdown(struct platform_device *dev)
|
|
{
|
|
int fg_coulomb = 0;
|
|
int shut_car_diff = 0;
|
|
int verify_car = 0;
|
|
|
|
fg_coulomb = gauge_get_coulomb();
|
|
if (gm.d_saved_car != 0) {
|
|
shut_car_diff = fg_coulomb - gm.d_saved_car;
|
|
gauge_dev_set_info(gm.gdev, GAUGE_SHUTDOWN_CAR, shut_car_diff);
|
|
/* ready for writing to PMIC_RG */
|
|
}
|
|
gauge_dev_get_info(gm.gdev, GAUGE_SHUTDOWN_CAR, &verify_car);
|
|
|
|
bm_err("******** %s!! car=[o:%d,new:%d,diff:%d v:%d]********\n",
|
|
__func__,
|
|
gm.d_saved_car, fg_coulomb, shut_car_diff, verify_car);
|
|
|
|
gm.fix_coverity = 1;
|
|
}
|
|
|
|
static int battery_suspend(struct platform_device *dev, pm_message_t state)
|
|
{
|
|
bm_err("******** %s!! iavg=%d ***GM3 disable:%d %d %d %d tmp_intr:%d***\n",
|
|
__func__,
|
|
gm.hw_status.iavg_intr_flag,
|
|
gm.disableGM30,
|
|
fg_cust_data.disable_nafg,
|
|
gm.ntc_disable_nafg,
|
|
gm.cmd_disable_nafg,
|
|
gm.enable_tmp_intr_suspend);
|
|
|
|
if (gm.enable_tmp_intr_suspend == 0) {
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_H, 0);
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_L, 0);
|
|
enable_bat_temp_det(0);
|
|
}
|
|
|
|
|
|
if (gauge_get_hw_version() >= GAUGE_HW_V2000
|
|
&& gm.hw_status.iavg_intr_flag == 1) {
|
|
gauge_enable_interrupt(FG_IAVG_H_NO, 0);
|
|
if (gm.hw_status.iavg_lt > 0)
|
|
gauge_enable_interrupt(FG_IAVG_L_NO, 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int battery_resume(struct platform_device *dev)
|
|
{
|
|
zcv_filter_add(&gm.zcvf);
|
|
zcv_filter_dump(&gm.zcvf);
|
|
zcv_check(&gm.zcvf);
|
|
|
|
bm_err("******** %s!! iavg=%d ***GM3 disable:%d %d %d %d***\n",
|
|
__func__,
|
|
gm.hw_status.iavg_intr_flag,
|
|
gm.disableGM30,
|
|
fg_cust_data.disable_nafg,
|
|
gm.ntc_disable_nafg,
|
|
gm.cmd_disable_nafg);
|
|
|
|
if (is_fg_disabled()) {
|
|
bm_info("[%s] fg_disabled, don't enable iavg interrupt\n", __func__);
|
|
} else {
|
|
if (gauge_get_hw_version() >=
|
|
GAUGE_HW_V2000
|
|
&& gm.hw_status.iavg_intr_flag == 1) {
|
|
gauge_enable_interrupt(FG_IAVG_H_NO, 1);
|
|
if (gm.hw_status.iavg_lt > 0)
|
|
gauge_enable_interrupt(FG_IAVG_L_NO, 1);
|
|
}
|
|
}
|
|
/* reset nafg monitor time to avoid suspend for too long case */
|
|
get_monotonic_boottime(&gm.last_nafg_update_time);
|
|
|
|
fg_update_sw_iavg();
|
|
|
|
if (is_fg_disabled()) {
|
|
bm_info("[%s] fg_disabled, don't enable bat_temp interrupt\n", __func__);
|
|
} else {
|
|
if (gm.enable_tmp_intr_suspend == 0) {
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_H, 1);
|
|
gauge_enable_interrupt(FG_RG_INT_EN_BAT_TEMP_L, 1);
|
|
enable_bat_temp_det(1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_OF
|
|
static const struct of_device_id mtk_bat_of_match[] = {
|
|
{.compatible = "mediatek,bat_gm30",},
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, mtk_bat_of_match);
|
|
#endif
|
|
|
|
|
|
struct platform_device battery_device = {
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
.name = "mtk-fg-battery",
|
|
#else
|
|
.name = "battery",
|
|
#endif
|
|
.id = -1,
|
|
};
|
|
|
|
static struct platform_driver battery_driver_probe = {
|
|
.probe = battery_probe,
|
|
.remove = NULL,
|
|
.shutdown = battery_shutdown,
|
|
.suspend = battery_suspend,
|
|
.resume = battery_resume,
|
|
.driver = {
|
|
#if defined(CONFIG_BATTERY_SAMSUNG)
|
|
.name = "mtk-fg-battery",
|
|
#else
|
|
.name = "battery",
|
|
#endif
|
|
#ifdef CONFIG_OF
|
|
.of_match_table = mtk_bat_of_match,
|
|
#endif
|
|
},
|
|
};
|
|
|
|
static int __init battery_init(void)
|
|
{
|
|
struct netlink_kernel_cfg cfg = {
|
|
.input = nl_data_handler,
|
|
};
|
|
|
|
int ret;
|
|
|
|
gm.daemo_nl_sk = netlink_kernel_create(&init_net, NETLINK_FGD, &cfg);
|
|
bm_err("netlink_kernel_create protol= %d\n", NETLINK_FGD);
|
|
|
|
if (gm.daemo_nl_sk == NULL) {
|
|
bm_err("netlink_kernel_create error\n");
|
|
return -1;
|
|
}
|
|
bm_err("netlink_kernel_create ok\n");
|
|
|
|
#ifdef CONFIG_OF
|
|
/* register battery_device by DTS */
|
|
#else
|
|
ret = platform_device_register(&battery_device);
|
|
#endif
|
|
|
|
ret = platform_driver_register(&battery_driver_probe);
|
|
|
|
bm_err("[%s] Initialization : DONE\n",
|
|
__func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __exit battery_exit(void)
|
|
{
|
|
|
|
}
|
|
module_init(battery_init);
|
|
module_exit(battery_exit);
|
|
|
|
MODULE_AUTHOR("Weiching Lin");
|
|
MODULE_DESCRIPTION("Battery Device Driver");
|
|
MODULE_LICENSE("GPL");
|