13d0407baSopenharmony_ci/*
23d0407baSopenharmony_ci * rk817 battery  driver
33d0407baSopenharmony_ci *
43d0407baSopenharmony_ci * Copyright (C) 2018 Rockchip Corporation
53d0407baSopenharmony_ci *
63d0407baSopenharmony_ci * This program is free software; you can redistribute it and/or modify
73d0407baSopenharmony_ci * it under the terms of the GNU General Public License as published by
83d0407baSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or
93d0407baSopenharmony_ci * (at your option) any later version.
103d0407baSopenharmony_ci *
113d0407baSopenharmony_ci * This program is distributed in the hope that it will be useful,
123d0407baSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
133d0407baSopenharmony_ci * MERCHANTABILITY or FITNESS FR A PARTICULAR PURPOSE.  See the
143d0407baSopenharmony_ci * GNU General Public License for more details.
153d0407baSopenharmony_ci *
163d0407baSopenharmony_ci */
173d0407baSopenharmony_ci
183d0407baSopenharmony_ci#define pr_fmt(fmt) "rk817-bat: " fmt
193d0407baSopenharmony_ci
203d0407baSopenharmony_ci#include <linux/delay.h>
213d0407baSopenharmony_ci#include <linux/extcon.h>
223d0407baSopenharmony_ci#include <linux/fb.h>
233d0407baSopenharmony_ci#include <linux/gpio.h>
243d0407baSopenharmony_ci#include <linux/iio/consumer.h>
253d0407baSopenharmony_ci#include <linux/iio/iio.h>
263d0407baSopenharmony_ci#include <linux/irq.h>
273d0407baSopenharmony_ci#include <linux/jiffies.h>
283d0407baSopenharmony_ci#include <linux/mfd/rk808.h>
293d0407baSopenharmony_ci#include <linux/module.h>
303d0407baSopenharmony_ci#include <linux/of_device.h>
313d0407baSopenharmony_ci#include <linux/of_gpio.h>
323d0407baSopenharmony_ci#include <linux/platform_device.h>
333d0407baSopenharmony_ci#include <linux/power_supply.h>
343d0407baSopenharmony_ci#include <linux/power/rk_usbbc.h>
353d0407baSopenharmony_ci#include <linux/regmap.h>
363d0407baSopenharmony_ci#include <linux/rk_keys.h>
373d0407baSopenharmony_ci#include <linux/rtc.h>
383d0407baSopenharmony_ci#include <linux/timer.h>
393d0407baSopenharmony_ci#include <linux/wakelock.h>
403d0407baSopenharmony_ci#include <linux/workqueue.h>
413d0407baSopenharmony_ci
423d0407baSopenharmony_cistatic int dbg_enable;
433d0407baSopenharmony_ci
443d0407baSopenharmony_cimodule_param_named(dbg_level, dbg_enable, int, 0644);
453d0407baSopenharmony_ci
463d0407baSopenharmony_ci#define DBG(args...)                                                                                                   \
473d0407baSopenharmony_ci    do {                                                                                                               \
483d0407baSopenharmony_ci        if (dbg_enable) {                                                                                              \
493d0407baSopenharmony_ci            pr_info(args);                                                                                             \
503d0407baSopenharmony_ci        }                                                                                                              \
513d0407baSopenharmony_ci    } while (0)
523d0407baSopenharmony_ci
533d0407baSopenharmony_ci#define BAT_INFO(fmt, args...) pr_info(fmt, ##args)
543d0407baSopenharmony_ci
553d0407baSopenharmony_ci#define DRIVER_VERSION "1.00"
563d0407baSopenharmony_ci#define SFT_SET_KB 1
573d0407baSopenharmony_ci
583d0407baSopenharmony_ci#define DIV(x) ((x) ? (x) : 1)
593d0407baSopenharmony_ci#define ENABLE 0x01
603d0407baSopenharmony_ci#define DISABLE 0x00
613d0407baSopenharmony_ci#define MAX_INTERPOLATE 1000
623d0407baSopenharmony_ci#define MAX_PERCENTAGE 100
633d0407baSopenharmony_ci#define MAX_INT 0x7FFF
643d0407baSopenharmony_ci
653d0407baSopenharmony_ci/* RK818_GGCON */
663d0407baSopenharmony_ci#define OCV_SAMP_MIN_MSK 0x0c
673d0407baSopenharmony_ci#define OCV_SAMP_8MIN (0x00 << 2)
683d0407baSopenharmony_ci
693d0407baSopenharmony_ci#define ADC_CAL_8MIN 0x00
703d0407baSopenharmony_ci#define RELAX_VOL12_UPD_MSK (RELAX_VOL1_UPD | RELAX_VOL2_UPD)
713d0407baSopenharmony_ci#define MINUTE(x) ((x)*60)
723d0407baSopenharmony_ci
733d0407baSopenharmony_ci#define ADC_TO_CURRENT(adc_value, samp_res) ((adc_value) * 172 / 1000 / (samp_res))
743d0407baSopenharmony_ci#define CURRENT_TO_ADC(current, samp_res) ((current) * 1000 * (samp_res) / 172)
753d0407baSopenharmony_ci
763d0407baSopenharmony_ci#define ADC_TO_CAPACITY(adc_value, samp_res) ((adc_value) / 1000 * 172 / 3600 / (samp_res))
773d0407baSopenharmony_ci#define CAPACITY_TO_ADC(capacity, samp_res) ((capacity) * (samp_res)*3600 / 172 * 1000)
783d0407baSopenharmony_ci
793d0407baSopenharmony_ci#define ADC_TO_CAPACITY_UAH(adc_value, samp_res) ((adc_value) / 3600 * 172 / (samp_res))
803d0407baSopenharmony_ci#define ADC_TO_CAPACITY_MAH(adc_value, samp_res) ((adc_value) / 1000 * 172 / 3600 / (samp_res))
813d0407baSopenharmony_ci
823d0407baSopenharmony_ci/* THREAML_REG */
833d0407baSopenharmony_ci#define TEMP_85C (0x00 << 2)
843d0407baSopenharmony_ci#define TEMP_95C (0x01 << 2)
853d0407baSopenharmony_ci#define TEMP_105C (0x02 << 2)
863d0407baSopenharmony_ci#define TEMP_115C (0x03 << 2)
873d0407baSopenharmony_ci
883d0407baSopenharmony_ci#define ZERO_LOAD_LVL1 1400
893d0407baSopenharmony_ci#define ZERO_LOAD_LVL2 600
903d0407baSopenharmony_ci
913d0407baSopenharmony_ci/* zero algorithm */
923d0407baSopenharmony_ci#define PWROFF_THRESD 3400
933d0407baSopenharmony_ci#define MIN_ZERO_DSOC_ACCURACY 10 /* 0.01% */
943d0407baSopenharmony_ci#define MIN_ZERO_OVERCNT 100
953d0407baSopenharmony_ci#define MIN_ACCURACY 1
963d0407baSopenharmony_ci#define DEF_PWRPATH_RES 50
973d0407baSopenharmony_ci#define WAIT_DSOC_DROP_SEC 15
983d0407baSopenharmony_ci#define WAIT_SHTD_DROP_SEC 30
993d0407baSopenharmony_ci#define MIN_ZERO_GAP_XSOC1 10
1003d0407baSopenharmony_ci#define MIN_ZERO_GAP_XSOC2 5
1013d0407baSopenharmony_ci#define MIN_ZERO_GAP_XSOC3 3
1023d0407baSopenharmony_ci#define MIN_ZERO_GAP_CALIB 5
1033d0407baSopenharmony_ci
1043d0407baSopenharmony_ci#define ADC_CALIB_THRESHOLD 4
1053d0407baSopenharmony_ci#define ADC_CALIB_LMT_MIN 3
1063d0407baSopenharmony_ci#define ADC_CALIB_CNT 5
1073d0407baSopenharmony_ci
1083d0407baSopenharmony_ci/* default param */
1093d0407baSopenharmony_ci#define DEFAULT_BAT_RES 135
1103d0407baSopenharmony_ci#define DEFAULT_SLP_ENTER_CUR 300
1113d0407baSopenharmony_ci#define DEFAULT_SLP_EXIT_CUR 300
1123d0407baSopenharmony_ci#define DEFAULT_SLP_FILTER_CUR 100
1133d0407baSopenharmony_ci#define DEFAULT_PWROFF_VOL_THRESD 3400
1143d0407baSopenharmony_ci#define DEFAULT_MONITOR_SEC 5
1153d0407baSopenharmony_ci#define DEFAULT_ALGR_VOL_THRESD1 3850
1163d0407baSopenharmony_ci#define DEFAULT_ALGR_VOL_THRESD2 3950
1173d0407baSopenharmony_ci#define DEFAULT_CHRG_VOL_SEL CHRG_VOL4200MV
1183d0407baSopenharmony_ci#define DEFAULT_CHRG_CUR_SEL CHRG_CUR1400MA
1193d0407baSopenharmony_ci#define DEFAULT_CHRG_CUR_INPUT INPUT_CUR2000MA
1203d0407baSopenharmony_ci#define DEFAULT_POFFSET 42
1213d0407baSopenharmony_ci#define DEFAULT_MAX_SOC_OFFSET 60
1223d0407baSopenharmony_ci#define DEFAULT_FB_TEMP TEMP_115C
1233d0407baSopenharmony_ci#define DEFAULT_ENERGY_MODE 0
1243d0407baSopenharmony_ci#define DEFAULT_ZERO_RESERVE_DSOC 10
1253d0407baSopenharmony_ci#define DEFAULT_SAMPLE_RES 20
1263d0407baSopenharmony_ci
1273d0407baSopenharmony_ci/* sample resistor and division */
1283d0407baSopenharmony_ci#define SAMPLE_RES_10MR 10
1293d0407baSopenharmony_ci#define SAMPLE_RES_20MR 20
1303d0407baSopenharmony_ci#define SAMPLE_RES_DIV1 1
1313d0407baSopenharmony_ci#define SAMPLE_RES_DIV2 2
1323d0407baSopenharmony_ci
1333d0407baSopenharmony_ci/* sleep */
1343d0407baSopenharmony_ci#define SLP_CURR_MAX 40
1353d0407baSopenharmony_ci#define SLP_CURR_MIN 6
1363d0407baSopenharmony_ci#define LOW_PWR_SLP_CURR_MAX 20
1373d0407baSopenharmony_ci#define LOW_PWR_SLP_CURR_MIN 1
1383d0407baSopenharmony_ci#define DISCHRG_TIME_STEP1 MINUTE(10)
1393d0407baSopenharmony_ci#define DISCHRG_TIME_STEP2 MINUTE(60)
1403d0407baSopenharmony_ci#define SLP_DSOC_VOL_THRESD 3600
1413d0407baSopenharmony_ci#define REBOOT_PERIOD_SEC 180
1423d0407baSopenharmony_ci#define REBOOT_MAX_CNT 80
1433d0407baSopenharmony_ci
1443d0407baSopenharmony_ci#define TIMER_MS_COUNTS 1000
1453d0407baSopenharmony_ci/* fcc */
1463d0407baSopenharmony_ci#define MIN_FCC 500
1473d0407baSopenharmony_ci#define CAP_INVALID 0x80
1483d0407baSopenharmony_ci
1493d0407baSopenharmony_ci/* virtual params */
1503d0407baSopenharmony_ci#define VIRTUAL_CURRENT 1000
1513d0407baSopenharmony_ci#define VIRTUAL_VOLTAGE 3888
1523d0407baSopenharmony_ci#define VIRTUAL_SOC 66
1533d0407baSopenharmony_ci#define VIRTUAL_PRESET 1
1543d0407baSopenharmony_ci#define VIRTUAL_TEMPERATURE 188
1553d0407baSopenharmony_ci#define VIRTUAL_STATUS POWER_SUPPLY_STATUS_CHARGING
1563d0407baSopenharmony_ci
1573d0407baSopenharmony_ci#define FINISH_CHRG_CUR1 1000
1583d0407baSopenharmony_ci#define FINISH_CHRG_CUR2 1500
1593d0407baSopenharmony_ci#define FINISH_MAX_SOC_DELAY 20
1603d0407baSopenharmony_ci#define TERM_CHRG_DSOC 88
1613d0407baSopenharmony_ci#define TERM_CHRG_CURR 600
1623d0407baSopenharmony_ci#define TERM_CHRG_K 650
1633d0407baSopenharmony_ci#define SIMULATE_CHRG_INTV 8
1643d0407baSopenharmony_ci#define SIMULATE_CHRG_CURR 400
1653d0407baSopenharmony_ci#define SIMULATE_CHRG_K 1500
1663d0407baSopenharmony_ci#define FULL_CHRG_K 400
1673d0407baSopenharmony_ci
1683d0407baSopenharmony_cienum work_mode {
1693d0407baSopenharmony_ci    MODE_ZERO = 0,
1703d0407baSopenharmony_ci    MODE_FINISH,
1713d0407baSopenharmony_ci    MODE_SMOOTH_CHRG,
1723d0407baSopenharmony_ci    MODE_SMOOTH_DISCHRG,
1733d0407baSopenharmony_ci    MODE_SMOOTH,
1743d0407baSopenharmony_ci};
1753d0407baSopenharmony_ci
1763d0407baSopenharmony_cienum charge_status {
1773d0407baSopenharmony_ci    CHRG_OFF,
1783d0407baSopenharmony_ci    DEAD_CHRG,
1793d0407baSopenharmony_ci    TRICKLE_CHRG,
1803d0407baSopenharmony_ci    CC_OR_CV_CHRG,
1813d0407baSopenharmony_ci    CHARGE_FINISH,
1823d0407baSopenharmony_ci    USB_OVER_VOL,
1833d0407baSopenharmony_ci    BAT_TMP_ERR,
1843d0407baSopenharmony_ci    BAT_TIM_ERR,
1853d0407baSopenharmony_ci};
1863d0407baSopenharmony_ci
1873d0407baSopenharmony_cienum bat_mode {
1883d0407baSopenharmony_ci    MODE_BATTARY = 0,
1893d0407baSopenharmony_ci    MODE_VIRTUAL,
1903d0407baSopenharmony_ci};
1913d0407baSopenharmony_ci
1923d0407baSopenharmony_cienum rk817_sample_time {
1933d0407baSopenharmony_ci    S_8_MIN,
1943d0407baSopenharmony_ci    S_16_MIN,
1953d0407baSopenharmony_ci    S_32_MIN,
1963d0407baSopenharmony_ci    S_48_MIN,
1973d0407baSopenharmony_ci};
1983d0407baSopenharmony_ci
1993d0407baSopenharmony_cienum rk817_output_mode {
2003d0407baSopenharmony_ci    AVERAGE_MODE,
2013d0407baSopenharmony_ci    INSTANT_MODE,
2023d0407baSopenharmony_ci};
2033d0407baSopenharmony_ci
2043d0407baSopenharmony_cienum rk817_battery_fields {
2053d0407baSopenharmony_ci    ADC_SLP_RATE,
2063d0407baSopenharmony_ci    BAT_CUR_ADC_EN,
2073d0407baSopenharmony_ci    BAT_VOL_ADC_EN,
2083d0407baSopenharmony_ci    USB_VOL_ADC_EN,
2093d0407baSopenharmony_ci    TS_ADC_EN,
2103d0407baSopenharmony_ci    SYS_VOL_ADC_EN,
2113d0407baSopenharmony_ci    GG_EN, /* ADC_CONFIG0 */
2123d0407baSopenharmony_ci    CUR_ADC_DITH_SEL,
2133d0407baSopenharmony_ci    CUR_ADC_DIH_EN,
2143d0407baSopenharmony_ci    CUR_ADC_CHOP_EN,
2153d0407baSopenharmony_ci    CUR_ADC_CHOP_SEL,
2163d0407baSopenharmony_ci    CUR_ADC_CHOP_VREF_EN, /* CUR_ADC_CFG0 */
2173d0407baSopenharmony_ci    CUR_ADC_VCOM_SEL,
2183d0407baSopenharmony_ci    CUR_ADC_VCOM_BUF_INC,
2193d0407baSopenharmony_ci    CUR_ADC_VREF_BUF_INC,
2203d0407baSopenharmony_ci    CUR_ADC_BIAS_DEC,
2213d0407baSopenharmony_ci    CUR_ADC_IBIAS_SEL, /* CUR_ADC_CFG1 */
2223d0407baSopenharmony_ci    VOL_ADC_EXT_VREF_EN,
2233d0407baSopenharmony_ci    VOL_ADC_DITH_SEL,
2243d0407baSopenharmony_ci    VOL_ADC_DITH_EN,
2253d0407baSopenharmony_ci    VOL_ADC_CHOP_EN,
2263d0407baSopenharmony_ci    VOL_ADC_CHOP_SEL,
2273d0407baSopenharmony_ci    VOL_ADC_CHOP_VREF_EN,
2283d0407baSopenharmony_ci    VOL_ADC_VCOM_SEL,
2293d0407baSopenharmony_ci    VOL_ADC_VCOM_BUF_INC,
2303d0407baSopenharmony_ci    VOL_ADC_VREF_BUF_INC,
2313d0407baSopenharmony_ci    VOL_ADC_IBIAS_SEL, /* VOL_ADC_CFG1 */
2323d0407baSopenharmony_ci    RLX_CUR_FILTER,
2333d0407baSopenharmony_ci    TS_FUN,
2343d0407baSopenharmony_ci    VOL_ADC_TSCUR_SEL,
2353d0407baSopenharmony_ci    VOL_CALIB_UPD,
2363d0407baSopenharmony_ci    CUR_CALIB_UPD, /* ADC_CONFIG1 */
2373d0407baSopenharmony_ci    CUR_OUT_MOD,
2383d0407baSopenharmony_ci    VOL_OUT_MOD,
2393d0407baSopenharmony_ci    FRAME_SMP_INTERV,
2403d0407baSopenharmony_ci    ADC_OFF_CAL_INTERV,
2413d0407baSopenharmony_ci    RLX_SPT, /* GG_CON */
2423d0407baSopenharmony_ci    OCV_UPD,
2433d0407baSopenharmony_ci    RELAX_STS,
2443d0407baSopenharmony_ci    RELAX_VOL2_UPD,
2453d0407baSopenharmony_ci    RELAX_VOL1_UPD,
2463d0407baSopenharmony_ci    BAT_CON,
2473d0407baSopenharmony_ci    QMAX_UPD_SOFT,
2483d0407baSopenharmony_ci    TERM_UPD,
2493d0407baSopenharmony_ci    OCV_STS, /* GG_STS */
2503d0407baSopenharmony_ci    RELAX_THRE_H,
2513d0407baSopenharmony_ci    RELAX_THRE_L, /* RELAX_THRE */
2523d0407baSopenharmony_ci    RELAX_VOL1_H,
2533d0407baSopenharmony_ci    RELAX_VOL1_L,
2543d0407baSopenharmony_ci    RELAX_VOL2_H,
2553d0407baSopenharmony_ci    RELAX_VOL2_L,
2563d0407baSopenharmony_ci    RELAX_CUR1_H,
2573d0407baSopenharmony_ci    RELAX_CUR1_L,
2583d0407baSopenharmony_ci    RELAX_CUR2_H,
2593d0407baSopenharmony_ci    RELAX_CUR2_L,
2603d0407baSopenharmony_ci    OCV_THRE_VOL,
2613d0407baSopenharmony_ci    OCV_VOL_H,
2623d0407baSopenharmony_ci    OCV_VOL_L,
2633d0407baSopenharmony_ci    OCV_VOL0_H,
2643d0407baSopenharmony_ci    OCV_VOL0_L,
2653d0407baSopenharmony_ci    OCV_CUR_H,
2663d0407baSopenharmony_ci    OCV_CUR_L,
2673d0407baSopenharmony_ci    OCV_CUR0_H,
2683d0407baSopenharmony_ci    OCV_CUR0_L,
2693d0407baSopenharmony_ci    PWRON_VOL_H,
2703d0407baSopenharmony_ci    PWRON_VOL_L,
2713d0407baSopenharmony_ci    PWRON_CUR_H,
2723d0407baSopenharmony_ci    PWRON_CUR_L,
2733d0407baSopenharmony_ci    OFF_CNT,
2743d0407baSopenharmony_ci    Q_INIT_H3,
2753d0407baSopenharmony_ci    Q_INIT_H2,
2763d0407baSopenharmony_ci    Q_INIT_L1,
2773d0407baSopenharmony_ci    Q_INIT_L0,
2783d0407baSopenharmony_ci    Q_PRESS_H3,
2793d0407baSopenharmony_ci    Q_PRESS_H2,
2803d0407baSopenharmony_ci    Q_PRESS_L1,
2813d0407baSopenharmony_ci    Q_PRESS_L0,
2823d0407baSopenharmony_ci    BAT_VOL_H,
2833d0407baSopenharmony_ci    BAT_VOL_L,
2843d0407baSopenharmony_ci    BAT_CUR_H,
2853d0407baSopenharmony_ci    BAT_CUR_L,
2863d0407baSopenharmony_ci    BAT_TS_H,
2873d0407baSopenharmony_ci    BAT_TS_L,
2883d0407baSopenharmony_ci    USB_VOL_H,
2893d0407baSopenharmony_ci    USB_VOL_L,
2903d0407baSopenharmony_ci    SYS_VOL_H,
2913d0407baSopenharmony_ci    SYS_VOL_L,
2923d0407baSopenharmony_ci    Q_MAX_H3,
2933d0407baSopenharmony_ci    Q_MAX_H2,
2943d0407baSopenharmony_ci    Q_MAX_L1,
2953d0407baSopenharmony_ci    Q_MAX_L0,
2963d0407baSopenharmony_ci    Q_TERM_H3,
2973d0407baSopenharmony_ci    Q_TERM_H2,
2983d0407baSopenharmony_ci    Q_TERM_L1,
2993d0407baSopenharmony_ci    Q_TERM_L0,
3003d0407baSopenharmony_ci    Q_OCV_H3,
3013d0407baSopenharmony_ci    Q_OCV_H2,
3023d0407baSopenharmony_ci    Q_OCV_L1,
3033d0407baSopenharmony_ci    Q_OCV_L0,
3043d0407baSopenharmony_ci    OCV_CNT,
3053d0407baSopenharmony_ci    SLEEP_CON_SAMP_CUR_H,
3063d0407baSopenharmony_ci    SLEEP_CON_SAMP_CUR_L,
3073d0407baSopenharmony_ci    CAL_OFFSET_H,
3083d0407baSopenharmony_ci    CAL_OFFSET_L,
3093d0407baSopenharmony_ci    VCALIB0_H,
3103d0407baSopenharmony_ci    VCALIB0_L,
3113d0407baSopenharmony_ci    VCALIB1_H,
3123d0407baSopenharmony_ci    VCALIB1_L,
3133d0407baSopenharmony_ci    IOFFSET_H,
3143d0407baSopenharmony_ci    IOFFSET_L,
3153d0407baSopenharmony_ci    BAT_R0,
3163d0407baSopenharmony_ci    SOC_REG0,
3173d0407baSopenharmony_ci    SOC_REG1,
3183d0407baSopenharmony_ci    SOC_REG2,
3193d0407baSopenharmony_ci    REMAIN_CAP_REG2,
3203d0407baSopenharmony_ci    REMAIN_CAP_REG1,
3213d0407baSopenharmony_ci    REMAIN_CAP_REG0,
3223d0407baSopenharmony_ci    NEW_FCC_REG2,
3233d0407baSopenharmony_ci    NEW_FCC_REG1,
3243d0407baSopenharmony_ci    NEW_FCC_REG0,
3253d0407baSopenharmony_ci    RESET_MODE,
3263d0407baSopenharmony_ci    FG_INIT,
3273d0407baSopenharmony_ci    HALT_CNT_REG,
3283d0407baSopenharmony_ci    CALC_REST_REGL,
3293d0407baSopenharmony_ci    CALC_REST_REGH,
3303d0407baSopenharmony_ci    VOL_ADC_B3,
3313d0407baSopenharmony_ci    VOL_ADC_B2,
3323d0407baSopenharmony_ci    VOL_ADC_B1,
3333d0407baSopenharmony_ci    VOL_ADC_B0,
3343d0407baSopenharmony_ci    VOL_ADC_K3,
3353d0407baSopenharmony_ci    VOL_ADC_K2,
3363d0407baSopenharmony_ci    VOL_ADC_K1,
3373d0407baSopenharmony_ci    VOL_ADC_K0,
3383d0407baSopenharmony_ci    BAT_EXS,
3393d0407baSopenharmony_ci    CHG_STS,
3403d0407baSopenharmony_ci    BAT_OVP_STS,
3413d0407baSopenharmony_ci    CHRG_IN_CLAMP,
3423d0407baSopenharmony_ci    CHIP_NAME_H,
3433d0407baSopenharmony_ci    CHIP_NAME_L,
3443d0407baSopenharmony_ci    PLUG_IN_STS,
3453d0407baSopenharmony_ci    F_MAX_FIELDS
3463d0407baSopenharmony_ci};
3473d0407baSopenharmony_ci
3483d0407baSopenharmony_cistatic const struct reg_field rk817_battery_reg_fields[] = {
3493d0407baSopenharmony_ci    [ADC_SLP_RATE] = REG_FIELD(0x50, 0, 0),
3503d0407baSopenharmony_ci    [BAT_CUR_ADC_EN] = REG_FIELD(0x50, 2, 2),
3513d0407baSopenharmony_ci    [BAT_VOL_ADC_EN] = REG_FIELD(0x50, 3, 3),
3523d0407baSopenharmony_ci    [USB_VOL_ADC_EN] = REG_FIELD(0x50, 4, 4),
3533d0407baSopenharmony_ci    [TS_ADC_EN] = REG_FIELD(0x50, 5, 5),
3543d0407baSopenharmony_ci    [SYS_VOL_ADC_EN] = REG_FIELD(0x50, 6, 6),
3553d0407baSopenharmony_ci    [GG_EN] = REG_FIELD(0x50, 7, 7), /* ADC_CONFIG0 */
3563d0407baSopenharmony_ci
3573d0407baSopenharmony_ci    [CUR_ADC_DITH_SEL] = REG_FIELD(0x51, 1, 3),
3583d0407baSopenharmony_ci    [CUR_ADC_DIH_EN] = REG_FIELD(0x51, 4, 4),
3593d0407baSopenharmony_ci    [CUR_ADC_CHOP_EN] = REG_FIELD(0x51, 5, 5),
3603d0407baSopenharmony_ci    [CUR_ADC_CHOP_SEL] = REG_FIELD(0x51, 6, 6),
3613d0407baSopenharmony_ci    [CUR_ADC_CHOP_VREF_EN] = REG_FIELD(0x51, 7, 7), /* CUR_ADC_COFG0 */
3623d0407baSopenharmony_ci
3633d0407baSopenharmony_ci    [CUR_ADC_VCOM_SEL] = REG_FIELD(0x52, 0, 1),
3643d0407baSopenharmony_ci    [CUR_ADC_VCOM_BUF_INC] = REG_FIELD(0x52, 2, 2),
3653d0407baSopenharmony_ci    [CUR_ADC_VREF_BUF_INC] = REG_FIELD(0x52, 3, 3),
3663d0407baSopenharmony_ci    [CUR_ADC_BIAS_DEC] = REG_FIELD(0x52, 4, 4),
3673d0407baSopenharmony_ci    [CUR_ADC_IBIAS_SEL] = REG_FIELD(0x52, 5, 6), /* CUR_ADC_COFG1 */
3683d0407baSopenharmony_ci
3693d0407baSopenharmony_ci    [VOL_ADC_EXT_VREF_EN] = REG_FIELD(0x53, 0, 0),
3703d0407baSopenharmony_ci    [VOL_ADC_DITH_SEL] = REG_FIELD(0x53, 1, 3),
3713d0407baSopenharmony_ci    [VOL_ADC_DITH_EN] = REG_FIELD(0x53, 4, 4),
3723d0407baSopenharmony_ci    [VOL_ADC_CHOP_EN] = REG_FIELD(0x53, 5, 5),
3733d0407baSopenharmony_ci    [VOL_ADC_CHOP_SEL] = REG_FIELD(0x53, 6, 6),
3743d0407baSopenharmony_ci    [VOL_ADC_CHOP_VREF_EN] = REG_FIELD(0x53, 7, 7), /* VOL_ADC_COFG0 */
3753d0407baSopenharmony_ci
3763d0407baSopenharmony_ci    [VOL_ADC_VCOM_SEL] = REG_FIELD(0x54, 0, 1),
3773d0407baSopenharmony_ci    [VOL_ADC_VCOM_BUF_INC] = REG_FIELD(0x54, 2, 2),
3783d0407baSopenharmony_ci    [VOL_ADC_VREF_BUF_INC] = REG_FIELD(0x54, 3, 3),
3793d0407baSopenharmony_ci    [VOL_ADC_IBIAS_SEL] = REG_FIELD(0x54, 5, 6), /* VOL_ADC_COFG1 */
3803d0407baSopenharmony_ci
3813d0407baSopenharmony_ci    [RLX_CUR_FILTER] = REG_FIELD(0x55, 0, 1),
3823d0407baSopenharmony_ci    [TS_FUN] = REG_FIELD(0x55, 3, 3),
3833d0407baSopenharmony_ci    [VOL_ADC_TSCUR_SEL] = REG_FIELD(0x55, 4, 5),
3843d0407baSopenharmony_ci    [VOL_CALIB_UPD] = REG_FIELD(0x55, 6, 6),
3853d0407baSopenharmony_ci    [CUR_CALIB_UPD] = REG_FIELD(0x55, 7, 7), /* ADC_CONFIG1 */
3863d0407baSopenharmony_ci
3873d0407baSopenharmony_ci    [CUR_OUT_MOD] = REG_FIELD(0x56, 0, 0),
3883d0407baSopenharmony_ci    [VOL_OUT_MOD] = REG_FIELD(0x56, 1, 1),
3893d0407baSopenharmony_ci    [FRAME_SMP_INTERV] = REG_FIELD(0x56, 2, 3),
3903d0407baSopenharmony_ci    [ADC_OFF_CAL_INTERV] = REG_FIELD(0x56, 4, 5),
3913d0407baSopenharmony_ci    [RLX_SPT] = REG_FIELD(0x56, 6, 7), /* GG_CON */
3923d0407baSopenharmony_ci
3933d0407baSopenharmony_ci    [OCV_UPD] = REG_FIELD(0x57, 0, 0),
3943d0407baSopenharmony_ci    [RELAX_STS] = REG_FIELD(0x57, 1, 1),
3953d0407baSopenharmony_ci    [RELAX_VOL2_UPD] = REG_FIELD(0x57, 2, 2),
3963d0407baSopenharmony_ci    [RELAX_VOL1_UPD] = REG_FIELD(0x57, 3, 3),
3973d0407baSopenharmony_ci    [BAT_CON] = REG_FIELD(0x57, 4, 4),
3983d0407baSopenharmony_ci    [QMAX_UPD_SOFT] = REG_FIELD(0x57, 5, 5),
3993d0407baSopenharmony_ci    [TERM_UPD] = REG_FIELD(0x57, 6, 6),
4003d0407baSopenharmony_ci    [OCV_STS] = REG_FIELD(0x57, 7, 7), /* GG_STS */
4013d0407baSopenharmony_ci
4023d0407baSopenharmony_ci    [RELAX_THRE_H] = REG_FIELD(0x58, 0, 7),
4033d0407baSopenharmony_ci    [RELAX_THRE_L] = REG_FIELD(0x59, 0, 7),
4043d0407baSopenharmony_ci
4053d0407baSopenharmony_ci    [RELAX_VOL1_H] = REG_FIELD(0x5A, 0, 7),
4063d0407baSopenharmony_ci    [RELAX_VOL1_L] = REG_FIELD(0x5B, 0, 7),
4073d0407baSopenharmony_ci    [RELAX_VOL2_H] = REG_FIELD(0x5C, 0, 7),
4083d0407baSopenharmony_ci    [RELAX_VOL2_L] = REG_FIELD(0x5D, 0, 7),
4093d0407baSopenharmony_ci
4103d0407baSopenharmony_ci    [RELAX_CUR1_H] = REG_FIELD(0x5E, 0, 7),
4113d0407baSopenharmony_ci    [RELAX_CUR1_L] = REG_FIELD(0x5F, 0, 7),
4123d0407baSopenharmony_ci    [RELAX_CUR2_H] = REG_FIELD(0x60, 0, 7),
4133d0407baSopenharmony_ci    [RELAX_CUR2_L] = REG_FIELD(0x61, 0, 7),
4143d0407baSopenharmony_ci
4153d0407baSopenharmony_ci    [OCV_THRE_VOL] = REG_FIELD(0x62, 0, 7),
4163d0407baSopenharmony_ci
4173d0407baSopenharmony_ci    [OCV_VOL_H] = REG_FIELD(0x63, 0, 7),
4183d0407baSopenharmony_ci    [OCV_VOL_L] = REG_FIELD(0x64, 0, 7),
4193d0407baSopenharmony_ci    [OCV_VOL0_H] = REG_FIELD(0x65, 0, 7),
4203d0407baSopenharmony_ci    [OCV_VOL0_L] = REG_FIELD(0x66, 0, 7),
4213d0407baSopenharmony_ci    [OCV_CUR_H] = REG_FIELD(0x67, 0, 7),
4223d0407baSopenharmony_ci    [OCV_CUR_L] = REG_FIELD(0x68, 0, 7),
4233d0407baSopenharmony_ci    [OCV_CUR0_H] = REG_FIELD(0x69, 0, 7),
4243d0407baSopenharmony_ci    [OCV_CUR0_L] = REG_FIELD(0x6A, 0, 7),
4253d0407baSopenharmony_ci    [PWRON_VOL_H] = REG_FIELD(0x6B, 0, 7),
4263d0407baSopenharmony_ci    [PWRON_VOL_L] = REG_FIELD(0x6C, 0, 7),
4273d0407baSopenharmony_ci    [PWRON_CUR_H] = REG_FIELD(0x6D, 0, 7),
4283d0407baSopenharmony_ci    [PWRON_CUR_L] = REG_FIELD(0x6E, 0, 7),
4293d0407baSopenharmony_ci    [OFF_CNT] = REG_FIELD(0x6F, 0, 7),
4303d0407baSopenharmony_ci    [Q_INIT_H3] = REG_FIELD(0x70, 0, 7),
4313d0407baSopenharmony_ci    [Q_INIT_H2] = REG_FIELD(0x71, 0, 7),
4323d0407baSopenharmony_ci    [Q_INIT_L1] = REG_FIELD(0x72, 0, 7),
4333d0407baSopenharmony_ci    [Q_INIT_L0] = REG_FIELD(0x73, 0, 7),
4343d0407baSopenharmony_ci
4353d0407baSopenharmony_ci    [Q_PRESS_H3] = REG_FIELD(0x74, 0, 7),
4363d0407baSopenharmony_ci    [Q_PRESS_H2] = REG_FIELD(0x75, 0, 7),
4373d0407baSopenharmony_ci    [Q_PRESS_L1] = REG_FIELD(0x76, 0, 7),
4383d0407baSopenharmony_ci    [Q_PRESS_L0] = REG_FIELD(0x77, 0, 7),
4393d0407baSopenharmony_ci
4403d0407baSopenharmony_ci    [BAT_VOL_H] = REG_FIELD(0x78, 0, 7),
4413d0407baSopenharmony_ci    [BAT_VOL_L] = REG_FIELD(0x79, 0, 7),
4423d0407baSopenharmony_ci
4433d0407baSopenharmony_ci    [BAT_CUR_H] = REG_FIELD(0x7A, 0, 7),
4443d0407baSopenharmony_ci    [BAT_CUR_L] = REG_FIELD(0x7B, 0, 7),
4453d0407baSopenharmony_ci
4463d0407baSopenharmony_ci    [BAT_TS_H] = REG_FIELD(0x7C, 0, 7),
4473d0407baSopenharmony_ci    [BAT_TS_L] = REG_FIELD(0x7D, 0, 7),
4483d0407baSopenharmony_ci    [USB_VOL_H] = REG_FIELD(0x7E, 0, 7),
4493d0407baSopenharmony_ci    [USB_VOL_L] = REG_FIELD(0x7F, 0, 7),
4503d0407baSopenharmony_ci
4513d0407baSopenharmony_ci    [SYS_VOL_H] = REG_FIELD(0x80, 0, 7),
4523d0407baSopenharmony_ci    [SYS_VOL_L] = REG_FIELD(0x81, 0, 7),
4533d0407baSopenharmony_ci    [Q_MAX_H3] = REG_FIELD(0x82, 0, 7),
4543d0407baSopenharmony_ci    [Q_MAX_H2] = REG_FIELD(0x83, 0, 7),
4553d0407baSopenharmony_ci    [Q_MAX_L1] = REG_FIELD(0x84, 0, 7),
4563d0407baSopenharmony_ci    [Q_MAX_L0] = REG_FIELD(0x85, 0, 7),
4573d0407baSopenharmony_ci
4583d0407baSopenharmony_ci    [Q_TERM_H3] = REG_FIELD(0x86, 0, 7),
4593d0407baSopenharmony_ci    [Q_TERM_H2] = REG_FIELD(0x87, 0, 7),
4603d0407baSopenharmony_ci    [Q_TERM_L1] = REG_FIELD(0x88, 0, 7),
4613d0407baSopenharmony_ci    [Q_TERM_L0] = REG_FIELD(0x89, 0, 7),
4623d0407baSopenharmony_ci    [Q_OCV_H3] = REG_FIELD(0x8A, 0, 7),
4633d0407baSopenharmony_ci    [Q_OCV_H2] = REG_FIELD(0x8B, 0, 7),
4643d0407baSopenharmony_ci
4653d0407baSopenharmony_ci    [Q_OCV_L1] = REG_FIELD(0x8C, 0, 7),
4663d0407baSopenharmony_ci    [Q_OCV_L0] = REG_FIELD(0x8D, 0, 7),
4673d0407baSopenharmony_ci    [OCV_CNT] = REG_FIELD(0x8E, 0, 7),
4683d0407baSopenharmony_ci    [SLEEP_CON_SAMP_CUR_H] = REG_FIELD(0x8F, 0, 7),
4693d0407baSopenharmony_ci    [SLEEP_CON_SAMP_CUR_L] = REG_FIELD(0x90, 0, 7),
4703d0407baSopenharmony_ci    [CAL_OFFSET_H] = REG_FIELD(0x91, 0, 7),
4713d0407baSopenharmony_ci    [CAL_OFFSET_L] = REG_FIELD(0x92, 0, 7),
4723d0407baSopenharmony_ci    [VCALIB0_H] = REG_FIELD(0x93, 0, 7),
4733d0407baSopenharmony_ci    [VCALIB0_L] = REG_FIELD(0x94, 0, 7),
4743d0407baSopenharmony_ci    [VCALIB1_H] = REG_FIELD(0x95, 0, 7),
4753d0407baSopenharmony_ci    [VCALIB1_L] = REG_FIELD(0x96, 0, 7),
4763d0407baSopenharmony_ci    [IOFFSET_H] = REG_FIELD(0x97, 0, 7),
4773d0407baSopenharmony_ci    [IOFFSET_L] = REG_FIELD(0x98, 0, 7),
4783d0407baSopenharmony_ci
4793d0407baSopenharmony_ci    [BAT_R0] = REG_FIELD(0x99, 0, 7),
4803d0407baSopenharmony_ci    [SOC_REG0] = REG_FIELD(0x9A, 0, 7),
4813d0407baSopenharmony_ci    [SOC_REG1] = REG_FIELD(0x9B, 0, 7),
4823d0407baSopenharmony_ci    [SOC_REG2] = REG_FIELD(0x9C, 0, 7),
4833d0407baSopenharmony_ci
4843d0407baSopenharmony_ci    [REMAIN_CAP_REG0] = REG_FIELD(0x9D, 0, 7),
4853d0407baSopenharmony_ci    [REMAIN_CAP_REG1] = REG_FIELD(0x9E, 0, 7),
4863d0407baSopenharmony_ci    [REMAIN_CAP_REG2] = REG_FIELD(0x9F, 0, 7),
4873d0407baSopenharmony_ci    [NEW_FCC_REG0] = REG_FIELD(0xA0, 0, 7),
4883d0407baSopenharmony_ci    [NEW_FCC_REG1] = REG_FIELD(0xA1, 0, 7),
4893d0407baSopenharmony_ci    [NEW_FCC_REG2] = REG_FIELD(0xA2, 0, 7),
4903d0407baSopenharmony_ci    [RESET_MODE] = REG_FIELD(0xA3, 0, 3),
4913d0407baSopenharmony_ci    [FG_INIT] = REG_FIELD(0xA5, 7, 7),
4923d0407baSopenharmony_ci
4933d0407baSopenharmony_ci    [HALT_CNT_REG] = REG_FIELD(0xA6, 0, 7),
4943d0407baSopenharmony_ci    [CALC_REST_REGL] = REG_FIELD(0xA7, 0, 7),
4953d0407baSopenharmony_ci    [CALC_REST_REGH] = REG_FIELD(0xA8, 0, 7),
4963d0407baSopenharmony_ci
4973d0407baSopenharmony_ci    [VOL_ADC_B3] = REG_FIELD(0xA9, 0, 7),
4983d0407baSopenharmony_ci    [VOL_ADC_B2] = REG_FIELD(0xAA, 0, 7),
4993d0407baSopenharmony_ci    [VOL_ADC_B1] = REG_FIELD(0xAB, 0, 7),
5003d0407baSopenharmony_ci    [VOL_ADC_B0] = REG_FIELD(0xAC, 0, 7),
5013d0407baSopenharmony_ci
5023d0407baSopenharmony_ci    [VOL_ADC_K3] = REG_FIELD(0xAD, 0, 7),
5033d0407baSopenharmony_ci    [VOL_ADC_K2] = REG_FIELD(0xAE, 0, 7),
5043d0407baSopenharmony_ci    [VOL_ADC_K1] = REG_FIELD(0xAF, 0, 7),
5053d0407baSopenharmony_ci    [VOL_ADC_K0] = REG_FIELD(0xB0, 0, 7),
5063d0407baSopenharmony_ci    [BAT_EXS] = REG_FIELD(0xEB, 7, 7),
5073d0407baSopenharmony_ci    [CHG_STS] = REG_FIELD(0xEB, 4, 6),
5083d0407baSopenharmony_ci    [BAT_OVP_STS] = REG_FIELD(0xEB, 3, 3),
5093d0407baSopenharmony_ci    [CHRG_IN_CLAMP] = REG_FIELD(0xEB, 2, 2),
5103d0407baSopenharmony_ci    [CHIP_NAME_H] = REG_FIELD(0xED, 0, 7),
5113d0407baSopenharmony_ci    [CHIP_NAME_L] = REG_FIELD(0xEE, 0, 7),
5123d0407baSopenharmony_ci    [PLUG_IN_STS] = REG_FIELD(0xF0, 6, 6),
5133d0407baSopenharmony_ci};
5143d0407baSopenharmony_ci
5153d0407baSopenharmony_cistruct battery_platform_data {
5163d0407baSopenharmony_ci    u32 *ocv_table;
5173d0407baSopenharmony_ci    u32 *zero_table;
5183d0407baSopenharmony_ci
5193d0407baSopenharmony_ci    u32 table_t[4][21];
5203d0407baSopenharmony_ci    int temp_t[4];
5213d0407baSopenharmony_ci    u32 temp_t_num;
5223d0407baSopenharmony_ci
5233d0407baSopenharmony_ci    u32 *ntc_table;
5243d0407baSopenharmony_ci    u32 ocv_size;
5253d0407baSopenharmony_ci    u32 ntc_size;
5263d0407baSopenharmony_ci    int ntc_degree_from;
5273d0407baSopenharmony_ci    u32 ntc_factor;
5283d0407baSopenharmony_ci    u32 max_input_current;
5293d0407baSopenharmony_ci    u32 max_chrg_current;
5303d0407baSopenharmony_ci    u32 max_chrg_voltage;
5313d0407baSopenharmony_ci    u32 lp_input_current;
5323d0407baSopenharmony_ci    u32 lp_soc_min;
5333d0407baSopenharmony_ci    u32 lp_soc_max;
5343d0407baSopenharmony_ci    u32 pwroff_vol;
5353d0407baSopenharmony_ci    u32 monitor_sec;
5363d0407baSopenharmony_ci    u32 zero_algorithm_vol;
5373d0407baSopenharmony_ci    u32 zero_reserve_dsoc;
5383d0407baSopenharmony_ci    u32 bat_res;
5393d0407baSopenharmony_ci    u32 design_capacity;
5403d0407baSopenharmony_ci    u32 design_qmax;
5413d0407baSopenharmony_ci    u32 sleep_enter_current;
5423d0407baSopenharmony_ci    u32 sleep_exit_current;
5433d0407baSopenharmony_ci    u32 sleep_filter_current;
5443d0407baSopenharmony_ci
5453d0407baSopenharmony_ci    u32 power_dc2otg;
5463d0407baSopenharmony_ci    u32 max_soc_offset;
5473d0407baSopenharmony_ci    u32 bat_mode;
5483d0407baSopenharmony_ci    u32 fb_temp;
5493d0407baSopenharmony_ci    u32 energy_mode;
5503d0407baSopenharmony_ci    u32 cccv_hour;
5513d0407baSopenharmony_ci    u32 dc_det_adc;
5523d0407baSopenharmony_ci    int dc_det_pin;
5533d0407baSopenharmony_ci    u8 dc_det_level;
5543d0407baSopenharmony_ci    u32 sample_res;
5553d0407baSopenharmony_ci    u32 bat_res_up;
5563d0407baSopenharmony_ci    u32 bat_res_down;
5573d0407baSopenharmony_ci    u32 design_max_voltage;
5583d0407baSopenharmony_ci    bool extcon;
5593d0407baSopenharmony_ci    u32 low_pwr_sleep;
5603d0407baSopenharmony_ci};
5613d0407baSopenharmony_ci
5623d0407baSopenharmony_cistruct rk817_battery_device {
5633d0407baSopenharmony_ci    struct platform_device *pdev;
5643d0407baSopenharmony_ci    struct device *dev;
5653d0407baSopenharmony_ci    struct i2c_client *client;
5663d0407baSopenharmony_ci    struct rk808 *rk817;
5673d0407baSopenharmony_ci    struct power_supply *bat;
5683d0407baSopenharmony_ci    struct power_supply *chg_psy;
5693d0407baSopenharmony_ci    struct power_supply *usb_psy;
5703d0407baSopenharmony_ci    struct power_supply *ac_psy;
5713d0407baSopenharmony_ci    struct regmap *regmap;
5723d0407baSopenharmony_ci    struct regmap_field *rmap_fields[F_MAX_FIELDS];
5733d0407baSopenharmony_ci    struct battery_platform_data *pdata;
5743d0407baSopenharmony_ci    struct workqueue_struct *bat_monitor_wq;
5753d0407baSopenharmony_ci    struct delayed_work bat_delay_work;
5763d0407baSopenharmony_ci    struct delayed_work calib_delay_work;
5773d0407baSopenharmony_ci    struct work_struct resume_work;
5783d0407baSopenharmony_ci    struct wake_lock wake_lock;
5793d0407baSopenharmony_ci    struct timer_list caltimer;
5803d0407baSopenharmony_ci
5813d0407baSopenharmony_ci    int res_div;
5823d0407baSopenharmony_ci    int bat_res;
5833d0407baSopenharmony_ci    bool is_first_power_on;
5843d0407baSopenharmony_ci    int chrg_status;
5853d0407baSopenharmony_ci    int res_fac;
5863d0407baSopenharmony_ci    int over_20mR;
5873d0407baSopenharmony_ci    bool is_initialized;
5883d0407baSopenharmony_ci    bool bat_first_power_on;
5893d0407baSopenharmony_ci    u8 ac_in;
5903d0407baSopenharmony_ci    u8 usb_in;
5913d0407baSopenharmony_ci    u8 otg_in;
5923d0407baSopenharmony_ci    u8 dc_in;
5933d0407baSopenharmony_ci    u8 prop_status;
5943d0407baSopenharmony_ci    int cvtlmt_irq;
5953d0407baSopenharmony_ci    int current_avg;
5963d0407baSopenharmony_ci    int current_relax;
5973d0407baSopenharmony_ci    int voltage_usb;
5983d0407baSopenharmony_ci    int voltage_sys;
5993d0407baSopenharmony_ci    int voltage_avg;
6003d0407baSopenharmony_ci    int voltage_ocv;
6013d0407baSopenharmony_ci    int voltage_relax;
6023d0407baSopenharmony_ci    int voltage_k; /* VCALIB0 VCALIB1 */
6033d0407baSopenharmony_ci    int voltage_b;
6043d0407baSopenharmony_ci    u32 remain_cap;
6053d0407baSopenharmony_ci    int design_cap;
6063d0407baSopenharmony_ci    int nac;
6073d0407baSopenharmony_ci    int fcc;
6083d0407baSopenharmony_ci    int lock_fcc;
6093d0407baSopenharmony_ci    int qmax;
6103d0407baSopenharmony_ci    int dsoc;
6113d0407baSopenharmony_ci    int rsoc;
6123d0407baSopenharmony_ci    int poffset;
6133d0407baSopenharmony_ci    int fake_offline;
6143d0407baSopenharmony_ci    int age_ocv_soc;
6153d0407baSopenharmony_ci    bool age_allow_update;
6163d0407baSopenharmony_ci    int age_level;
6173d0407baSopenharmony_ci    int age_ocv_cap;
6183d0407baSopenharmony_ci    int pwron_voltage;
6193d0407baSopenharmony_ci    int age_voltage;
6203d0407baSopenharmony_ci    int age_adjust_cap;
6213d0407baSopenharmony_ci    unsigned long age_keep_sec;
6223d0407baSopenharmony_ci    int zero_timeout_cnt;
6233d0407baSopenharmony_ci    int zero_remain_cap;
6243d0407baSopenharmony_ci    int zero_dsoc;
6253d0407baSopenharmony_ci    int zero_linek;
6263d0407baSopenharmony_ci    u64 zero_drop_sec;
6273d0407baSopenharmony_ci    u64 shtd_drop_sec;
6283d0407baSopenharmony_ci
6293d0407baSopenharmony_ci    int powerpatch_res;
6303d0407baSopenharmony_ci    int zero_voltage_avg;
6313d0407baSopenharmony_ci    int zero_current_avg;
6323d0407baSopenharmony_ci    int zero_vsys;
6333d0407baSopenharmony_ci    int zero_dead_voltage;
6343d0407baSopenharmony_ci    int zero_dead_soc;
6353d0407baSopenharmony_ci    int zero_dead_cap;
6363d0407baSopenharmony_ci    int zero_batvol_to_ocv;
6373d0407baSopenharmony_ci    int zero_batocv_to_soc;
6383d0407baSopenharmony_ci    int zero_batocv_to_cap;
6393d0407baSopenharmony_ci    int zero_xsoc;
6403d0407baSopenharmony_ci    unsigned long finish_base;
6413d0407baSopenharmony_ci    time64_t rtc_base;
6423d0407baSopenharmony_ci    int sm_remain_cap;
6433d0407baSopenharmony_ci    int sm_linek;
6443d0407baSopenharmony_ci    int sm_chrg_dsoc;
6453d0407baSopenharmony_ci    int sm_dischrg_dsoc;
6463d0407baSopenharmony_ci    int smooth_soc;
6473d0407baSopenharmony_ci    int algo_rest_val;
6483d0407baSopenharmony_ci    int algo_rest_mode;
6493d0407baSopenharmony_ci    int sleep_sum_cap;
6503d0407baSopenharmony_ci    int sleep_remain_cap;
6513d0407baSopenharmony_ci    unsigned long sleep_dischrg_sec;
6523d0407baSopenharmony_ci    unsigned long sleep_sum_sec;
6533d0407baSopenharmony_ci    bool sleep_chrg_online;
6543d0407baSopenharmony_ci    u8 sleep_chrg_status;
6553d0407baSopenharmony_ci    bool adc_allow_update;
6563d0407baSopenharmony_ci    int fb_blank;
6573d0407baSopenharmony_ci    bool s2r; /* suspend to resume */
6583d0407baSopenharmony_ci    u32 work_mode;
6593d0407baSopenharmony_ci    int temperature;
6603d0407baSopenharmony_ci    int chrg_cur_lp_input;
6613d0407baSopenharmony_ci    int chrg_vol_sel;
6623d0407baSopenharmony_ci    int chrg_cur_input;
6633d0407baSopenharmony_ci    int chrg_cur_sel;
6643d0407baSopenharmony_ci    u32 monitor_ms;
6653d0407baSopenharmony_ci    u32 pwroff_min;
6663d0407baSopenharmony_ci    u32 adc_calib_cnt;
6673d0407baSopenharmony_ci    unsigned long chrg_finish_base;
6683d0407baSopenharmony_ci    unsigned long boot_base;
6693d0407baSopenharmony_ci    unsigned long flat_match_sec;
6703d0407baSopenharmony_ci    unsigned long plug_in_base;
6713d0407baSopenharmony_ci    unsigned long plug_out_base;
6723d0407baSopenharmony_ci    u8 halt_cnt;
6733d0407baSopenharmony_ci    bool is_halt;
6743d0407baSopenharmony_ci    bool is_max_soc_offset;
6753d0407baSopenharmony_ci    bool is_sw_reset;
6763d0407baSopenharmony_ci    bool is_ocv_calib;
6773d0407baSopenharmony_ci    bool is_first_on;
6783d0407baSopenharmony_ci    bool is_force_calib;
6793d0407baSopenharmony_ci    int last_dsoc;
6803d0407baSopenharmony_ci    u8 cvtlmt_int_event;
6813d0407baSopenharmony_ci    u8 slp_dcdc_en_reg;
6823d0407baSopenharmony_ci    int ocv_pre_dsoc;
6833d0407baSopenharmony_ci    int ocv_new_dsoc;
6843d0407baSopenharmony_ci    int max_pre_dsoc;
6853d0407baSopenharmony_ci    int max_new_dsoc;
6863d0407baSopenharmony_ci    int force_pre_dsoc;
6873d0407baSopenharmony_ci    int force_new_dsoc;
6883d0407baSopenharmony_ci
6893d0407baSopenharmony_ci    int dbg_cap_low0;
6903d0407baSopenharmony_ci    int dbg_pwr_dsoc;
6913d0407baSopenharmony_ci    int dbg_pwr_rsoc;
6923d0407baSopenharmony_ci    int dbg_pwr_vol;
6933d0407baSopenharmony_ci    int dbg_chrg_min[10];
6943d0407baSopenharmony_ci    int dbg_meet_soc;
6953d0407baSopenharmony_ci    int dbg_calc_dsoc;
6963d0407baSopenharmony_ci    int dbg_calc_rsoc;
6973d0407baSopenharmony_ci    int is_charging;
6983d0407baSopenharmony_ci    unsigned long charge_count;
6993d0407baSopenharmony_ci    u8 plugin_trigger;
7003d0407baSopenharmony_ci    u8 plugout_trigger;
7013d0407baSopenharmony_ci    int plugin_irq;
7023d0407baSopenharmony_ci    int plugout_irq;
7033d0407baSopenharmony_ci    int chip_id;
7043d0407baSopenharmony_ci    int is_register_chg_psy;
7053d0407baSopenharmony_ci    bool change; /* Battery status change, report information */
7063d0407baSopenharmony_ci};
7073d0407baSopenharmony_ci
7083d0407baSopenharmony_cistatic void rk817_bat_resume_work(struct work_struct *work);
7093d0407baSopenharmony_ci
7103d0407baSopenharmony_cistatic u64 get_boot_sec(void)
7113d0407baSopenharmony_ci{
7123d0407baSopenharmony_ci    struct timespec64 ts;
7133d0407baSopenharmony_ci
7143d0407baSopenharmony_ci    ktime_get_boottime_ts64(&ts);
7153d0407baSopenharmony_ci
7163d0407baSopenharmony_ci    return ts.tv_sec;
7173d0407baSopenharmony_ci}
7183d0407baSopenharmony_ci
7193d0407baSopenharmony_cistatic unsigned long base2sec(unsigned long x)
7203d0407baSopenharmony_ci{
7213d0407baSopenharmony_ci    if (x) {
7223d0407baSopenharmony_ci        return (get_boot_sec() > x) ? (get_boot_sec() - x) : 0;
7233d0407baSopenharmony_ci    } else {
7243d0407baSopenharmony_ci        return 0;
7253d0407baSopenharmony_ci    }
7263d0407baSopenharmony_ci}
7273d0407baSopenharmony_ci
7283d0407baSopenharmony_cistatic u32 interpolate(int value, u32 *table, int size)
7293d0407baSopenharmony_ci{
7303d0407baSopenharmony_ci    u8 i;
7313d0407baSopenharmony_ci    u16 d;
7323d0407baSopenharmony_ci
7333d0407baSopenharmony_ci    for (i = 0; i < size; i++) {
7343d0407baSopenharmony_ci        if (value < table[i]) {
7353d0407baSopenharmony_ci            break;
7363d0407baSopenharmony_ci        }
7373d0407baSopenharmony_ci    }
7383d0407baSopenharmony_ci
7393d0407baSopenharmony_ci    if ((i > 0) && (i < size)) {
7403d0407baSopenharmony_ci        d = (value - table[i - 1]) * (MAX_INTERPOLATE / (size - 1));
7413d0407baSopenharmony_ci        d /= table[i] - table[i - 1];
7423d0407baSopenharmony_ci        d = d + (i - 1) * (MAX_INTERPOLATE / (size - 1));
7433d0407baSopenharmony_ci    } else {
7443d0407baSopenharmony_ci        d = i * ((MAX_INTERPOLATE + size / 0x02) / size);
7453d0407baSopenharmony_ci    }
7463d0407baSopenharmony_ci
7473d0407baSopenharmony_ci    if (d > 0x3E8) {
7483d0407baSopenharmony_ci        d = 0x3E8;
7493d0407baSopenharmony_ci    }
7503d0407baSopenharmony_ci
7513d0407baSopenharmony_ci    return d;
7523d0407baSopenharmony_ci}
7533d0407baSopenharmony_ci
7543d0407baSopenharmony_ci/* (a * b) / c */
7553d0407baSopenharmony_cistatic int32_t ab_div_c(u32 a, u32 b, u32 c)
7563d0407baSopenharmony_ci{
7573d0407baSopenharmony_ci    bool sign;
7583d0407baSopenharmony_ci    u32 ans = MAX_INT;
7593d0407baSopenharmony_ci    int tmp;
7603d0407baSopenharmony_ci
7613d0407baSopenharmony_ci    sign = ((((a ^ b) ^ c) & 0x80000000) != 0);
7623d0407baSopenharmony_ci    if (c != 0) {
7633d0407baSopenharmony_ci        if (sign) {
7643d0407baSopenharmony_ci            c = -c;
7653d0407baSopenharmony_ci        }
7663d0407baSopenharmony_ci        tmp = (a * b + (c >> 1)) / c;
7673d0407baSopenharmony_ci        if (tmp < MAX_INT) {
7683d0407baSopenharmony_ci            ans = tmp;
7693d0407baSopenharmony_ci        }
7703d0407baSopenharmony_ci    }
7713d0407baSopenharmony_ci
7723d0407baSopenharmony_ci    if (sign) {
7733d0407baSopenharmony_ci        ans = -ans;
7743d0407baSopenharmony_ci    }
7753d0407baSopenharmony_ci
7763d0407baSopenharmony_ci    return ans;
7773d0407baSopenharmony_ci}
7783d0407baSopenharmony_ci
7793d0407baSopenharmony_cistatic int rk817_bat_field_read(struct rk817_battery_device *battery, enum rk817_battery_fields field_id)
7803d0407baSopenharmony_ci{
7813d0407baSopenharmony_ci    int val;
7823d0407baSopenharmony_ci    int ret;
7833d0407baSopenharmony_ci
7843d0407baSopenharmony_ci    ret = regmap_field_read(battery->rmap_fields[field_id], &val);
7853d0407baSopenharmony_ci    if (ret < 0) {
7863d0407baSopenharmony_ci        return ret;
7873d0407baSopenharmony_ci    }
7883d0407baSopenharmony_ci
7893d0407baSopenharmony_ci    return val;
7903d0407baSopenharmony_ci}
7913d0407baSopenharmony_ci
7923d0407baSopenharmony_cistatic int rk817_bat_field_write(struct rk817_battery_device *battery, enum rk817_battery_fields field_id,
7933d0407baSopenharmony_ci                                 unsigned int val)
7943d0407baSopenharmony_ci{
7953d0407baSopenharmony_ci    return regmap_field_write(battery->rmap_fields[field_id], val);
7963d0407baSopenharmony_ci}
7973d0407baSopenharmony_ci
7983d0407baSopenharmony_ci/* cal_offset: current offset value */
7993d0407baSopenharmony_cistatic int rk817_bat_get_coffset(struct rk817_battery_device *battery)
8003d0407baSopenharmony_ci{
8013d0407baSopenharmony_ci    int coffset_value = 0;
8023d0407baSopenharmony_ci
8033d0407baSopenharmony_ci    coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_H) << 0x08;
8043d0407baSopenharmony_ci    coffset_value |= rk817_bat_field_read(battery, CAL_OFFSET_L);
8053d0407baSopenharmony_ci
8063d0407baSopenharmony_ci    return coffset_value;
8073d0407baSopenharmony_ci}
8083d0407baSopenharmony_ci
8093d0407baSopenharmony_cistatic void rk817_bat_set_coffset(struct rk817_battery_device *battery, int val)
8103d0407baSopenharmony_ci{
8113d0407baSopenharmony_ci    u8 buf = 0;
8123d0407baSopenharmony_ci
8133d0407baSopenharmony_ci    buf = (val >> 0x08) & 0xff;
8143d0407baSopenharmony_ci    rk817_bat_field_write(battery, CAL_OFFSET_H, buf);
8153d0407baSopenharmony_ci    buf = (val >> 0) & 0xff;
8163d0407baSopenharmony_ci    rk817_bat_field_write(battery, CAL_OFFSET_L, buf);
8173d0407baSopenharmony_ci}
8183d0407baSopenharmony_ci
8193d0407baSopenharmony_ci/* current offset value calculated */
8203d0407baSopenharmony_cistatic int rk817_bat_get_ioffset(struct rk817_battery_device *battery)
8213d0407baSopenharmony_ci{
8223d0407baSopenharmony_ci    int ioffset_value = 0;
8233d0407baSopenharmony_ci
8243d0407baSopenharmony_ci    ioffset_value |= rk817_bat_field_read(battery, IOFFSET_H) << 0x08;
8253d0407baSopenharmony_ci    ioffset_value |= rk817_bat_field_read(battery, IOFFSET_L);
8263d0407baSopenharmony_ci
8273d0407baSopenharmony_ci    return ioffset_value;
8283d0407baSopenharmony_ci}
8293d0407baSopenharmony_ci
8303d0407baSopenharmony_cistatic void rk817_bat_current_calibration(struct rk817_battery_device *battery)
8313d0407baSopenharmony_ci{
8323d0407baSopenharmony_ci    int pwron_value, ioffset, cal_offset;
8333d0407baSopenharmony_ci
8343d0407baSopenharmony_ci    pwron_value = rk817_bat_field_read(battery, PWRON_CUR_H) << 0x08;
8353d0407baSopenharmony_ci    pwron_value |= rk817_bat_field_read(battery, PWRON_CUR_L);
8363d0407baSopenharmony_ci
8373d0407baSopenharmony_ci    ioffset = rk817_bat_get_ioffset(battery);
8383d0407baSopenharmony_ci
8393d0407baSopenharmony_ci    DBG("Caloffset: 0x%x\n", rk817_bat_get_coffset(battery));
8403d0407baSopenharmony_ci    DBG("IOFFSET: 0x%x\n", ioffset);
8413d0407baSopenharmony_ci    if (0) {
8423d0407baSopenharmony_ci        cal_offset = pwron_value + ioffset;
8433d0407baSopenharmony_ci    } else {
8443d0407baSopenharmony_ci        cal_offset = ioffset;
8453d0407baSopenharmony_ci    }
8463d0407baSopenharmony_ci
8473d0407baSopenharmony_ci    rk817_bat_set_coffset(battery, cal_offset);
8483d0407baSopenharmony_ci    DBG("Caloffset: 0x%x\n", rk817_bat_get_coffset(battery));
8493d0407baSopenharmony_ci}
8503d0407baSopenharmony_ci
8513d0407baSopenharmony_cistatic int rk817_bat_get_vaclib0(struct rk817_battery_device *battery)
8523d0407baSopenharmony_ci{
8533d0407baSopenharmony_ci    int vcalib_value = 0;
8543d0407baSopenharmony_ci
8553d0407baSopenharmony_ci    vcalib_value |= rk817_bat_field_read(battery, VCALIB0_H) << 0x08;
8563d0407baSopenharmony_ci    vcalib_value |= rk817_bat_field_read(battery, VCALIB0_L);
8573d0407baSopenharmony_ci
8583d0407baSopenharmony_ci    return vcalib_value;
8593d0407baSopenharmony_ci}
8603d0407baSopenharmony_ci
8613d0407baSopenharmony_cistatic int rk817_bat_get_vaclib1(struct rk817_battery_device *battery)
8623d0407baSopenharmony_ci{
8633d0407baSopenharmony_ci    int vcalib_value = 0;
8643d0407baSopenharmony_ci
8653d0407baSopenharmony_ci    vcalib_value |= rk817_bat_field_read(battery, VCALIB1_H) << 0x08;
8663d0407baSopenharmony_ci    vcalib_value |= rk817_bat_field_read(battery, VCALIB1_L);
8673d0407baSopenharmony_ci
8683d0407baSopenharmony_ci    return vcalib_value;
8693d0407baSopenharmony_ci}
8703d0407baSopenharmony_ci
8713d0407baSopenharmony_cistatic void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery)
8723d0407baSopenharmony_ci{
8733d0407baSopenharmony_ci    int vcalib0, vcalib1;
8743d0407baSopenharmony_ci
8753d0407baSopenharmony_ci    vcalib0 = rk817_bat_get_vaclib0(battery);
8763d0407baSopenharmony_ci    vcalib1 = rk817_bat_get_vaclib1(battery);
8773d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
8783d0407baSopenharmony_ci        battery->voltage_k = (0x41A - 0x258) * 0x3E8 / DIV(vcalib1 - vcalib0);
8793d0407baSopenharmony_ci        battery->voltage_b = 0x41A - (battery->voltage_k * vcalib1) / 0x3E8;
8803d0407baSopenharmony_ci    } else {
8813d0407baSopenharmony_ci        battery->voltage_k = (0xFB9 - 0x8FC) * 0x3E8 / DIV(vcalib1 - vcalib0);
8823d0407baSopenharmony_ci        battery->voltage_b = 0xFB9 - (battery->voltage_k * vcalib1) / 0x3E8;
8833d0407baSopenharmony_ci    }
8843d0407baSopenharmony_ci}
8853d0407baSopenharmony_ci
8863d0407baSopenharmony_cistatic void rk817_bat_restart_relax(struct rk817_battery_device *battery)
8873d0407baSopenharmony_ci{
8883d0407baSopenharmony_ci    rk817_bat_field_write(battery, RELAX_VOL1_UPD, 0x00);
8893d0407baSopenharmony_ci    rk817_bat_field_write(battery, RELAX_VOL2_UPD, 0x00);
8903d0407baSopenharmony_ci}
8913d0407baSopenharmony_ci
8923d0407baSopenharmony_cistatic bool is_rk817_bat_relax_mode(struct rk817_battery_device *battery)
8933d0407baSopenharmony_ci{
8943d0407baSopenharmony_ci    u8 relax_sts, relax_vol1_upd, relax_vol2_upd;
8953d0407baSopenharmony_ci
8963d0407baSopenharmony_ci    relax_sts = rk817_bat_field_read(battery, RELAX_STS);
8973d0407baSopenharmony_ci    relax_vol1_upd = rk817_bat_field_read(battery, RELAX_VOL1_UPD);
8983d0407baSopenharmony_ci    relax_vol2_upd = rk817_bat_field_read(battery, RELAX_VOL2_UPD);
8993d0407baSopenharmony_ci
9003d0407baSopenharmony_ci    DBG("RELAX_STS: %d\n", relax_sts);
9013d0407baSopenharmony_ci    DBG("RELAX_VOL1_UPD: %d\n", relax_vol1_upd);
9023d0407baSopenharmony_ci    DBG("RELAX_VOL2_UPD: %d\n", relax_vol2_upd);
9033d0407baSopenharmony_ci    if (relax_sts && relax_vol1_upd && relax_vol2_upd) {
9043d0407baSopenharmony_ci        return true;
9053d0407baSopenharmony_ci    } else {
9063d0407baSopenharmony_ci        return false;
9073d0407baSopenharmony_ci    }
9083d0407baSopenharmony_ci}
9093d0407baSopenharmony_ci
9103d0407baSopenharmony_cistatic u16 rk817_bat_get_relax_vol1(struct rk817_battery_device *battery)
9113d0407baSopenharmony_ci{
9123d0407baSopenharmony_ci    u16 vol, val = 0;
9133d0407baSopenharmony_ci
9143d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, RELAX_VOL1_H) << 0x08;
9153d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, RELAX_VOL1_L);
9163d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0x3E8 + battery->voltage_b;
9173d0407baSopenharmony_ci
9183d0407baSopenharmony_ci    return vol;
9193d0407baSopenharmony_ci}
9203d0407baSopenharmony_ci
9213d0407baSopenharmony_cistatic u16 rk817_bat_get_relax_vol2(struct rk817_battery_device *battery)
9223d0407baSopenharmony_ci{
9233d0407baSopenharmony_ci    u16 vol, val = 0;
9243d0407baSopenharmony_ci
9253d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, RELAX_VOL2_H) << 0x08;
9263d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, RELAX_VOL2_L);
9273d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0x3E8 + battery->voltage_b;
9283d0407baSopenharmony_ci
9293d0407baSopenharmony_ci    return vol;
9303d0407baSopenharmony_ci}
9313d0407baSopenharmony_ci
9323d0407baSopenharmony_cistatic u16 rk817_bat_get_relax_voltage(struct rk817_battery_device *battery)
9333d0407baSopenharmony_ci{
9343d0407baSopenharmony_ci    u16 relax_vol1, relax_vol2;
9353d0407baSopenharmony_ci
9363d0407baSopenharmony_ci    if (!is_rk817_bat_relax_mode(battery)) {
9373d0407baSopenharmony_ci        return 0;
9383d0407baSopenharmony_ci    }
9393d0407baSopenharmony_ci
9403d0407baSopenharmony_ci    relax_vol1 = rk817_bat_get_relax_vol1(battery);
9413d0407baSopenharmony_ci    relax_vol2 = rk817_bat_get_relax_vol2(battery);
9423d0407baSopenharmony_ci
9433d0407baSopenharmony_ci    return relax_vol1 > relax_vol2 ? relax_vol1 : relax_vol2;
9443d0407baSopenharmony_ci}
9453d0407baSopenharmony_ci
9463d0407baSopenharmony_cistatic void rk817_bat_set_relax_sample(struct rk817_battery_device *battery)
9473d0407baSopenharmony_ci{
9483d0407baSopenharmony_ci    u8 buf;
9493d0407baSopenharmony_ci    int enter_thres, filter_thres;
9503d0407baSopenharmony_ci    struct battery_platform_data *pdata = battery->pdata;
9513d0407baSopenharmony_ci
9523d0407baSopenharmony_ci    filter_thres = pdata->sleep_filter_current * 0x3E8 / 0X5E2;
9533d0407baSopenharmony_ci
9543d0407baSopenharmony_ci    enter_thres = CURRENT_TO_ADC(pdata->sleep_enter_current, battery->res_div);
9553d0407baSopenharmony_ci    filter_thres = CURRENT_TO_ADC(pdata->sleep_filter_current, battery->res_div);
9563d0407baSopenharmony_ci
9573d0407baSopenharmony_ci    /* set relax enter and exit threshold */
9583d0407baSopenharmony_ci    buf = (enter_thres >> 0x08) & 0xff;
9593d0407baSopenharmony_ci    rk817_bat_field_write(battery, RELAX_THRE_H, buf);
9603d0407baSopenharmony_ci    buf = enter_thres & 0xff;
9613d0407baSopenharmony_ci    rk817_bat_field_write(battery, RELAX_THRE_L, buf);
9623d0407baSopenharmony_ci    /* set sample current threshold */
9633d0407baSopenharmony_ci    buf = (filter_thres >> 0x08) & 0xff;
9643d0407baSopenharmony_ci    rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_H, buf);
9653d0407baSopenharmony_ci    buf = filter_thres & 0xff;
9663d0407baSopenharmony_ci    rk817_bat_field_write(battery, SLEEP_CON_SAMP_CUR_L, buf);
9673d0407baSopenharmony_ci
9683d0407baSopenharmony_ci    /* reset relax update state */
9693d0407baSopenharmony_ci    rk817_bat_restart_relax(battery);
9703d0407baSopenharmony_ci    DBG("<%s>. sleep_enter_current = %d, sleep_exit_current = %d\n", __func__, pdata->sleep_enter_current,
9713d0407baSopenharmony_ci        pdata->sleep_exit_current);
9723d0407baSopenharmony_ci}
9733d0407baSopenharmony_ci
9743d0407baSopenharmony_ci/* runtime OCV voltage,  |RLX_VOL2 - RLX_VOL1| < OCV_THRE,
9753d0407baSopenharmony_ci * the OCV reg update every 120s
9763d0407baSopenharmony_ci */
9773d0407baSopenharmony_cistatic void rk817_bat_ocv_thre(struct rk817_battery_device *battery, int value)
9783d0407baSopenharmony_ci{
9793d0407baSopenharmony_ci    rk817_bat_field_write(battery, OCV_THRE_VOL, value);
9803d0407baSopenharmony_ci}
9813d0407baSopenharmony_ci
9823d0407baSopenharmony_cistatic int rk817_bat_get_ocv_voltage(struct rk817_battery_device *battery)
9833d0407baSopenharmony_ci{
9843d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
9853d0407baSopenharmony_ci
9863d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, OCV_VOL_H) << 0x08;
9873d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, OCV_VOL_L);
9883d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0X3E8 + battery->voltage_b;
9893d0407baSopenharmony_ci
9903d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
9913d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
9923d0407baSopenharmony_ci        vol = vol_temp;
9933d0407baSopenharmony_ci    }
9943d0407baSopenharmony_ci
9953d0407baSopenharmony_ci    return vol;
9963d0407baSopenharmony_ci}
9973d0407baSopenharmony_ci
9983d0407baSopenharmony_cistatic int rk817_bat_get_ocv0_voltage0(struct rk817_battery_device *battery)
9993d0407baSopenharmony_ci{
10003d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
10013d0407baSopenharmony_ci
10023d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, OCV_VOL0_H) << 0x08;
10033d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, OCV_VOL0_L);
10043d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0X3E8 + battery->voltage_b;
10053d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
10063d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
10073d0407baSopenharmony_ci        vol = vol_temp;
10083d0407baSopenharmony_ci    }
10093d0407baSopenharmony_ci
10103d0407baSopenharmony_ci    return vol;
10113d0407baSopenharmony_ci}
10123d0407baSopenharmony_ci
10133d0407baSopenharmony_ci/* power on battery voltage */
10143d0407baSopenharmony_cistatic int rk817_bat_get_pwron_voltage(struct rk817_battery_device *battery)
10153d0407baSopenharmony_ci{
10163d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
10173d0407baSopenharmony_ci
10183d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, PWRON_VOL_H) << 0x08;
10193d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, PWRON_VOL_L);
10203d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0x3E8 + battery->voltage_b;
10213d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
10223d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
10233d0407baSopenharmony_ci        vol = vol_temp;
10243d0407baSopenharmony_ci    }
10253d0407baSopenharmony_ci
10263d0407baSopenharmony_ci    return vol;
10273d0407baSopenharmony_ci}
10283d0407baSopenharmony_ci
10293d0407baSopenharmony_cistatic int rk817_bat_get_battery_voltage(struct rk817_battery_device *battery)
10303d0407baSopenharmony_ci{
10313d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
10323d0407baSopenharmony_ci    int vcalib0, vcalib1;
10333d0407baSopenharmony_ci
10343d0407baSopenharmony_ci    vcalib0 = rk817_bat_get_vaclib0(battery);
10353d0407baSopenharmony_ci    vcalib1 = rk817_bat_get_vaclib1(battery);
10363d0407baSopenharmony_ci
10373d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, BAT_VOL_H) << 0x08;
10383d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, BAT_VOL_L) << 0;
10393d0407baSopenharmony_ci
10403d0407baSopenharmony_ci    vol = battery->voltage_k * val / 0x3E8 + battery->voltage_b;
10413d0407baSopenharmony_ci
10423d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
10433d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
10443d0407baSopenharmony_ci        vol = vol_temp;
10453d0407baSopenharmony_ci    }
10463d0407baSopenharmony_ci
10473d0407baSopenharmony_ci    return vol;
10483d0407baSopenharmony_ci}
10493d0407baSopenharmony_ci
10503d0407baSopenharmony_cistatic int rk817_bat_get_USB_voltage(struct rk817_battery_device *battery)
10513d0407baSopenharmony_ci{
10523d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
10533d0407baSopenharmony_ci
10543d0407baSopenharmony_ci    rk817_bat_field_write(battery, USB_VOL_ADC_EN, 0x01);
10553d0407baSopenharmony_ci
10563d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, USB_VOL_H) << 0x08;
10573d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, USB_VOL_L) << 0;
10583d0407baSopenharmony_ci
10593d0407baSopenharmony_ci    vol = (battery->voltage_k * val / 0x3E8 + battery->voltage_b) * 0x3C / 0x2E;
10603d0407baSopenharmony_ci
10613d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
10623d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
10633d0407baSopenharmony_ci        vol = vol_temp;
10643d0407baSopenharmony_ci    }
10653d0407baSopenharmony_ci
10663d0407baSopenharmony_ci    return vol;
10673d0407baSopenharmony_ci}
10683d0407baSopenharmony_ci
10693d0407baSopenharmony_cistatic int rk817_bat_get_sys_voltage(struct rk817_battery_device *battery)
10703d0407baSopenharmony_ci{
10713d0407baSopenharmony_ci    int vol, val = 0, vol_temp;
10723d0407baSopenharmony_ci
10733d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, SYS_VOL_H) << 0x08;
10743d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, SYS_VOL_L) << 0;
10753d0407baSopenharmony_ci
10763d0407baSopenharmony_ci    vol = (battery->voltage_k * val / 0x3E8 + battery->voltage_b) * 0x3C / 0x2E;
10773d0407baSopenharmony_ci
10783d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
10793d0407baSopenharmony_ci        vol_temp = vol * battery->pdata->bat_res_up / battery->pdata->bat_res_down + vol;
10803d0407baSopenharmony_ci        vol = vol_temp;
10813d0407baSopenharmony_ci    }
10823d0407baSopenharmony_ci
10833d0407baSopenharmony_ci    return vol;
10843d0407baSopenharmony_ci}
10853d0407baSopenharmony_ci
10863d0407baSopenharmony_cistatic int rk817_bat_get_avg_current(struct rk817_battery_device *battery)
10873d0407baSopenharmony_ci{
10883d0407baSopenharmony_ci    int cur, val = 0;
10893d0407baSopenharmony_ci
10903d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, BAT_CUR_H) << 0x08;
10913d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, BAT_CUR_L);
10923d0407baSopenharmony_ci    if (val & 0x8000) {
10933d0407baSopenharmony_ci        val -= 0x10000;
10943d0407baSopenharmony_ci    }
10953d0407baSopenharmony_ci
10963d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
10973d0407baSopenharmony_ci
10983d0407baSopenharmony_ci    return cur;
10993d0407baSopenharmony_ci}
11003d0407baSopenharmony_ci
11013d0407baSopenharmony_cistatic int rk817_bat_get_relax_cur1(struct rk817_battery_device *battery)
11023d0407baSopenharmony_ci{
11033d0407baSopenharmony_ci    int cur, val = 0;
11043d0407baSopenharmony_ci
11053d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, RELAX_CUR1_H) << 0x08;
11063d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, RELAX_CUR1_L);
11073d0407baSopenharmony_ci    if (val & 0x8000) {
11083d0407baSopenharmony_ci        val -= 0x10000;
11093d0407baSopenharmony_ci    }
11103d0407baSopenharmony_ci
11113d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
11123d0407baSopenharmony_ci
11133d0407baSopenharmony_ci    return cur;
11143d0407baSopenharmony_ci}
11153d0407baSopenharmony_ci
11163d0407baSopenharmony_cistatic int rk817_bat_get_relax_cur2(struct rk817_battery_device *battery)
11173d0407baSopenharmony_ci{
11183d0407baSopenharmony_ci    int cur, val = 0;
11193d0407baSopenharmony_ci
11203d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, RELAX_CUR2_H) << 0x08;
11213d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, RELAX_CUR2_L);
11223d0407baSopenharmony_ci    if (val & 0x8000) {
11233d0407baSopenharmony_ci        val -= 0x10000;
11243d0407baSopenharmony_ci    }
11253d0407baSopenharmony_ci
11263d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
11273d0407baSopenharmony_ci
11283d0407baSopenharmony_ci    return cur;
11293d0407baSopenharmony_ci}
11303d0407baSopenharmony_ci
11313d0407baSopenharmony_cistatic int rk817_bat_get_relax_current(struct rk817_battery_device *battery)
11323d0407baSopenharmony_ci{
11333d0407baSopenharmony_ci    int relax_cur1, relax_cur2;
11343d0407baSopenharmony_ci
11353d0407baSopenharmony_ci    if (!is_rk817_bat_relax_mode(battery)) {
11363d0407baSopenharmony_ci        return 0;
11373d0407baSopenharmony_ci    }
11383d0407baSopenharmony_ci
11393d0407baSopenharmony_ci    relax_cur1 = rk817_bat_get_relax_cur1(battery);
11403d0407baSopenharmony_ci    relax_cur2 = rk817_bat_get_relax_cur2(battery);
11413d0407baSopenharmony_ci
11423d0407baSopenharmony_ci    return (relax_cur1 < relax_cur2) ? relax_cur1 : relax_cur2;
11433d0407baSopenharmony_ci}
11443d0407baSopenharmony_ci
11453d0407baSopenharmony_cistatic int rk817_bat_get_ocv_current(struct rk817_battery_device *battery)
11463d0407baSopenharmony_ci{
11473d0407baSopenharmony_ci    int cur, val = 0;
11483d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, OCV_CUR_H) << 0x08;
11493d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, OCV_CUR_L);
11503d0407baSopenharmony_ci    if (val & 0x8000) {
11513d0407baSopenharmony_ci        val -= 0x10000;
11523d0407baSopenharmony_ci    }
11533d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
11543d0407baSopenharmony_ci    return cur;
11553d0407baSopenharmony_ci}
11563d0407baSopenharmony_ci
11573d0407baSopenharmony_cistatic int rk817_bat_get_ocv_current0(struct rk817_battery_device *battery)
11583d0407baSopenharmony_ci{
11593d0407baSopenharmony_ci    int cur, val = 0;
11603d0407baSopenharmony_ci
11613d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, OCV_CUR0_H) << 0x08;
11623d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, OCV_CUR0_L);
11633d0407baSopenharmony_ci    if (val & 0x8000) {
11643d0407baSopenharmony_ci        val -= 0x10000;
11653d0407baSopenharmony_ci    }
11663d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
11673d0407baSopenharmony_ci    return cur;
11683d0407baSopenharmony_ci}
11693d0407baSopenharmony_ci
11703d0407baSopenharmony_cistatic int rk817_bat_get_pwron_current(struct rk817_battery_device *battery)
11713d0407baSopenharmony_ci{
11723d0407baSopenharmony_ci    int cur, val = 0;
11733d0407baSopenharmony_ci
11743d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, PWRON_CUR_H) << 0x08;
11753d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, PWRON_CUR_L);
11763d0407baSopenharmony_ci    if (val & 0x8000) {
11773d0407baSopenharmony_ci        val -= 0x10000;
11783d0407baSopenharmony_ci    }
11793d0407baSopenharmony_ci    cur = ADC_TO_CURRENT(val, battery->res_div);
11803d0407baSopenharmony_ci
11813d0407baSopenharmony_ci    return cur;
11823d0407baSopenharmony_ci}
11833d0407baSopenharmony_ci
11843d0407baSopenharmony_cistatic bool rk817_bat_remain_cap_is_valid(struct rk817_battery_device *battery)
11853d0407baSopenharmony_ci{
11863d0407baSopenharmony_ci    return !(rk817_bat_field_read(battery, Q_PRESS_H3) & CAP_INVALID);
11873d0407baSopenharmony_ci}
11883d0407baSopenharmony_ci
11893d0407baSopenharmony_cistatic u32 rk817_bat_get_capacity_uah(struct rk817_battery_device *battery)
11903d0407baSopenharmony_ci{
11913d0407baSopenharmony_ci    u32 val = 0, capacity = 0;
11923d0407baSopenharmony_ci
11933d0407baSopenharmony_ci    if (rk817_bat_remain_cap_is_valid(battery)) {
11943d0407baSopenharmony_ci        val = rk817_bat_field_read(battery, Q_PRESS_H3) << 0x18;
11953d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 0x10;
11963d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 0x08;
11973d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0;
11983d0407baSopenharmony_ci
11993d0407baSopenharmony_ci        capacity = ADC_TO_CAPACITY_UAH(val, battery->res_div);
12003d0407baSopenharmony_ci    }
12013d0407baSopenharmony_ci
12023d0407baSopenharmony_ci    DBG("xxxxxxxxxxxxx capacity = %d\n", capacity);
12033d0407baSopenharmony_ci    return capacity;
12043d0407baSopenharmony_ci}
12053d0407baSopenharmony_ci
12063d0407baSopenharmony_cistatic u32 rk817_bat_get_capacity_mah(struct rk817_battery_device *battery)
12073d0407baSopenharmony_ci{
12083d0407baSopenharmony_ci    u32 val, capacity = 0;
12093d0407baSopenharmony_ci
12103d0407baSopenharmony_ci    if (rk817_bat_remain_cap_is_valid(battery)) {
12113d0407baSopenharmony_ci        val = rk817_bat_field_read(battery, Q_PRESS_H3) << 0x18;
12123d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_H2) << 0x10;
12133d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_L1) << 0x08;
12143d0407baSopenharmony_ci        val |= rk817_bat_field_read(battery, Q_PRESS_L0) << 0;
12153d0407baSopenharmony_ci
12163d0407baSopenharmony_ci        capacity = ADC_TO_CAPACITY(val, battery->res_div);
12173d0407baSopenharmony_ci    }
12183d0407baSopenharmony_ci    DBG("Q_PRESS_H3 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_H3));
12193d0407baSopenharmony_ci    DBG("Q_PRESS_H2 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_H2));
12203d0407baSopenharmony_ci    DBG("Q_PRESS_H1 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_L1));
12213d0407baSopenharmony_ci    DBG("Q_PRESS_H0 = 0x%x\n", rk817_bat_field_read(battery, Q_PRESS_L0));
12223d0407baSopenharmony_ci
12233d0407baSopenharmony_ci    DBG("xxxxxxxxxxxxx capacity = %d\n", capacity);
12243d0407baSopenharmony_ci    return capacity;
12253d0407baSopenharmony_ci}
12263d0407baSopenharmony_ci
12273d0407baSopenharmony_cistatic void fuel_gauge_q_init_info(struct rk817_battery_device *battery)
12283d0407baSopenharmony_ci{
12293d0407baSopenharmony_ci    DBG("Q_INIT_H3 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_H3));
12303d0407baSopenharmony_ci    DBG("Q_INIT_H2 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_H2));
12313d0407baSopenharmony_ci    DBG("Q_INIT_L1 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_L1));
12323d0407baSopenharmony_ci    DBG("Q_INIT_L0 = 0x%x\n", rk817_bat_field_read(battery, Q_INIT_L0));
12333d0407baSopenharmony_ci}
12343d0407baSopenharmony_ci
12353d0407baSopenharmony_cistatic void rk817_bat_init_coulomb_cap(struct rk817_battery_device *battery, u32 capacity)
12363d0407baSopenharmony_ci{
12373d0407baSopenharmony_ci    u8 buf;
12383d0407baSopenharmony_ci    u32 cap;
12393d0407baSopenharmony_ci
12403d0407baSopenharmony_ci    fuel_gauge_q_init_info(battery);
12413d0407baSopenharmony_ci    cap = CAPACITY_TO_ADC(capacity, battery->res_div);
12423d0407baSopenharmony_ci    DBG("new cap: 0x%x\n", cap);
12433d0407baSopenharmony_ci    buf = (cap >> 0x18) & 0xff;
12443d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_INIT_H3, buf);
12453d0407baSopenharmony_ci    buf = (cap >> 0x10) & 0xff;
12463d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_INIT_H2, buf);
12473d0407baSopenharmony_ci    buf = (cap >> 0x08) & 0xff;
12483d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_INIT_L1, buf);
12493d0407baSopenharmony_ci    buf = (cap >> 0) & 0xff;
12503d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_INIT_L0, buf);
12513d0407baSopenharmony_ci
12523d0407baSopenharmony_ci    battery->rsoc = capacity * 0x3E8 * 0x64 / battery->fcc;
12533d0407baSopenharmony_ci    battery->remain_cap = capacity * 0x3E8;
12543d0407baSopenharmony_ci    DBG("new remaincap: %d\n", battery->remain_cap);
12553d0407baSopenharmony_ci    fuel_gauge_q_init_info(battery);
12563d0407baSopenharmony_ci}
12573d0407baSopenharmony_ci
12583d0407baSopenharmony_cistatic void rk817_bat_save_cap(struct rk817_battery_device *battery, int capacity)
12593d0407baSopenharmony_ci{
12603d0407baSopenharmony_ci    u8 buf;
12613d0407baSopenharmony_ci    static u32 old_cap;
12623d0407baSopenharmony_ci
12633d0407baSopenharmony_ci    if (capacity >= battery->qmax) {
12643d0407baSopenharmony_ci        capacity = battery->qmax;
12653d0407baSopenharmony_ci    }
12663d0407baSopenharmony_ci    if (capacity <= 0) {
12673d0407baSopenharmony_ci        capacity = 0;
12683d0407baSopenharmony_ci    }
12693d0407baSopenharmony_ci    if (old_cap == capacity) {
12703d0407baSopenharmony_ci        return;
12713d0407baSopenharmony_ci    }
12723d0407baSopenharmony_ci
12733d0407baSopenharmony_ci    old_cap = capacity;
12743d0407baSopenharmony_ci    buf = (capacity >> 0x10) & 0xff;
12753d0407baSopenharmony_ci    rk817_bat_field_write(battery, REMAIN_CAP_REG2, buf);
12763d0407baSopenharmony_ci    buf = (capacity >> 0x08) & 0xff;
12773d0407baSopenharmony_ci    rk817_bat_field_write(battery, REMAIN_CAP_REG1, buf);
12783d0407baSopenharmony_ci    buf = (capacity >> 0) & 0xff;
12793d0407baSopenharmony_ci    rk817_bat_field_write(battery, REMAIN_CAP_REG0, buf);
12803d0407baSopenharmony_ci}
12813d0407baSopenharmony_ci
12823d0407baSopenharmony_cistatic void rk817_bat_update_qmax(struct rk817_battery_device *battery, u32 capacity)
12833d0407baSopenharmony_ci{
12843d0407baSopenharmony_ci    u8 buf;
12853d0407baSopenharmony_ci    u32 cap_adc;
12863d0407baSopenharmony_ci
12873d0407baSopenharmony_ci    cap_adc = CAPACITY_TO_ADC(capacity, battery->res_div);
12883d0407baSopenharmony_ci    buf = (cap_adc >> 0x18) & 0xff;
12893d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_MAX_H3, buf);
12903d0407baSopenharmony_ci    buf = (cap_adc >> 0x10) & 0xff;
12913d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_MAX_H2, buf);
12923d0407baSopenharmony_ci    buf = (cap_adc >> 0x08) & 0xff;
12933d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_MAX_L1, buf);
12943d0407baSopenharmony_ci    buf = (cap_adc >> 0) & 0xff;
12953d0407baSopenharmony_ci    rk817_bat_field_write(battery, Q_MAX_L0, buf);
12963d0407baSopenharmony_ci    battery->qmax = capacity;
12973d0407baSopenharmony_ci}
12983d0407baSopenharmony_ci
12993d0407baSopenharmony_cistatic int rk817_bat_get_qmax(struct rk817_battery_device *battery)
13003d0407baSopenharmony_ci{
13013d0407baSopenharmony_ci    u32 capacity;
13023d0407baSopenharmony_ci    int val = 0;
13033d0407baSopenharmony_ci
13043d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, Q_MAX_H3) << 0x18;
13053d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, Q_MAX_H2) << 0x10;
13063d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, Q_MAX_L1) << 0x08;
13073d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, Q_MAX_L0) << 0;
13083d0407baSopenharmony_ci    capacity = ADC_TO_CAPACITY(val, battery->res_div);
13093d0407baSopenharmony_ci    battery->qmax = capacity;
13103d0407baSopenharmony_ci    return capacity;
13113d0407baSopenharmony_ci}
13123d0407baSopenharmony_ci
13133d0407baSopenharmony_cistatic void rk817_bat_save_fcc(struct rk817_battery_device *battery, int fcc)
13143d0407baSopenharmony_ci{
13153d0407baSopenharmony_ci    u8 buf;
13163d0407baSopenharmony_ci
13173d0407baSopenharmony_ci    buf = (fcc >> 0x10) & 0xff;
13183d0407baSopenharmony_ci    rk817_bat_field_write(battery, NEW_FCC_REG2, buf);
13193d0407baSopenharmony_ci    buf = (fcc >> 0x08) & 0xff;
13203d0407baSopenharmony_ci    rk817_bat_field_write(battery, NEW_FCC_REG1, buf);
13213d0407baSopenharmony_ci    buf = (fcc >> 0) & 0xff;
13223d0407baSopenharmony_ci    rk817_bat_field_write(battery, NEW_FCC_REG0, buf);
13233d0407baSopenharmony_ci}
13243d0407baSopenharmony_ci
13253d0407baSopenharmony_cistatic int rk817_bat_get_fcc(struct rk817_battery_device *battery)
13263d0407baSopenharmony_ci{
13273d0407baSopenharmony_ci    u32 fcc = 0;
13283d0407baSopenharmony_ci
13293d0407baSopenharmony_ci    fcc |= rk817_bat_field_read(battery, NEW_FCC_REG2) << 0x10;
13303d0407baSopenharmony_ci    fcc |= rk817_bat_field_read(battery, NEW_FCC_REG1) << 0x08;
13313d0407baSopenharmony_ci    fcc |= rk817_bat_field_read(battery, NEW_FCC_REG0) << 0;
13323d0407baSopenharmony_ci    if (fcc < MIN_FCC) {
13333d0407baSopenharmony_ci        DBG("invalid fcc(%d), use design cap", fcc);
13343d0407baSopenharmony_ci        fcc = battery->pdata->design_capacity;
13353d0407baSopenharmony_ci        rk817_bat_save_fcc(battery, fcc);
13363d0407baSopenharmony_ci    } else if (fcc > battery->pdata->design_qmax) {
13373d0407baSopenharmony_ci        DBG("invalid fcc(%d), use qmax", fcc);
13383d0407baSopenharmony_ci        fcc = battery->pdata->design_qmax;
13393d0407baSopenharmony_ci        rk817_bat_save_fcc(battery, fcc);
13403d0407baSopenharmony_ci    }
13413d0407baSopenharmony_ci
13423d0407baSopenharmony_ci    return fcc;
13433d0407baSopenharmony_ci}
13443d0407baSopenharmony_ci
13453d0407baSopenharmony_cistatic int rk817_bat_get_rsoc(struct rk817_battery_device *battery)
13463d0407baSopenharmony_ci{
13473d0407baSopenharmony_ci    int remain_cap;
13483d0407baSopenharmony_ci
13493d0407baSopenharmony_ci    remain_cap = rk817_bat_get_capacity_uah(battery);
13503d0407baSopenharmony_ci
13513d0407baSopenharmony_ci    return remain_cap * 0x64 / DIV(battery->fcc);
13523d0407baSopenharmony_ci}
13533d0407baSopenharmony_ci
13543d0407baSopenharmony_cistatic int rk817_bat_get_off_count(struct rk817_battery_device *battery)
13553d0407baSopenharmony_ci{
13563d0407baSopenharmony_ci    return rk817_bat_field_read(battery, OFF_CNT);
13573d0407baSopenharmony_ci}
13583d0407baSopenharmony_ci
13593d0407baSopenharmony_cistatic int rk817_bat_get_ocv_count(struct rk817_battery_device *battery)
13603d0407baSopenharmony_ci{
13613d0407baSopenharmony_ci    return rk817_bat_field_read(battery, OCV_CNT);
13623d0407baSopenharmony_ci}
13633d0407baSopenharmony_ci
13643d0407baSopenharmony_cistatic int rk817_bat_vol_to_soc(struct rk817_battery_device *battery, int voltage)
13653d0407baSopenharmony_ci{
13663d0407baSopenharmony_ci    u32 *ocv_table, temp;
13673d0407baSopenharmony_ci    int ocv_size, ocv_soc;
13683d0407baSopenharmony_ci
13693d0407baSopenharmony_ci    ocv_table = battery->pdata->ocv_table;
13703d0407baSopenharmony_ci    ocv_size = battery->pdata->ocv_size;
13713d0407baSopenharmony_ci    temp = interpolate(voltage, ocv_table, ocv_size);
13723d0407baSopenharmony_ci    ocv_soc = ab_div_c(temp, MAX_PERCENTAGE, MAX_INTERPOLATE);
13733d0407baSopenharmony_ci
13743d0407baSopenharmony_ci    return ocv_soc;
13753d0407baSopenharmony_ci}
13763d0407baSopenharmony_ci
13773d0407baSopenharmony_cistatic int rk817_bat_vol_to_cap(struct rk817_battery_device *battery, int voltage)
13783d0407baSopenharmony_ci{
13793d0407baSopenharmony_ci    u32 *ocv_table, temp;
13803d0407baSopenharmony_ci    int ocv_size, capacity;
13813d0407baSopenharmony_ci
13823d0407baSopenharmony_ci    ocv_table = battery->pdata->ocv_table;
13833d0407baSopenharmony_ci    ocv_size = battery->pdata->ocv_size;
13843d0407baSopenharmony_ci    temp = interpolate(voltage, ocv_table, ocv_size);
13853d0407baSopenharmony_ci    capacity = ab_div_c(temp, battery->fcc, MAX_INTERPOLATE);
13863d0407baSopenharmony_ci
13873d0407baSopenharmony_ci    return capacity;
13883d0407baSopenharmony_ci}
13893d0407baSopenharmony_ci
13903d0407baSopenharmony_cistatic void rk817_bat_save_dsoc(struct rk817_battery_device *battery, int save_soc)
13913d0407baSopenharmony_ci{
13923d0407baSopenharmony_ci    static int last_soc = -1;
13933d0407baSopenharmony_ci
13943d0407baSopenharmony_ci    if (last_soc != save_soc) {
13953d0407baSopenharmony_ci        rk817_bat_field_write(battery, SOC_REG0, save_soc & 0xff);
13963d0407baSopenharmony_ci        rk817_bat_field_write(battery, SOC_REG1, (save_soc >> 0x08) & 0xff);
13973d0407baSopenharmony_ci        rk817_bat_field_write(battery, SOC_REG2, (save_soc >> 0x10) & 0xff);
13983d0407baSopenharmony_ci
13993d0407baSopenharmony_ci        last_soc = save_soc;
14003d0407baSopenharmony_ci    }
14013d0407baSopenharmony_ci}
14023d0407baSopenharmony_ci
14033d0407baSopenharmony_cistatic int rk817_bat_get_prev_dsoc(struct rk817_battery_device *battery)
14043d0407baSopenharmony_ci{
14053d0407baSopenharmony_ci    int soc_save;
14063d0407baSopenharmony_ci
14073d0407baSopenharmony_ci    soc_save = rk817_bat_field_read(battery, SOC_REG0);
14083d0407baSopenharmony_ci    soc_save |= (rk817_bat_field_read(battery, SOC_REG1) << 0x08);
14093d0407baSopenharmony_ci    soc_save |= (rk817_bat_field_read(battery, SOC_REG2) << 0x10);
14103d0407baSopenharmony_ci
14113d0407baSopenharmony_ci    return soc_save;
14123d0407baSopenharmony_ci}
14133d0407baSopenharmony_ci
14143d0407baSopenharmony_cistatic bool is_rk817_bat_first_pwron(struct rk817_battery_device *battery)
14153d0407baSopenharmony_ci{
14163d0407baSopenharmony_ci    if (rk817_bat_field_read(battery, BAT_CON)) {
14173d0407baSopenharmony_ci        rk817_bat_field_write(battery, BAT_CON, 0x00);
14183d0407baSopenharmony_ci        return true;
14193d0407baSopenharmony_ci    }
14203d0407baSopenharmony_ci
14213d0407baSopenharmony_ci    return false;
14223d0407baSopenharmony_ci}
14233d0407baSopenharmony_ci
14243d0407baSopenharmony_cistatic int rk817_bat_get_charge_status(struct rk817_battery_device *battery)
14253d0407baSopenharmony_ci{
14263d0407baSopenharmony_ci    int status;
14273d0407baSopenharmony_ci
14283d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
14293d0407baSopenharmony_ci        if ((battery->voltage_avg > battery->pdata->design_max_voltage) && (battery->current_avg > 0) &&
14303d0407baSopenharmony_ci            ((battery->current_avg < 0x1F4) || (battery->rsoc / 0x3E8 == 0x64))) {
14313d0407baSopenharmony_ci            return CHARGE_FINISH;
14323d0407baSopenharmony_ci        }
14333d0407baSopenharmony_ci
14343d0407baSopenharmony_ci        if (battery->plugin_trigger) {
14353d0407baSopenharmony_ci            return CC_OR_CV_CHRG;
14363d0407baSopenharmony_ci        } else {
14373d0407baSopenharmony_ci            return CHRG_OFF;
14383d0407baSopenharmony_ci        }
14393d0407baSopenharmony_ci    }
14403d0407baSopenharmony_ci    status = rk817_bat_field_read(battery, CHG_STS);
14413d0407baSopenharmony_ci    if (status == CC_OR_CV_CHRG) {
14423d0407baSopenharmony_ci        if (battery->rsoc == 0x64 * 0X3E8) {
14433d0407baSopenharmony_ci            DBG("charge to finish\n");
14443d0407baSopenharmony_ci            status = CHARGE_FINISH;
14453d0407baSopenharmony_ci        }
14463d0407baSopenharmony_ci    }
14473d0407baSopenharmony_ci
14483d0407baSopenharmony_ci    switch (status) {
14493d0407baSopenharmony_ci        case CHRG_OFF:
14503d0407baSopenharmony_ci            DBG("charge off...\n");
14513d0407baSopenharmony_ci            break;
14523d0407baSopenharmony_ci        case DEAD_CHRG:
14533d0407baSopenharmony_ci            DBG("dead charge...\n");
14543d0407baSopenharmony_ci            break;
14553d0407baSopenharmony_ci        case TRICKLE_CHRG:
14563d0407baSopenharmony_ci            DBG("trickle charge...\n");
14573d0407baSopenharmony_ci            break;
14583d0407baSopenharmony_ci        case CC_OR_CV_CHRG:
14593d0407baSopenharmony_ci            DBG("CC or CV charge...\n");
14603d0407baSopenharmony_ci            break;
14613d0407baSopenharmony_ci        case CHARGE_FINISH:
14623d0407baSopenharmony_ci            DBG("charge finish...\n");
14633d0407baSopenharmony_ci            break;
14643d0407baSopenharmony_ci        case USB_OVER_VOL:
14653d0407baSopenharmony_ci            DBG("USB over voltage...\n");
14663d0407baSopenharmony_ci            break;
14673d0407baSopenharmony_ci        case BAT_TMP_ERR:
14683d0407baSopenharmony_ci            DBG("battery temperature error...\n");
14693d0407baSopenharmony_ci            break;
14703d0407baSopenharmony_ci        case BAT_TIM_ERR:
14713d0407baSopenharmony_ci            DBG("battery timer error..\n");
14723d0407baSopenharmony_ci            break;
14733d0407baSopenharmony_ci        default:
14743d0407baSopenharmony_ci            break;
14753d0407baSopenharmony_ci    }
14763d0407baSopenharmony_ci
14773d0407baSopenharmony_ci    return status;
14783d0407baSopenharmony_ci}
14793d0407baSopenharmony_ci
14803d0407baSopenharmony_ci/*
14813d0407baSopenharmony_ci * cccv and finish switch all the time will cause dsoc freeze,
14823d0407baSopenharmony_ci * if so, do finish chrg, 100ma is less than min finish_ma.
14833d0407baSopenharmony_ci */
14843d0407baSopenharmony_cistatic bool rk817_bat_fake_finish_mode(struct rk817_battery_device *battery)
14853d0407baSopenharmony_ci{
14863d0407baSopenharmony_ci    if ((battery->rsoc == 0x64) && (rk817_bat_get_charge_status(battery) == CC_OR_CV_CHRG) &&
14873d0407baSopenharmony_ci        (abs(battery->current_avg) <= 0x64)) {
14883d0407baSopenharmony_ci        return true;
14893d0407baSopenharmony_ci    } else {
14903d0407baSopenharmony_ci        return false;
14913d0407baSopenharmony_ci    }
14923d0407baSopenharmony_ci}
14933d0407baSopenharmony_ci
14943d0407baSopenharmony_cistatic int get_charge_status(struct rk817_battery_device *battery)
14953d0407baSopenharmony_ci{
14963d0407baSopenharmony_ci    return rk817_bat_get_charge_status(battery);
14973d0407baSopenharmony_ci}
14983d0407baSopenharmony_ci
14993d0407baSopenharmony_cistatic bool is_rk817_bat_ocv_valid(struct rk817_battery_device *battery)
15003d0407baSopenharmony_ci{
15013d0407baSopenharmony_ci    return (!battery->is_initialized && battery->pwroff_min >= 0x1E);
15023d0407baSopenharmony_ci}
15033d0407baSopenharmony_ci
15043d0407baSopenharmony_cistatic void rk817_bat_gas_gaugle_enable(struct rk817_battery_device *battery)
15053d0407baSopenharmony_ci{
15063d0407baSopenharmony_ci    rk817_bat_field_write(battery, GG_EN, ENABLE);
15073d0407baSopenharmony_ci}
15083d0407baSopenharmony_ci
15093d0407baSopenharmony_cistatic void rk817_bat_gg_con_init(struct rk817_battery_device *battery)
15103d0407baSopenharmony_ci{
15113d0407baSopenharmony_ci    rk817_bat_field_write(battery, RLX_SPT, S_8_MIN);
15123d0407baSopenharmony_ci    rk817_bat_field_write(battery, ADC_OFF_CAL_INTERV, S_8_MIN);
15133d0407baSopenharmony_ci    rk817_bat_field_write(battery, VOL_OUT_MOD, AVERAGE_MODE);
15143d0407baSopenharmony_ci    rk817_bat_field_write(battery, CUR_OUT_MOD, AVERAGE_MODE);
15153d0407baSopenharmony_ci}
15163d0407baSopenharmony_ci
15173d0407baSopenharmony_cistatic void rk817_bat_adc_init(struct rk817_battery_device *battery)
15183d0407baSopenharmony_ci{
15193d0407baSopenharmony_ci    rk817_bat_field_write(battery, SYS_VOL_ADC_EN, ENABLE);
15203d0407baSopenharmony_ci    rk817_bat_field_write(battery, TS_ADC_EN, ENABLE);
15213d0407baSopenharmony_ci    rk817_bat_field_write(battery, USB_VOL_ADC_EN, ENABLE);
15223d0407baSopenharmony_ci    rk817_bat_field_write(battery, BAT_VOL_ADC_EN, ENABLE);
15233d0407baSopenharmony_ci    rk817_bat_field_write(battery, BAT_CUR_ADC_EN, ENABLE);
15243d0407baSopenharmony_ci}
15253d0407baSopenharmony_ci
15263d0407baSopenharmony_cistatic void rk817_bat_init_info(struct rk817_battery_device *battery)
15273d0407baSopenharmony_ci{
15283d0407baSopenharmony_ci    battery->design_cap = battery->pdata->design_capacity;
15293d0407baSopenharmony_ci    battery->qmax = battery->pdata->design_qmax;
15303d0407baSopenharmony_ci    battery->bat_res = battery->pdata->bat_res;
15313d0407baSopenharmony_ci    battery->monitor_ms = battery->pdata->monitor_sec * TIMER_MS_COUNTS;
15323d0407baSopenharmony_ci    battery->res_div = (battery->pdata->sample_res == SAMPLE_RES_20MR) ? SAMPLE_RES_DIV2 : SAMPLE_RES_DIV1;
15333d0407baSopenharmony_ci    DBG("battery->qmax :%d\n", battery->qmax);
15343d0407baSopenharmony_ci}
15353d0407baSopenharmony_ci
15363d0407baSopenharmony_cistatic int rk817_bat_get_prev_cap(struct rk817_battery_device *battery)
15373d0407baSopenharmony_ci{
15383d0407baSopenharmony_ci    int val = 0;
15393d0407baSopenharmony_ci
15403d0407baSopenharmony_ci    val = rk817_bat_field_read(battery, REMAIN_CAP_REG2) << 0x10;
15413d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, REMAIN_CAP_REG1) << 0x08;
15423d0407baSopenharmony_ci    val |= rk817_bat_field_read(battery, REMAIN_CAP_REG0) << 0;
15433d0407baSopenharmony_ci
15443d0407baSopenharmony_ci    return val;
15453d0407baSopenharmony_ci}
15463d0407baSopenharmony_ci
15473d0407baSopenharmony_cistatic u8 rk817_bat_get_halt_cnt(struct rk817_battery_device *battery)
15483d0407baSopenharmony_ci{
15493d0407baSopenharmony_ci    return rk817_bat_field_read(battery, HALT_CNT_REG);
15503d0407baSopenharmony_ci}
15513d0407baSopenharmony_ci
15523d0407baSopenharmony_cistatic void rk817_bat_inc_halt_cnt(struct rk817_battery_device *battery)
15533d0407baSopenharmony_ci{
15543d0407baSopenharmony_ci    u8 cnt;
15553d0407baSopenharmony_ci
15563d0407baSopenharmony_ci    cnt = rk817_bat_field_read(battery, HALT_CNT_REG);
15573d0407baSopenharmony_ci    rk817_bat_field_write(battery, HALT_CNT_REG, ++cnt);
15583d0407baSopenharmony_ci}
15593d0407baSopenharmony_ci
15603d0407baSopenharmony_cistatic bool is_rk817_bat_last_halt(struct rk817_battery_device *battery)
15613d0407baSopenharmony_ci{
15623d0407baSopenharmony_ci    int pre_cap = rk817_bat_get_prev_cap(battery);
15633d0407baSopenharmony_ci    int now_cap = rk817_bat_get_capacity_mah(battery);
15643d0407baSopenharmony_ci    /* over 10%: system halt last time */
15653d0407baSopenharmony_ci    if (abs(now_cap - pre_cap) > (battery->fcc / 10)) {
15663d0407baSopenharmony_ci        rk817_bat_inc_halt_cnt(battery);
15673d0407baSopenharmony_ci        return true;
15683d0407baSopenharmony_ci    } else {
15693d0407baSopenharmony_ci        return false;
15703d0407baSopenharmony_ci    }
15713d0407baSopenharmony_ci}
15723d0407baSopenharmony_ci
15733d0407baSopenharmony_cistatic u8 is_rk817_bat_initialized(struct rk817_battery_device *battery)
15743d0407baSopenharmony_ci{
15753d0407baSopenharmony_ci    u8 val = rk817_bat_field_read(battery, FG_INIT);
15763d0407baSopenharmony_ci    if (val) {
15773d0407baSopenharmony_ci        rk817_bat_field_write(battery, FG_INIT, 0x00);
15783d0407baSopenharmony_ci        return true;
15793d0407baSopenharmony_ci    } else {
15803d0407baSopenharmony_ci        return false;
15813d0407baSopenharmony_ci    }
15823d0407baSopenharmony_ci}
15833d0407baSopenharmony_ci
15843d0407baSopenharmony_cistatic void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery)
15853d0407baSopenharmony_ci{
15863d0407baSopenharmony_ci    int linek;
15873d0407baSopenharmony_ci    int diff, delta;
15883d0407baSopenharmony_ci    int current_avg = rk817_bat_get_avg_current(battery);
15893d0407baSopenharmony_ci
15903d0407baSopenharmony_ci    delta = abs(battery->dsoc - battery->rsoc);
15913d0407baSopenharmony_ci    diff = delta * 3; /* speed:3/4 */
15923d0407baSopenharmony_ci
15933d0407baSopenharmony_ci    if (current_avg > 0) {
15943d0407baSopenharmony_ci        if (battery->dsoc < battery->rsoc) {
15953d0407baSopenharmony_ci            linek = 0x3E8 * (delta + diff) / DIV(diff);
15963d0407baSopenharmony_ci        } else if (battery->dsoc > battery->rsoc) {
15973d0407baSopenharmony_ci            linek = 0x3E8 * diff / DIV(delta + diff);
15983d0407baSopenharmony_ci        } else {
15993d0407baSopenharmony_ci            linek = 0X3E8;
16003d0407baSopenharmony_ci        }
16013d0407baSopenharmony_ci    } else {
16023d0407baSopenharmony_ci        if (battery->dsoc < battery->rsoc) {
16033d0407baSopenharmony_ci            linek = -0x3E8 * diff / DIV(delta + diff);
16043d0407baSopenharmony_ci        } else if (battery->dsoc > battery->rsoc) {
16053d0407baSopenharmony_ci            linek = -0x3E8 * (delta + diff) / DIV(diff);
16063d0407baSopenharmony_ci        } else {
16073d0407baSopenharmony_ci            linek = -0x3E8;
16083d0407baSopenharmony_ci        }
16093d0407baSopenharmony_ci    }
16103d0407baSopenharmony_ci
16113d0407baSopenharmony_ci    battery->dbg_meet_soc = (battery->dsoc >= battery->rsoc) ? (battery->dsoc - diff) : (battery->rsoc - diff);
16123d0407baSopenharmony_ci
16133d0407baSopenharmony_ci    battery->sm_linek = linek;
16143d0407baSopenharmony_ci    battery->sm_remain_cap = battery->remain_cap;
16153d0407baSopenharmony_ci    battery->dbg_calc_dsoc = battery->dsoc;
16163d0407baSopenharmony_ci    battery->dbg_calc_rsoc = battery->rsoc;
16173d0407baSopenharmony_ci}
16183d0407baSopenharmony_ci
16193d0407baSopenharmony_cistatic void rk817_bat_smooth_algo_prepare(struct rk817_battery_device *battery)
16203d0407baSopenharmony_ci{
16213d0407baSopenharmony_ci    battery->smooth_soc = battery->dsoc;
16223d0407baSopenharmony_ci
16233d0407baSopenharmony_ci    DBG("<%s>. dsoc=%d, dsoc:smooth_soc=%d\n", __func__, battery->dsoc, battery->smooth_soc);
16243d0407baSopenharmony_ci    rk817_bat_calc_sm_linek(battery);
16253d0407baSopenharmony_ci}
16263d0407baSopenharmony_ci
16273d0407baSopenharmony_cistatic void rk817_bat_finish_algo_prepare(struct rk817_battery_device *battery)
16283d0407baSopenharmony_ci{
16293d0407baSopenharmony_ci    battery->finish_base = get_boot_sec();
16303d0407baSopenharmony_ci
16313d0407baSopenharmony_ci    if (!battery->finish_base) {
16323d0407baSopenharmony_ci        battery->finish_base = 1;
16333d0407baSopenharmony_ci    }
16343d0407baSopenharmony_ci}
16353d0407baSopenharmony_ci
16363d0407baSopenharmony_cistatic void rk817_bat_init_dsoc_algorithm(struct rk817_battery_device *battery)
16373d0407baSopenharmony_ci{
16383d0407baSopenharmony_ci    if (battery->dsoc >= 0x64 * 0x3E8) {
16393d0407baSopenharmony_ci        battery->dsoc = 0x64 * 0x3E8;
16403d0407baSopenharmony_ci    } else if (battery->dsoc <= 0) {
16413d0407baSopenharmony_ci        battery->dsoc = 0;
16423d0407baSopenharmony_ci    }
16433d0407baSopenharmony_ci    /* init current mode */
16443d0407baSopenharmony_ci    battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
16453d0407baSopenharmony_ci    battery->current_avg = rk817_bat_get_avg_current(battery);
16463d0407baSopenharmony_ci
16473d0407baSopenharmony_ci    if (get_charge_status(battery) == CHARGE_FINISH) {
16483d0407baSopenharmony_ci        rk817_bat_finish_algo_prepare(battery);
16493d0407baSopenharmony_ci        battery->work_mode = MODE_FINISH;
16503d0407baSopenharmony_ci    } else {
16513d0407baSopenharmony_ci        rk817_bat_smooth_algo_prepare(battery);
16523d0407baSopenharmony_ci        battery->work_mode = MODE_SMOOTH;
16533d0407baSopenharmony_ci    }
16543d0407baSopenharmony_ci    DBG("%s, sm_remain_cap = %d, smooth_soc = %d\n", __func__, battery->sm_remain_cap, battery->smooth_soc);
16553d0407baSopenharmony_ci}
16563d0407baSopenharmony_ci
16573d0407baSopenharmony_cistatic void rk817_bat_first_pwron(struct rk817_battery_device *battery)
16583d0407baSopenharmony_ci{
16593d0407baSopenharmony_ci    battery->rsoc = rk817_bat_vol_to_soc(battery, battery->pwron_voltage) * 0x3E8; /* uAH */
16603d0407baSopenharmony_ci    battery->dsoc = battery->rsoc;
16613d0407baSopenharmony_ci    battery->fcc = battery->pdata->design_capacity;
16623d0407baSopenharmony_ci    battery->nac = rk817_bat_vol_to_cap(battery, battery->pwron_voltage);
16633d0407baSopenharmony_ci
16643d0407baSopenharmony_ci    rk817_bat_update_qmax(battery, battery->qmax);
16653d0407baSopenharmony_ci    rk817_bat_save_fcc(battery, battery->fcc);
16663d0407baSopenharmony_ci    DBG("%s, rsoc = %d, dsoc = %d, fcc = %d, nac = %d\n", __func__, battery->rsoc, battery->dsoc, battery->fcc,
16673d0407baSopenharmony_ci        battery->nac);
16683d0407baSopenharmony_ci}
16693d0407baSopenharmony_ci
16703d0407baSopenharmony_cistatic void rk817_bat_not_first_pwron(struct rk817_battery_device *battery)
16713d0407baSopenharmony_ci{
16723d0407baSopenharmony_ci    int now_cap, pre_soc, pre_cap, ocv_cap, ocv_soc, ocv_vol;
16733d0407baSopenharmony_ci
16743d0407baSopenharmony_ci    battery->fcc = rk817_bat_get_fcc(battery);
16753d0407baSopenharmony_ci    pre_soc = rk817_bat_get_prev_dsoc(battery);
16763d0407baSopenharmony_ci    pre_cap = rk817_bat_get_prev_cap(battery);
16773d0407baSopenharmony_ci    now_cap = rk817_bat_get_capacity_mah(battery);
16783d0407baSopenharmony_ci    battery->remain_cap = pre_cap * 0x3E8;
16793d0407baSopenharmony_ci    battery->is_halt = is_rk817_bat_last_halt(battery);
16803d0407baSopenharmony_ci    battery->halt_cnt = rk817_bat_get_halt_cnt(battery);
16813d0407baSopenharmony_ci    battery->is_initialized = is_rk817_bat_initialized(battery);
16823d0407baSopenharmony_ci    battery->is_ocv_calib = is_rk817_bat_ocv_valid(battery);
16833d0407baSopenharmony_ci
16843d0407baSopenharmony_ci    if (battery->is_halt) {
16853d0407baSopenharmony_ci        BAT_INFO("system halt last time... cap: pre=%d, now=%d\n", pre_cap, now_cap);
16863d0407baSopenharmony_ci        if (now_cap < 0) {
16873d0407baSopenharmony_ci            now_cap = 0;
16883d0407baSopenharmony_ci        }
16893d0407baSopenharmony_ci        rk817_bat_init_coulomb_cap(battery, now_cap);
16903d0407baSopenharmony_ci        pre_cap = now_cap;
16913d0407baSopenharmony_ci        pre_soc = battery->rsoc;
16923d0407baSopenharmony_ci        goto finish;
16933d0407baSopenharmony_ci    } else if (battery->is_initialized) {
16943d0407baSopenharmony_ci        /* uboot initialized */
16953d0407baSopenharmony_ci        BAT_INFO("initialized yet..\n");
16963d0407baSopenharmony_ci        goto finish;
16973d0407baSopenharmony_ci    } else if (battery->is_ocv_calib) {
16983d0407baSopenharmony_ci        /* not initialized and poweroff_cnt above 30 min */
16993d0407baSopenharmony_ci        ocv_vol = rk817_bat_get_ocv_voltage(battery);
17003d0407baSopenharmony_ci        ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol);
17013d0407baSopenharmony_ci        ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol);
17023d0407baSopenharmony_ci        pre_cap = ocv_cap;
17033d0407baSopenharmony_ci        battery->ocv_pre_dsoc = pre_soc;
17043d0407baSopenharmony_ci        battery->ocv_new_dsoc = ocv_soc;
17053d0407baSopenharmony_ci        if (abs(ocv_soc - pre_soc) >= battery->pdata->max_soc_offset) {
17063d0407baSopenharmony_ci            battery->ocv_pre_dsoc = pre_soc;
17073d0407baSopenharmony_ci            battery->ocv_new_dsoc = ocv_soc;
17083d0407baSopenharmony_ci            battery->is_max_soc_offset = true;
17093d0407baSopenharmony_ci            BAT_INFO("trigger max soc offset, dsoc: %d -> %d\n", pre_soc, ocv_soc);
17103d0407baSopenharmony_ci            pre_soc = ocv_soc;
17113d0407baSopenharmony_ci        }
17123d0407baSopenharmony_ci        BAT_INFO("OCV calib: cap=%d, rsoc=%d\n", ocv_cap, ocv_soc);
17133d0407baSopenharmony_ci    } else if (battery->pwroff_min > 0) {
17143d0407baSopenharmony_ci        ocv_vol = rk817_bat_get_ocv_voltage(battery);
17153d0407baSopenharmony_ci        ocv_soc = rk817_bat_vol_to_soc(battery, ocv_vol);
17163d0407baSopenharmony_ci        ocv_cap = rk817_bat_vol_to_cap(battery, ocv_vol);
17173d0407baSopenharmony_ci        battery->force_pre_dsoc = pre_soc;
17183d0407baSopenharmony_ci        battery->force_new_dsoc = ocv_soc;
17193d0407baSopenharmony_ci        if (abs(ocv_soc - pre_soc) >= 0X50) {
17203d0407baSopenharmony_ci            battery->is_force_calib = true;
17213d0407baSopenharmony_ci            BAT_INFO("dsoc force calib: %d -> %d\n", pre_soc, ocv_soc);
17223d0407baSopenharmony_ci            pre_soc = ocv_soc;
17233d0407baSopenharmony_ci            pre_cap = ocv_cap;
17243d0407baSopenharmony_ci        }
17253d0407baSopenharmony_ci    }
17263d0407baSopenharmony_cifinish:
17273d0407baSopenharmony_ci    battery->dsoc = pre_soc;
17283d0407baSopenharmony_ci    battery->nac = pre_cap;
17293d0407baSopenharmony_ci    if (battery->nac < 0) {
17303d0407baSopenharmony_ci        battery->nac = 0;
17313d0407baSopenharmony_ci    }
17323d0407baSopenharmony_ci
17333d0407baSopenharmony_ci    DBG("dsoc=%d cap=%d v=%d ov=%d rv=%d min=%d psoc=%d pcap=%d\n", battery->dsoc, battery->nac,
17343d0407baSopenharmony_ci        rk817_bat_get_battery_voltage(battery), rk817_bat_get_ocv_voltage(battery),
17353d0407baSopenharmony_ci        rk817_bat_get_relax_voltage(battery), battery->pwroff_min, rk817_bat_get_prev_dsoc(battery),
17363d0407baSopenharmony_ci        rk817_bat_get_prev_cap(battery));
17373d0407baSopenharmony_ci}
17383d0407baSopenharmony_ci
17393d0407baSopenharmony_cistatic void rk817_bat_rsoc_init(struct rk817_battery_device *battery)
17403d0407baSopenharmony_ci{
17413d0407baSopenharmony_ci    battery->is_first_power_on = is_rk817_bat_first_pwron(battery);
17423d0407baSopenharmony_ci    battery->pwroff_min = rk817_bat_get_off_count(battery);
17433d0407baSopenharmony_ci    battery->pwron_voltage = rk817_bat_get_pwron_voltage(battery);
17443d0407baSopenharmony_ci
17453d0407baSopenharmony_ci    DBG("%s, is_first_power_on = %d, pwroff_min = %d, pwron_voltage = %d\n", __func__, battery->is_first_power_on,
17463d0407baSopenharmony_ci        battery->pwroff_min, battery->pwron_voltage);
17473d0407baSopenharmony_ci
17483d0407baSopenharmony_ci    if (battery->is_first_power_on) {
17493d0407baSopenharmony_ci        rk817_bat_first_pwron(battery);
17503d0407baSopenharmony_ci    } else {
17513d0407baSopenharmony_ci        rk817_bat_not_first_pwron(battery);
17523d0407baSopenharmony_ci    }
17533d0407baSopenharmony_ci
17543d0407baSopenharmony_ci    rk817_bat_save_dsoc(battery, battery->dsoc);
17553d0407baSopenharmony_ci}
17563d0407baSopenharmony_ci
17573d0407baSopenharmony_cistatic void rk817_bat_caltimer_isr(struct timer_list *t)
17583d0407baSopenharmony_ci{
17593d0407baSopenharmony_ci    struct rk817_battery_device *battery = from_timer(battery, t, caltimer);
17603d0407baSopenharmony_ci
17613d0407baSopenharmony_ci    mod_timer(&battery->caltimer, jiffies + MINUTE(8) * HZ);
17623d0407baSopenharmony_ci    queue_delayed_work(battery->bat_monitor_wq, &battery->calib_delay_work, msecs_to_jiffies(0X0A));
17633d0407baSopenharmony_ci}
17643d0407baSopenharmony_ci
17653d0407baSopenharmony_cistatic void rk817_bat_internal_calib(struct work_struct *work)
17663d0407baSopenharmony_ci{
17673d0407baSopenharmony_ci    struct rk817_battery_device *battery = container_of(work, struct rk817_battery_device, calib_delay_work.work);
17683d0407baSopenharmony_ci
17693d0407baSopenharmony_ci    return;
17703d0407baSopenharmony_ci
17713d0407baSopenharmony_ci    rk817_bat_current_calibration(battery);
17723d0407baSopenharmony_ci    /* calib voltage kb */
17733d0407baSopenharmony_ci    rk817_bat_init_voltage_kb(battery);
17743d0407baSopenharmony_ci
17753d0407baSopenharmony_ci    DBG("caltimer:coffset=0x%x\n", rk817_bat_get_coffset(battery));
17763d0407baSopenharmony_ci}
17773d0407baSopenharmony_ci
17783d0407baSopenharmony_cistatic void rk817_bat_init_caltimer(struct rk817_battery_device *battery)
17793d0407baSopenharmony_ci{
17803d0407baSopenharmony_ci    timer_setup(&battery->caltimer, rk817_bat_caltimer_isr, 0);
17813d0407baSopenharmony_ci    battery->caltimer.expires = jiffies + MINUTE(8) * HZ;
17823d0407baSopenharmony_ci    add_timer(&battery->caltimer);
17833d0407baSopenharmony_ci    INIT_DELAYED_WORK(&battery->calib_delay_work, rk817_bat_internal_calib);
17843d0407baSopenharmony_ci}
17853d0407baSopenharmony_ci
17863d0407baSopenharmony_cistatic void rk817_bat_init_fg(struct rk817_battery_device *battery)
17873d0407baSopenharmony_ci{
17883d0407baSopenharmony_ci    rk817_bat_adc_init(battery);
17893d0407baSopenharmony_ci    rk817_bat_gas_gaugle_enable(battery);
17903d0407baSopenharmony_ci    rk817_bat_gg_con_init(battery);
17913d0407baSopenharmony_ci    rk817_bat_init_voltage_kb(battery);
17923d0407baSopenharmony_ci    rk817_bat_set_relax_sample(battery);
17933d0407baSopenharmony_ci    rk817_bat_ocv_thre(battery, 0xff);
17943d0407baSopenharmony_ci    rk817_bat_init_caltimer(battery);
17953d0407baSopenharmony_ci    rk817_bat_rsoc_init(battery);
17963d0407baSopenharmony_ci    rk817_bat_init_coulomb_cap(battery, battery->nac);
17973d0407baSopenharmony_ci    DBG("rsoc%d, fcc = %d\n", battery->rsoc, battery->fcc);
17983d0407baSopenharmony_ci    rk817_bat_init_dsoc_algorithm(battery);
17993d0407baSopenharmony_ci    battery->qmax = rk817_bat_get_qmax(battery);
18003d0407baSopenharmony_ci    battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
18013d0407baSopenharmony_ci    battery->voltage_sys = rk817_bat_get_sys_voltage(battery);
18023d0407baSopenharmony_ci
18033d0407baSopenharmony_ci    battery->voltage_ocv = rk817_bat_get_ocv_voltage(battery);
18043d0407baSopenharmony_ci    battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
18053d0407baSopenharmony_ci    battery->current_avg = rk817_bat_get_avg_current(battery);
18063d0407baSopenharmony_ci    battery->dbg_pwr_dsoc = battery->dsoc;
18073d0407baSopenharmony_ci    battery->dbg_pwr_rsoc = battery->rsoc;
18083d0407baSopenharmony_ci    battery->dbg_pwr_vol = battery->voltage_avg;
18093d0407baSopenharmony_ci    battery->temperature = VIRTUAL_TEMPERATURE;
18103d0407baSopenharmony_ci
18113d0407baSopenharmony_ci    DBG("probe init: battery->dsoc = %d, rsoc = %d\n"
18123d0407baSopenharmony_ci        "remain_cap = %d\n, battery_vol = %d\n, system_vol = %d, qmax = %d\n",
18133d0407baSopenharmony_ci        battery->dsoc, battery->rsoc, battery->remain_cap, battery->voltage_avg, battery->voltage_sys, battery->qmax);
18143d0407baSopenharmony_ci    DBG("OCV_THRE_VOL: 0x%x", rk817_bat_field_read(battery, OCV_THRE_VOL));
18153d0407baSopenharmony_ci}
18163d0407baSopenharmony_ci
18173d0407baSopenharmony_cistatic int rk817_bat_parse_dt(struct rk817_battery_device *battery)
18183d0407baSopenharmony_ci{
18193d0407baSopenharmony_ci    u32 out_value;
18203d0407baSopenharmony_ci    int length, ret;
18213d0407baSopenharmony_ci    size_t size;
18223d0407baSopenharmony_ci    struct battery_platform_data *pdata;
18233d0407baSopenharmony_ci    struct device *dev = battery->dev;
18243d0407baSopenharmony_ci    struct device_node *np = battery->dev->of_node;
18253d0407baSopenharmony_ci
18263d0407baSopenharmony_ci    pdata = devm_kzalloc(battery->dev, sizeof(*pdata), GFP_KERNEL);
18273d0407baSopenharmony_ci    if (!pdata) {
18283d0407baSopenharmony_ci        return -ENOMEM;
18293d0407baSopenharmony_ci    }
18303d0407baSopenharmony_ci
18313d0407baSopenharmony_ci    battery->pdata = pdata;
18323d0407baSopenharmony_ci    /* init default param */
18333d0407baSopenharmony_ci    pdata->bat_res = DEFAULT_BAT_RES;
18343d0407baSopenharmony_ci    pdata->monitor_sec = DEFAULT_MONITOR_SEC;
18353d0407baSopenharmony_ci    pdata->pwroff_vol = DEFAULT_PWROFF_VOL_THRESD;
18363d0407baSopenharmony_ci    pdata->sleep_exit_current = DEFAULT_SLP_EXIT_CUR;
18373d0407baSopenharmony_ci    pdata->sleep_enter_current = DEFAULT_SLP_ENTER_CUR;
18383d0407baSopenharmony_ci
18393d0407baSopenharmony_ci    pdata->sleep_filter_current = DEFAULT_SLP_FILTER_CUR;
18403d0407baSopenharmony_ci    pdata->bat_mode = MODE_BATTARY;
18413d0407baSopenharmony_ci    pdata->max_soc_offset = DEFAULT_MAX_SOC_OFFSET;
18423d0407baSopenharmony_ci    pdata->fb_temp = DEFAULT_FB_TEMP;
18433d0407baSopenharmony_ci    pdata->energy_mode = DEFAULT_ENERGY_MODE;
18443d0407baSopenharmony_ci    pdata->zero_reserve_dsoc = DEFAULT_ZERO_RESERVE_DSOC * 0x3E8;
18453d0407baSopenharmony_ci
18463d0407baSopenharmony_ci    pdata->sample_res = DEFAULT_SAMPLE_RES;
18473d0407baSopenharmony_ci
18483d0407baSopenharmony_ci    /* parse necessary param */
18493d0407baSopenharmony_ci    if (!of_find_property(np, "ocv_table", &length)) {
18503d0407baSopenharmony_ci        dev_err(dev, "ocv_table not found!\n");
18513d0407baSopenharmony_ci        return -EINVAL;
18523d0407baSopenharmony_ci    }
18533d0407baSopenharmony_ci
18543d0407baSopenharmony_ci    pdata->ocv_size = length / sizeof(u32);
18553d0407baSopenharmony_ci    if (pdata->ocv_size <= 0) {
18563d0407baSopenharmony_ci        dev_err(dev, "invalid ocv table\n");
18573d0407baSopenharmony_ci        return -EINVAL;
18583d0407baSopenharmony_ci    }
18593d0407baSopenharmony_ci
18603d0407baSopenharmony_ci    size = sizeof(*pdata->ocv_table) * pdata->ocv_size;
18613d0407baSopenharmony_ci    pdata->ocv_table = devm_kzalloc(battery->dev, size, GFP_KERNEL);
18623d0407baSopenharmony_ci    if (!pdata->ocv_table) {
18633d0407baSopenharmony_ci        return -ENOMEM;
18643d0407baSopenharmony_ci    }
18653d0407baSopenharmony_ci
18663d0407baSopenharmony_ci    ret = of_property_read_u32_array(np, "ocv_table", pdata->ocv_table, pdata->ocv_size);
18673d0407baSopenharmony_ci    if (ret < 0) {
18683d0407baSopenharmony_ci        return ret;
18693d0407baSopenharmony_ci    }
18703d0407baSopenharmony_ci
18713d0407baSopenharmony_ci    ret = of_property_read_u32(np, "design_capacity", &out_value);
18723d0407baSopenharmony_ci    if (ret < 0) {
18733d0407baSopenharmony_ci        dev_err(dev, "design_capacity not found!\n");
18743d0407baSopenharmony_ci        return ret;
18753d0407baSopenharmony_ci    }
18763d0407baSopenharmony_ci    pdata->design_capacity = out_value;
18773d0407baSopenharmony_ci
18783d0407baSopenharmony_ci    ret = of_property_read_u32(np, "design_qmax", &out_value);
18793d0407baSopenharmony_ci    if (ret < 0) {
18803d0407baSopenharmony_ci        dev_err(dev, "design_qmax not found!\n");
18813d0407baSopenharmony_ci        return ret;
18823d0407baSopenharmony_ci    }
18833d0407baSopenharmony_ci    pdata->design_qmax = out_value;
18843d0407baSopenharmony_ci
18853d0407baSopenharmony_ci    /* parse unnecessary param */
18863d0407baSopenharmony_ci    ret = of_property_read_u32(np, "sample_res", &pdata->sample_res);
18873d0407baSopenharmony_ci    if (ret < 0) {
18883d0407baSopenharmony_ci        dev_err(dev, "sample_res missing!\n");
18893d0407baSopenharmony_ci    }
18903d0407baSopenharmony_ci
18913d0407baSopenharmony_ci    ret = of_property_read_u32(np, "fb_temperature", &pdata->fb_temp);
18923d0407baSopenharmony_ci    if (ret < 0) {
18933d0407baSopenharmony_ci        dev_err(dev, "fb_temperature missing!\n");
18943d0407baSopenharmony_ci    }
18953d0407baSopenharmony_ci
18963d0407baSopenharmony_ci    ret = of_property_read_u32(np, "energy_mode", &pdata->energy_mode);
18973d0407baSopenharmony_ci    if (ret < 0) {
18983d0407baSopenharmony_ci        dev_err(dev, "energy_mode missing!\n");
18993d0407baSopenharmony_ci    }
19003d0407baSopenharmony_ci
19013d0407baSopenharmony_ci    ret = of_property_read_u32(np, "max_soc_offset", &pdata->max_soc_offset);
19023d0407baSopenharmony_ci    if (ret < 0) {
19033d0407baSopenharmony_ci        dev_err(dev, "max_soc_offset missing!\n");
19043d0407baSopenharmony_ci    }
19053d0407baSopenharmony_ci
19063d0407baSopenharmony_ci    ret = of_property_read_u32(np, "monitor_sec", &pdata->monitor_sec);
19073d0407baSopenharmony_ci    if (ret < 0) {
19083d0407baSopenharmony_ci        dev_err(dev, "monitor_sec missing!\n");
19093d0407baSopenharmony_ci    }
19103d0407baSopenharmony_ci
19113d0407baSopenharmony_ci    ret = of_property_read_u32(np, "zero_algorithm_vol", &pdata->zero_algorithm_vol);
19123d0407baSopenharmony_ci    if (ret < 0) {
19133d0407baSopenharmony_ci        dev_err(dev, "zero_algorithm_vol missing!\n");
19143d0407baSopenharmony_ci    }
19153d0407baSopenharmony_ci
19163d0407baSopenharmony_ci    ret = of_property_read_u32(np, "zero_reserve_dsoc", &pdata->zero_reserve_dsoc);
19173d0407baSopenharmony_ci    if (ret < 0) {
19183d0407baSopenharmony_ci        dev_err(dev, "zero_reserve_dsoc missing!\n");
19193d0407baSopenharmony_ci    }
19203d0407baSopenharmony_ci    pdata->zero_reserve_dsoc *= 0x3E8;
19213d0407baSopenharmony_ci
19223d0407baSopenharmony_ci    ret = of_property_read_u32(np, "virtual_power", &pdata->bat_mode);
19233d0407baSopenharmony_ci    if (ret < 0) {
19243d0407baSopenharmony_ci        dev_err(dev, "virtual_power missing!\n");
19253d0407baSopenharmony_ci    }
19263d0407baSopenharmony_ci
19273d0407baSopenharmony_ci    ret = of_property_read_u32(np, "bat_res", &pdata->bat_res);
19283d0407baSopenharmony_ci    if (ret < 0) {
19293d0407baSopenharmony_ci        dev_err(dev, "bat_res missing!\n");
19303d0407baSopenharmony_ci    }
19313d0407baSopenharmony_ci
19323d0407baSopenharmony_ci    ret = of_property_read_u32(np, "sleep_enter_current", &pdata->sleep_enter_current);
19333d0407baSopenharmony_ci    if (ret < 0) {
19343d0407baSopenharmony_ci        dev_err(dev, "sleep_enter_current missing!\n");
19353d0407baSopenharmony_ci    }
19363d0407baSopenharmony_ci
19373d0407baSopenharmony_ci    ret = of_property_read_u32(np, "sleep_exit_current", &pdata->sleep_exit_current);
19383d0407baSopenharmony_ci    if (ret < 0) {
19393d0407baSopenharmony_ci        dev_err(dev, "sleep_exit_current missing!\n");
19403d0407baSopenharmony_ci    }
19413d0407baSopenharmony_ci
19423d0407baSopenharmony_ci    ret = of_property_read_u32(np, "sleep_filter_current", &pdata->sleep_filter_current);
19433d0407baSopenharmony_ci    if (ret < 0) {
19443d0407baSopenharmony_ci        dev_err(dev, "sleep_filter_current missing!\n");
19453d0407baSopenharmony_ci    }
19463d0407baSopenharmony_ci
19473d0407baSopenharmony_ci    ret = of_property_read_u32(np, "power_off_thresd", &pdata->pwroff_vol);
19483d0407baSopenharmony_ci    if (ret < 0) {
19493d0407baSopenharmony_ci        dev_err(dev, "power_off_thresd missing!\n");
19503d0407baSopenharmony_ci    }
19513d0407baSopenharmony_ci
19523d0407baSopenharmony_ci    ret = of_property_read_u32(np, "low_power_sleep", &pdata->low_pwr_sleep);
19533d0407baSopenharmony_ci    if (ret < 0) {
19543d0407baSopenharmony_ci        dev_info(dev, "low_power_sleep missing!\n");
19553d0407baSopenharmony_ci    }
19563d0407baSopenharmony_ci
19573d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
19583d0407baSopenharmony_ci        ret = of_property_read_u32(np, "bat_res_up", &pdata->bat_res_up);
19593d0407baSopenharmony_ci        if (ret < 0) {
19603d0407baSopenharmony_ci            dev_err(dev, "battery res_up missing\n");
19613d0407baSopenharmony_ci        }
19623d0407baSopenharmony_ci
19633d0407baSopenharmony_ci        ret = of_property_read_u32(np, "bat_res_down", &pdata->bat_res_down);
19643d0407baSopenharmony_ci        if (ret < 0) {
19653d0407baSopenharmony_ci            dev_err(dev, "battery res_down missing!\n");
19663d0407baSopenharmony_ci        }
19673d0407baSopenharmony_ci
19683d0407baSopenharmony_ci        ret = of_property_read_u32(np, "design_max_voltage", &pdata->design_max_voltage);
19693d0407baSopenharmony_ci        if (ret < 0) {
19703d0407baSopenharmony_ci            dev_err(dev, "battery design_max_voltage missing!\n");
19713d0407baSopenharmony_ci        }
19723d0407baSopenharmony_ci
19733d0407baSopenharmony_ci        ret = of_property_read_u32(np, "register_chg_psy", &battery->is_register_chg_psy);
19743d0407baSopenharmony_ci        if (ret < 0 || !battery->is_register_chg_psy) {
19753d0407baSopenharmony_ci            dev_err(dev, "not have to register chg psy!\n");
19763d0407baSopenharmony_ci        }
19773d0407baSopenharmony_ci    }
19783d0407baSopenharmony_ci
19793d0407baSopenharmony_ci    DBG("the battery dts info dump:\n"
19803d0407baSopenharmony_ci        "bat_res:%d\n"
19813d0407baSopenharmony_ci        "res_sample:%d\n"
19823d0407baSopenharmony_ci        "design_capacity:%d\n"
19833d0407baSopenharmony_ci        "design_qmax :%d\n"
19843d0407baSopenharmony_ci        "sleep_enter_current:%d\n"
19853d0407baSopenharmony_ci        "sleep_exit_current:%d\n"
19863d0407baSopenharmony_ci        "sleep_filter_current:%d\n"
19873d0407baSopenharmony_ci        "zero_algorithm_vol:%d\n"
19883d0407baSopenharmony_ci        "zero_reserve_dsoc:%d\n"
19893d0407baSopenharmony_ci        "monitor_sec:%d\n"
19903d0407baSopenharmony_ci        "max_soc_offset:%d\n"
19913d0407baSopenharmony_ci        "virtual_power:%d\n"
19923d0407baSopenharmony_ci        "pwroff_vol:%d\n",
19933d0407baSopenharmony_ci        pdata->bat_res, pdata->sample_res, pdata->design_capacity, pdata->design_qmax, pdata->sleep_enter_current,
19943d0407baSopenharmony_ci        pdata->sleep_exit_current, pdata->sleep_filter_current, pdata->zero_algorithm_vol, pdata->zero_reserve_dsoc,
19953d0407baSopenharmony_ci        pdata->monitor_sec, pdata->max_soc_offset, pdata->bat_mode, pdata->pwroff_vol);
19963d0407baSopenharmony_ci
19973d0407baSopenharmony_ci    return 0;
19983d0407baSopenharmony_ci}
19993d0407baSopenharmony_ci
20003d0407baSopenharmony_cistatic enum power_supply_property rk817_bat_props[] = {
20013d0407baSopenharmony_ci    POWER_SUPPLY_PROP_STATUS,
20023d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CURRENT_NOW,
20033d0407baSopenharmony_ci    POWER_SUPPLY_PROP_VOLTAGE_NOW,
20043d0407baSopenharmony_ci    POWER_SUPPLY_PROP_HEALTH,
20053d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CAPACITY,
20063d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CAPACITY_LEVEL,
20073d0407baSopenharmony_ci    POWER_SUPPLY_PROP_TEMP,
20083d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CHARGE_COUNTER,
20093d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CHARGE_FULL,
20103d0407baSopenharmony_ci    POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
20113d0407baSopenharmony_ci    POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
20123d0407baSopenharmony_ci};
20133d0407baSopenharmony_ci
20143d0407baSopenharmony_cistatic int rk817_bat_get_usb_psy(struct device *dev, void *data)
20153d0407baSopenharmony_ci{
20163d0407baSopenharmony_ci    struct rk817_battery_device *battery = data;
20173d0407baSopenharmony_ci    struct power_supply *psy = dev_get_drvdata(dev);
20183d0407baSopenharmony_ci
20193d0407baSopenharmony_ci    if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {
20203d0407baSopenharmony_ci        battery->usb_psy = psy;
20213d0407baSopenharmony_ci        return 1;
20223d0407baSopenharmony_ci    }
20233d0407baSopenharmony_ci
20243d0407baSopenharmony_ci    return 0;
20253d0407baSopenharmony_ci}
20263d0407baSopenharmony_ci
20273d0407baSopenharmony_cistatic int rk817_bat_get_ac_psy(struct device *dev, void *data)
20283d0407baSopenharmony_ci{
20293d0407baSopenharmony_ci    struct rk817_battery_device *battery = data;
20303d0407baSopenharmony_ci    struct power_supply *psy = dev_get_drvdata(dev);
20313d0407baSopenharmony_ci
20323d0407baSopenharmony_ci    if (psy->desc->type == POWER_SUPPLY_TYPE_MAINS) {
20333d0407baSopenharmony_ci        battery->ac_psy = psy;
20343d0407baSopenharmony_ci        return 1;
20353d0407baSopenharmony_ci    }
20363d0407baSopenharmony_ci
20373d0407baSopenharmony_ci    return 0;
20383d0407baSopenharmony_ci}
20393d0407baSopenharmony_ci
20403d0407baSopenharmony_cistatic void rk817_bat_get_chrg_psy(struct rk817_battery_device *battery)
20413d0407baSopenharmony_ci{
20423d0407baSopenharmony_ci    if (!battery->usb_psy) {
20433d0407baSopenharmony_ci        class_for_each_device(power_supply_class, NULL, (void *)battery, rk817_bat_get_usb_psy);
20443d0407baSopenharmony_ci    }
20453d0407baSopenharmony_ci    if (!battery->ac_psy) {
20463d0407baSopenharmony_ci        class_for_each_device(power_supply_class, NULL, (void *)battery, rk817_bat_get_ac_psy);
20473d0407baSopenharmony_ci    }
20483d0407baSopenharmony_ci}
20493d0407baSopenharmony_ci
20503d0407baSopenharmony_cistatic int rk817_bat_get_charge_state(struct rk817_battery_device *battery)
20513d0407baSopenharmony_ci{
20523d0407baSopenharmony_ci    union power_supply_propval val;
20533d0407baSopenharmony_ci    int ret;
20543d0407baSopenharmony_ci    struct power_supply *psy;
20553d0407baSopenharmony_ci
20563d0407baSopenharmony_ci    if (!battery->usb_psy || !battery->ac_psy) {
20573d0407baSopenharmony_ci        rk817_bat_get_chrg_psy(battery);
20583d0407baSopenharmony_ci    }
20593d0407baSopenharmony_ci
20603d0407baSopenharmony_ci    psy = battery->usb_psy;
20613d0407baSopenharmony_ci    if (psy) {
20623d0407baSopenharmony_ci        ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
20633d0407baSopenharmony_ci        if (!ret) {
20643d0407baSopenharmony_ci            battery->usb_in = val.intval;
20653d0407baSopenharmony_ci        }
20663d0407baSopenharmony_ci    }
20673d0407baSopenharmony_ci
20683d0407baSopenharmony_ci    psy = battery->ac_psy;
20693d0407baSopenharmony_ci    if (psy) {
20703d0407baSopenharmony_ci        ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
20713d0407baSopenharmony_ci        if (!ret) {
20723d0407baSopenharmony_ci            battery->ac_in = val.intval;
20733d0407baSopenharmony_ci        }
20743d0407baSopenharmony_ci    }
20753d0407baSopenharmony_ci
20763d0407baSopenharmony_ci    DBG("%s: ac_online=%d, usb_online=%d\n", __func__, battery->ac_in, battery->usb_in);
20773d0407baSopenharmony_ci
20783d0407baSopenharmony_ci    return (battery->usb_in || battery->ac_in);
20793d0407baSopenharmony_ci}
20803d0407baSopenharmony_ci
20813d0407baSopenharmony_cistatic int rk817_get_capacity_leve(struct rk817_battery_device *battery)
20823d0407baSopenharmony_ci{
20833d0407baSopenharmony_ci    int dsoc;
20843d0407baSopenharmony_ci
20853d0407baSopenharmony_ci    if (battery->pdata->bat_mode == MODE_VIRTUAL) {
20863d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
20873d0407baSopenharmony_ci    }
20883d0407baSopenharmony_ci
20893d0407baSopenharmony_ci    dsoc = (battery->dsoc + 0x1F4) / 0X3E8;
20903d0407baSopenharmony_ci    if (dsoc < 1) {
20913d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
20923d0407baSopenharmony_ci    } else if (dsoc <= 0X14) {
20933d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
20943d0407baSopenharmony_ci    } else if (dsoc <= 0X46) {
20953d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
20963d0407baSopenharmony_ci    } else if (dsoc <= 0X5A) {
20973d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
20983d0407baSopenharmony_ci    } else {
20993d0407baSopenharmony_ci        return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
21003d0407baSopenharmony_ci    }
21013d0407baSopenharmony_ci}
21023d0407baSopenharmony_ci
21033d0407baSopenharmony_cistatic int rk817_battery_time_to_full(struct rk817_battery_device *battery)
21043d0407baSopenharmony_ci{
21053d0407baSopenharmony_ci    int time_sec;
21063d0407baSopenharmony_ci    int cap_temp;
21073d0407baSopenharmony_ci
21083d0407baSopenharmony_ci    if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21093d0407baSopenharmony_ci        time_sec = 0xE10;
21103d0407baSopenharmony_ci    } else if (battery->voltage_avg > 0) {
21113d0407baSopenharmony_ci        cap_temp = battery->design_cap - (battery->remain_cap / 0x3E8);
21123d0407baSopenharmony_ci        if (cap_temp < 0) {
21133d0407baSopenharmony_ci            cap_temp = 0;
21143d0407baSopenharmony_ci        }
21153d0407baSopenharmony_ci        time_sec = (0xE10 * cap_temp) / battery->voltage_avg;
21163d0407baSopenharmony_ci    } else {
21173d0407baSopenharmony_ci        time_sec = 0xE10 * 0x18; /* One day */
21183d0407baSopenharmony_ci    }
21193d0407baSopenharmony_ci
21203d0407baSopenharmony_ci    return time_sec;
21213d0407baSopenharmony_ci}
21223d0407baSopenharmony_ci
21233d0407baSopenharmony_cistatic int rk817_battery_get_property(struct power_supply *psy, enum power_supply_property psp,
21243d0407baSopenharmony_ci                                      union power_supply_propval *val)
21253d0407baSopenharmony_ci{
21263d0407baSopenharmony_ci    struct rk817_battery_device *battery = power_supply_get_drvdata(psy);
21273d0407baSopenharmony_ci
21283d0407baSopenharmony_ci    switch (psp) {
21293d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CURRENT_NOW:
21303d0407baSopenharmony_ci            val->intval = battery->current_avg * 0x3E8; /* uA */
21313d0407baSopenharmony_ci            if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21323d0407baSopenharmony_ci                val->intval = VIRTUAL_CURRENT * 0x3E8;
21333d0407baSopenharmony_ci            }
21343d0407baSopenharmony_ci            break;
21353d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
21363d0407baSopenharmony_ci            val->intval = battery->voltage_avg * 0x3E8; /* uV */
21373d0407baSopenharmony_ci            if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21383d0407baSopenharmony_ci                val->intval = VIRTUAL_VOLTAGE * 0x3E8;
21393d0407baSopenharmony_ci            }
21403d0407baSopenharmony_ci            break;
21413d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CAPACITY:
21423d0407baSopenharmony_ci            val->intval = (battery->dsoc + 0x1F4) / 0x3E8;
21433d0407baSopenharmony_ci            if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21443d0407baSopenharmony_ci                val->intval = VIRTUAL_SOC;
21453d0407baSopenharmony_ci            }
21463d0407baSopenharmony_ci            break;
21473d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
21483d0407baSopenharmony_ci            val->intval = rk817_get_capacity_leve(battery);
21493d0407baSopenharmony_ci            break;
21503d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_HEALTH:
21513d0407baSopenharmony_ci            val->intval = POWER_SUPPLY_HEALTH_GOOD;
21523d0407baSopenharmony_ci            break;
21533d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_TEMP:
21543d0407baSopenharmony_ci            val->intval = battery->temperature;
21553d0407baSopenharmony_ci            if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21563d0407baSopenharmony_ci                val->intval = VIRTUAL_TEMPERATURE;
21573d0407baSopenharmony_ci            }
21583d0407baSopenharmony_ci            break;
21593d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_STATUS:
21603d0407baSopenharmony_ci            if (battery->pdata->bat_mode == MODE_VIRTUAL) {
21613d0407baSopenharmony_ci                val->intval = VIRTUAL_STATUS;
21623d0407baSopenharmony_ci            } else if (battery->dsoc == 0x64 * 0x3E8) {
21633d0407baSopenharmony_ci                val->intval = POWER_SUPPLY_STATUS_FULL;
21643d0407baSopenharmony_ci            } else {
21653d0407baSopenharmony_ci                if ((battery->chip_id != RK809_ID) && rk817_bat_get_charge_state(battery)) {
21663d0407baSopenharmony_ci                    val->intval = POWER_SUPPLY_STATUS_CHARGING;
21673d0407baSopenharmony_ci                } else if (battery->chip_id == RK809_ID && battery->plugin_trigger) {
21683d0407baSopenharmony_ci                    val->intval = POWER_SUPPLY_STATUS_CHARGING;
21693d0407baSopenharmony_ci                } else {
21703d0407baSopenharmony_ci                    val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
21713d0407baSopenharmony_ci                }
21723d0407baSopenharmony_ci            }
21733d0407baSopenharmony_ci            break;
21743d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CHARGE_COUNTER:
21753d0407baSopenharmony_ci            val->intval = battery->charge_count;
21763d0407baSopenharmony_ci            break;
21773d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CHARGE_FULL:
21783d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
21793d0407baSopenharmony_ci            val->intval = battery->pdata->design_capacity * 0x3E8; /* uAh */
21803d0407baSopenharmony_ci            break;
21813d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
21823d0407baSopenharmony_ci            val->intval = rk817_battery_time_to_full(battery);
21833d0407baSopenharmony_ci            break;
21843d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_VOLTAGE_MAX:
21853d0407baSopenharmony_ci            val->intval = 0x1194 * 0x3E8;
21863d0407baSopenharmony_ci            break;
21873d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_CURRENT_MAX:
21883d0407baSopenharmony_ci            val->intval = 0x1388 * 0x3E8;
21893d0407baSopenharmony_ci            break;
21903d0407baSopenharmony_ci        default:
21913d0407baSopenharmony_ci            return -EINVAL;
21923d0407baSopenharmony_ci    }
21933d0407baSopenharmony_ci
21943d0407baSopenharmony_ci    return 0;
21953d0407baSopenharmony_ci}
21963d0407baSopenharmony_ci
21973d0407baSopenharmony_cistatic const struct power_supply_desc rk817_bat_desc = {
21983d0407baSopenharmony_ci    .name = "battery",
21993d0407baSopenharmony_ci    .type = POWER_SUPPLY_TYPE_BATTERY,
22003d0407baSopenharmony_ci    .properties = rk817_bat_props,
22013d0407baSopenharmony_ci    .num_properties = ARRAY_SIZE(rk817_bat_props),
22023d0407baSopenharmony_ci    .get_property = rk817_battery_get_property,
22033d0407baSopenharmony_ci};
22043d0407baSopenharmony_ci
22053d0407baSopenharmony_cistatic int rk817_bat_init_power_supply(struct rk817_battery_device *battery)
22063d0407baSopenharmony_ci{
22073d0407baSopenharmony_ci    struct power_supply_config psy_cfg = {
22083d0407baSopenharmony_ci        .drv_data = battery,
22093d0407baSopenharmony_ci    };
22103d0407baSopenharmony_ci
22113d0407baSopenharmony_ci    battery->bat = devm_power_supply_register(battery->dev, &rk817_bat_desc, &psy_cfg);
22123d0407baSopenharmony_ci    if (IS_ERR(battery->bat)) {
22133d0407baSopenharmony_ci        dev_err(battery->dev, "register bat power supply fail\n");
22143d0407baSopenharmony_ci        return PTR_ERR(battery->bat);
22153d0407baSopenharmony_ci    }
22163d0407baSopenharmony_ci
22173d0407baSopenharmony_ci    return 0;
22183d0407baSopenharmony_ci}
22193d0407baSopenharmony_ci
22203d0407baSopenharmony_cistatic enum power_supply_property rk809_chg_props[] = {
22213d0407baSopenharmony_ci    POWER_SUPPLY_PROP_ONLINE,
22223d0407baSopenharmony_ci    POWER_SUPPLY_PROP_STATUS,
22233d0407baSopenharmony_ci};
22243d0407baSopenharmony_ci
22253d0407baSopenharmony_cistatic int rk809_chg_get_property(struct power_supply *psy, enum power_supply_property psp,
22263d0407baSopenharmony_ci                                  union power_supply_propval *val)
22273d0407baSopenharmony_ci{
22283d0407baSopenharmony_ci    struct rk817_battery_device *battery = power_supply_get_drvdata(psy);
22293d0407baSopenharmony_ci    int online = 0;
22303d0407baSopenharmony_ci    int ret = 0;
22313d0407baSopenharmony_ci
22323d0407baSopenharmony_ci    if (battery->plugin_trigger) {
22333d0407baSopenharmony_ci        online = 1;
22343d0407baSopenharmony_ci    }
22353d0407baSopenharmony_ci    switch (psp) {
22363d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_ONLINE:
22373d0407baSopenharmony_ci            val->intval = online;
22383d0407baSopenharmony_ci            dev_dbg(battery->dev, "report online: %d\n", val->intval);
22393d0407baSopenharmony_ci            break;
22403d0407baSopenharmony_ci        case POWER_SUPPLY_PROP_STATUS:
22413d0407baSopenharmony_ci            if (online) {
22423d0407baSopenharmony_ci                val->intval = POWER_SUPPLY_STATUS_CHARGING;
22433d0407baSopenharmony_ci            } else {
22443d0407baSopenharmony_ci                val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
22453d0407baSopenharmony_ci            }
22463d0407baSopenharmony_ci            dev_dbg(battery->dev, "report prop: %d\n", val->intval);
22473d0407baSopenharmony_ci            break;
22483d0407baSopenharmony_ci        default:
22493d0407baSopenharmony_ci            ret = -EINVAL;
22503d0407baSopenharmony_ci            break;
22513d0407baSopenharmony_ci    }
22523d0407baSopenharmony_ci
22533d0407baSopenharmony_ci    return ret;
22543d0407baSopenharmony_ci}
22553d0407baSopenharmony_ci
22563d0407baSopenharmony_cistatic const struct power_supply_desc rk809_chg_desc = {
22573d0407baSopenharmony_ci    .name = "charger",
22583d0407baSopenharmony_ci    .type = POWER_SUPPLY_TYPE_USB,
22593d0407baSopenharmony_ci    .properties = rk809_chg_props,
22603d0407baSopenharmony_ci    .num_properties = ARRAY_SIZE(rk809_chg_props),
22613d0407baSopenharmony_ci    .get_property = rk809_chg_get_property,
22623d0407baSopenharmony_ci};
22633d0407baSopenharmony_ci
22643d0407baSopenharmony_cistatic int rk809_chg_init_power_supply(struct rk817_battery_device *battery)
22653d0407baSopenharmony_ci{
22663d0407baSopenharmony_ci    struct power_supply_config psy_cfg = {
22673d0407baSopenharmony_ci        .drv_data = battery,
22683d0407baSopenharmony_ci    };
22693d0407baSopenharmony_ci
22703d0407baSopenharmony_ci    battery->chg_psy = devm_power_supply_register(battery->dev, &rk809_chg_desc, &psy_cfg);
22713d0407baSopenharmony_ci    if (IS_ERR(battery->chg_psy)) {
22723d0407baSopenharmony_ci        dev_err(battery->dev, "register chg psy power supply fail\n");
22733d0407baSopenharmony_ci        return PTR_ERR(battery->chg_psy);
22743d0407baSopenharmony_ci    }
22753d0407baSopenharmony_ci
22763d0407baSopenharmony_ci    return 0;
22773d0407baSopenharmony_ci}
22783d0407baSopenharmony_ci
22793d0407baSopenharmony_cistatic void rk817_bat_power_supply_changed(struct rk817_battery_device *battery)
22803d0407baSopenharmony_ci{
22813d0407baSopenharmony_ci    static int old_soc = -1;
22823d0407baSopenharmony_ci
22833d0407baSopenharmony_ci    if (battery->dsoc > 0x64 * 0x3E8) {
22843d0407baSopenharmony_ci        battery->dsoc = 0x64 * 0x3E8;
22853d0407baSopenharmony_ci    } else if (battery->dsoc < 0) {
22863d0407baSopenharmony_ci        battery->dsoc = 0;
22873d0407baSopenharmony_ci    }
22883d0407baSopenharmony_ci
22893d0407baSopenharmony_ci    if (battery->dsoc == old_soc && !battery->change) {
22903d0407baSopenharmony_ci        return;
22913d0407baSopenharmony_ci    }
22923d0407baSopenharmony_ci
22933d0407baSopenharmony_ci    battery->change = false;
22943d0407baSopenharmony_ci    old_soc = battery->dsoc;
22953d0407baSopenharmony_ci    battery->last_dsoc = battery->dsoc;
22963d0407baSopenharmony_ci    power_supply_changed(battery->bat);
22973d0407baSopenharmony_ci    DBG("changed: dsoc=%d, rsoc=%d, v=%d, ov=%d c=%d, cap=%d, f=%d\n", battery->dsoc, battery->rsoc,
22983d0407baSopenharmony_ci        battery->voltage_avg, battery->voltage_ocv, battery->current_avg, battery->remain_cap, battery->fcc);
22993d0407baSopenharmony_ci
23003d0407baSopenharmony_ci    DBG("dl=%d, rl=%d, v=%d, halt=%d, halt_n=%d, max=%d\n"
23013d0407baSopenharmony_ci        "init=%d, sw=%d, calib=%d, below0=%d, force=%d\n",
23023d0407baSopenharmony_ci        battery->dbg_pwr_dsoc, battery->dbg_pwr_rsoc, battery->dbg_pwr_vol, battery->is_halt, battery->halt_cnt,
23033d0407baSopenharmony_ci        battery->is_max_soc_offset, battery->is_initialized, battery->is_sw_reset, battery->is_ocv_calib,
23043d0407baSopenharmony_ci        battery->dbg_cap_low0, battery->is_force_calib);
23053d0407baSopenharmony_ci}
23063d0407baSopenharmony_ci
23073d0407baSopenharmony_cistatic void rk817_battery_debug_info(struct rk817_battery_device *battery)
23083d0407baSopenharmony_ci{
23093d0407baSopenharmony_ci    rk817_bat_get_battery_voltage(battery);
23103d0407baSopenharmony_ci    rk817_bat_get_sys_voltage(battery);
23113d0407baSopenharmony_ci    rk817_bat_get_USB_voltage(battery);
23123d0407baSopenharmony_ci    rk817_bat_get_pwron_voltage(battery);
23133d0407baSopenharmony_ci    rk817_bat_get_ocv_voltage(battery);
23143d0407baSopenharmony_ci    rk817_bat_get_ocv0_voltage0(battery);
23153d0407baSopenharmony_ci
23163d0407baSopenharmony_ci    rk817_bat_current_calibration(battery);
23173d0407baSopenharmony_ci    rk817_bat_get_avg_current(battery);
23183d0407baSopenharmony_ci    rk817_bat_get_relax_cur1(battery);
23193d0407baSopenharmony_ci    rk817_bat_get_relax_cur2(battery);
23203d0407baSopenharmony_ci    rk817_bat_get_relax_current(battery);
23213d0407baSopenharmony_ci    rk817_bat_get_ocv_current(battery);
23223d0407baSopenharmony_ci    rk817_bat_get_ocv_current0(battery);
23233d0407baSopenharmony_ci    rk817_bat_get_pwron_current(battery);
23243d0407baSopenharmony_ci    rk817_bat_get_ocv_count(battery);
23253d0407baSopenharmony_ci    rk817_bat_save_dsoc(battery, battery->dsoc);
23263d0407baSopenharmony_ci    DBG("capactiy = %d\n", rk817_bat_get_capacity_mah(battery));
23273d0407baSopenharmony_ci}
23283d0407baSopenharmony_ci
23293d0407baSopenharmony_cistatic void rk817_bat_update_charging_status(struct rk817_battery_device *battery)
23303d0407baSopenharmony_ci{
23313d0407baSopenharmony_ci    int is_charging;
23323d0407baSopenharmony_ci
23333d0407baSopenharmony_ci    is_charging = rk817_bat_get_charge_state(battery);
23343d0407baSopenharmony_ci    if (is_charging == battery->is_charging) {
23353d0407baSopenharmony_ci        return;
23363d0407baSopenharmony_ci    }
23373d0407baSopenharmony_ci
23383d0407baSopenharmony_ci    battery->change = true;
23393d0407baSopenharmony_ci    battery->is_charging = is_charging;
23403d0407baSopenharmony_ci    if (is_charging) {
23413d0407baSopenharmony_ci        battery->charge_count++;
23423d0407baSopenharmony_ci    }
23433d0407baSopenharmony_ci}
23443d0407baSopenharmony_ci
23453d0407baSopenharmony_cistatic void rk817_bat_update_info(struct rk817_battery_device *battery)
23463d0407baSopenharmony_ci{
23473d0407baSopenharmony_ci    battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
23483d0407baSopenharmony_ci    battery->voltage_sys = rk817_bat_get_sys_voltage(battery);
23493d0407baSopenharmony_ci    battery->current_avg = rk817_bat_get_avg_current(battery);
23503d0407baSopenharmony_ci    battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
23513d0407baSopenharmony_ci    battery->rsoc = rk817_bat_get_rsoc(battery);
23523d0407baSopenharmony_ci    battery->remain_cap = rk817_bat_get_capacity_uah(battery);
23533d0407baSopenharmony_ci    battery->voltage_usb = rk817_bat_get_USB_voltage(battery);
23543d0407baSopenharmony_ci    battery->chrg_status = get_charge_status(battery);
23553d0407baSopenharmony_ci    rk817_bat_update_charging_status(battery);
23563d0407baSopenharmony_ci    DBG("valtage usb: %d\n", battery->voltage_usb);
23573d0407baSopenharmony_ci    DBG("UPDATE: voltage_avg = %d\n"
23583d0407baSopenharmony_ci        "voltage_sys = %d\n"
23593d0407baSopenharmony_ci        "curren_avg = %d\n"
23603d0407baSopenharmony_ci        "rsoc = %d\n"
23613d0407baSopenharmony_ci        "chrg_status = %d\n"
23623d0407baSopenharmony_ci        "PWRON_CUR = %d\n"
23633d0407baSopenharmony_ci        "remain_cap = %d\n",
23643d0407baSopenharmony_ci        battery->voltage_avg, battery->voltage_sys, battery->current_avg, battery->rsoc, battery->chrg_status,
23653d0407baSopenharmony_ci        rk817_bat_get_pwron_current(battery), battery->remain_cap);
23663d0407baSopenharmony_ci
23673d0407baSopenharmony_ci    /* smooth charge */
23683d0407baSopenharmony_ci    if (battery->remain_cap / 0x3E8 > battery->fcc) {
23693d0407baSopenharmony_ci        /* battery->sm_remain_cap -= */
23703d0407baSopenharmony_ci        battery->sm_remain_cap = battery->fcc * 0x3E8;
23713d0407baSopenharmony_ci        DBG("<%s>. cap: remain=%d, sm_remain=%d\n", __func__, battery->remain_cap, battery->sm_remain_cap);
23723d0407baSopenharmony_ci        DBG("fcc: %d\n", battery->fcc);
23733d0407baSopenharmony_ci        rk817_bat_init_coulomb_cap(battery, battery->fcc + 0x64);
23743d0407baSopenharmony_ci        rk817_bat_init_coulomb_cap(battery, battery->fcc);
23753d0407baSopenharmony_ci        rk817_bat_get_capacity_mah(battery);
23763d0407baSopenharmony_ci    }
23773d0407baSopenharmony_ci
23783d0407baSopenharmony_ci    if (battery->chrg_status != CHARGE_FINISH) {
23793d0407baSopenharmony_ci        battery->finish_base = get_boot_sec();
23803d0407baSopenharmony_ci    }
23813d0407baSopenharmony_ci}
23823d0407baSopenharmony_ci
23833d0407baSopenharmony_cistatic void rk817_bat_save_data(struct rk817_battery_device *battery)
23843d0407baSopenharmony_ci{
23853d0407baSopenharmony_ci    rk817_bat_save_dsoc(battery, battery->dsoc);
23863d0407baSopenharmony_ci    rk817_bat_save_cap(battery, battery->remain_cap / 0x3E8);
23873d0407baSopenharmony_ci}
23883d0407baSopenharmony_ci
23893d0407baSopenharmony_ci/* high load: current < 0 with charger in.
23903d0407baSopenharmony_ci * System will not shutdown while dsoc=0% with charging state(ac_in),
23913d0407baSopenharmony_ci * which will cause over discharge, so oppose status before report states.
23923d0407baSopenharmony_ci */
23933d0407baSopenharmony_cistatic void rk817_bat_lowpwr_check(struct rk817_battery_device *battery)
23943d0407baSopenharmony_ci{
23953d0407baSopenharmony_ci    static u64 time;
23963d0407baSopenharmony_ci    int pwr_off_thresd = battery->pdata->pwroff_vol;
23973d0407baSopenharmony_ci
23983d0407baSopenharmony_ci    if (battery->current_avg < 0 && battery->voltage_avg < pwr_off_thresd) {
23993d0407baSopenharmony_ci        if (!time) {
24003d0407baSopenharmony_ci            time = get_boot_sec();
24013d0407baSopenharmony_ci        }
24023d0407baSopenharmony_ci
24033d0407baSopenharmony_ci        if ((base2sec(time) > MINUTE(1)) || (battery->voltage_avg <= pwr_off_thresd - 0x32)) {
24043d0407baSopenharmony_ci            battery->fake_offline = 1;
24053d0407baSopenharmony_ci            if (battery->voltage_avg <= pwr_off_thresd - 0x32) {
24063d0407baSopenharmony_ci                battery->dsoc -= 0x3E8;
24073d0407baSopenharmony_ci            }
24083d0407baSopenharmony_ci            DBG("low power, soc=%d, current=%d\n", battery->dsoc, battery->current_avg);
24093d0407baSopenharmony_ci        }
24103d0407baSopenharmony_ci    } else {
24113d0407baSopenharmony_ci        time = 0;
24123d0407baSopenharmony_ci        battery->fake_offline = 0;
24133d0407baSopenharmony_ci    }
24143d0407baSopenharmony_ci
24153d0407baSopenharmony_ci    DBG("<%s>. t=%lu, dsoc=%d, current=%d, fake_offline=%d\n", __func__, base2sec(time), battery->dsoc,
24163d0407baSopenharmony_ci        battery->current_avg, battery->fake_offline);
24173d0407baSopenharmony_ci}
24183d0407baSopenharmony_ci
24193d0407baSopenharmony_cistatic void rk817_bat_calc_smooth_dischrg(struct rk817_battery_device *battery)
24203d0407baSopenharmony_ci{
24213d0407baSopenharmony_ci    int tmp_soc = 0;
24223d0407baSopenharmony_ci
24233d0407baSopenharmony_ci    /* check new dsoc */
24243d0407baSopenharmony_ci    if (battery->smooth_soc < 0) {
24253d0407baSopenharmony_ci        battery->smooth_soc = 0;
24263d0407baSopenharmony_ci    }
24273d0407baSopenharmony_ci
24283d0407baSopenharmony_ci    tmp_soc = battery->smooth_soc / 0x3E8;
24293d0407baSopenharmony_ci
24303d0407baSopenharmony_ci    if (tmp_soc != battery->dsoc / 0x3E8) {
24313d0407baSopenharmony_ci        if (battery->smooth_soc > battery->dsoc) {
24323d0407baSopenharmony_ci            return;
24333d0407baSopenharmony_ci        }
24343d0407baSopenharmony_ci
24353d0407baSopenharmony_ci        if (battery->smooth_soc + 0x3E8 > battery->dsoc) {
24363d0407baSopenharmony_ci            battery->dsoc = battery->smooth_soc;
24373d0407baSopenharmony_ci        } else {
24383d0407baSopenharmony_ci            battery->dsoc -= 0x3E8;
24393d0407baSopenharmony_ci        }
24403d0407baSopenharmony_ci
24413d0407baSopenharmony_ci        if (battery->dsoc <= 0) {
24423d0407baSopenharmony_ci            battery->dsoc = 0;
24433d0407baSopenharmony_ci        }
24443d0407baSopenharmony_ci    }
24453d0407baSopenharmony_ci}
24463d0407baSopenharmony_ci
24473d0407baSopenharmony_cistatic void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery)
24483d0407baSopenharmony_ci{
24493d0407baSopenharmony_ci    int ydsoc = 0, delta_cap = 0, old_cap = 0, tmp_soc;
24503d0407baSopenharmony_ci
24513d0407baSopenharmony_ci    int diff, delta;
24523d0407baSopenharmony_ci    delta = abs(battery->dsoc - battery->rsoc);
24533d0407baSopenharmony_ci    diff = delta * 3; /* speed:3/4 */
24543d0407baSopenharmony_ci
24553d0407baSopenharmony_ci    /* charge and discharge switch */
24563d0407baSopenharmony_ci    if ((battery->sm_linek * battery->current_avg <= 0)) {
24573d0407baSopenharmony_ci        DBG("<%s>. linek mode, retinit sm linek..\n", __func__);
24583d0407baSopenharmony_ci        rk817_bat_calc_sm_linek(battery);
24593d0407baSopenharmony_ci    }
24603d0407baSopenharmony_ci
24613d0407baSopenharmony_ci    battery->remain_cap = rk817_bat_get_capacity_uah(battery);
24623d0407baSopenharmony_ci
24633d0407baSopenharmony_ci    old_cap = battery->sm_remain_cap;
24643d0407baSopenharmony_ci    DBG("smooth: smooth_soc = %d, dsoc = %d, battery->sm_linek = %d\n", battery->smooth_soc, battery->dsoc,
24653d0407baSopenharmony_ci        battery->sm_linek);
24663d0407baSopenharmony_ci
24673d0407baSopenharmony_ci    /* discharge status: sm_remain_cap > remain_cap, delta_cap > 0 */
24683d0407baSopenharmony_ci    /* from charge to discharge:
24693d0407baSopenharmony_ci     * remain_cap may be above sm_remain_cap, delta_cap <= 0
24703d0407baSopenharmony_ci     */
24713d0407baSopenharmony_ci    delta_cap = battery->remain_cap - battery->sm_remain_cap;
24723d0407baSopenharmony_ci    DBG("smooth: sm_remain_cap = %d, remain_cap = %d\n", battery->sm_remain_cap, battery->remain_cap);
24733d0407baSopenharmony_ci    DBG("smooth: delta_cap = %d, dsoc = %d\n", delta_cap, battery->dsoc);
24743d0407baSopenharmony_ci
24753d0407baSopenharmony_ci    if (delta_cap == 0) {
24763d0407baSopenharmony_ci        DBG("<%s>. delta_cap = 0\n", __func__);
24773d0407baSopenharmony_ci        return;
24783d0407baSopenharmony_ci    }
24793d0407baSopenharmony_ci
24803d0407baSopenharmony_ci    /* discharge: sm_linek < 0, if delate_cap <0, ydsoc > 0 */
24813d0407baSopenharmony_ci    ydsoc = battery->sm_linek * abs(delta_cap / 0x0A) / DIV(battery->fcc);
24823d0407baSopenharmony_ci
24833d0407baSopenharmony_ci    DBG("smooth: ydsoc = %d, fcc = %d\n", ydsoc, battery->fcc);
24843d0407baSopenharmony_ci    if (ydsoc == 0) {
24853d0407baSopenharmony_ci        DBG("<%s>. ydsoc = 0\n", __func__);
24863d0407baSopenharmony_ci        return;
24873d0407baSopenharmony_ci    }
24883d0407baSopenharmony_ci    battery->sm_remain_cap = battery->remain_cap;
24893d0407baSopenharmony_ci
24903d0407baSopenharmony_ci    DBG("<%s>. k=%d, ydsoc=%d; cap:old=%d, new:%d; delta_cap=%d\n", __func__, battery->sm_linek, ydsoc, old_cap,
24913d0407baSopenharmony_ci        battery->sm_remain_cap, delta_cap);
24923d0407baSopenharmony_ci
24933d0407baSopenharmony_ci    /* discharge mode */
24943d0407baSopenharmony_ci    /* discharge mode, but ydsoc > 0,
24953d0407baSopenharmony_ci     * from charge status to dischrage
24963d0407baSopenharmony_ci     */
24973d0407baSopenharmony_ci    battery->smooth_soc += ydsoc;
24983d0407baSopenharmony_ci    if (ydsoc < 0) {
24993d0407baSopenharmony_ci        rk817_bat_calc_smooth_dischrg(battery);
25003d0407baSopenharmony_ci    } else {
25013d0407baSopenharmony_ci        if (battery->smooth_soc < 0) {
25023d0407baSopenharmony_ci            battery->smooth_soc = 0;
25033d0407baSopenharmony_ci        }
25043d0407baSopenharmony_ci
25053d0407baSopenharmony_ci        tmp_soc = battery->smooth_soc / 0x3E8;
25063d0407baSopenharmony_ci
25073d0407baSopenharmony_ci        if (tmp_soc != battery->dsoc / 0x3E8) {
25083d0407baSopenharmony_ci            if (battery->smooth_soc < battery->dsoc) {
25093d0407baSopenharmony_ci                return;
25103d0407baSopenharmony_ci            }
25113d0407baSopenharmony_ci
25123d0407baSopenharmony_ci            battery->dsoc = battery->smooth_soc;
25133d0407baSopenharmony_ci            if (battery->dsoc <= 0) {
25143d0407baSopenharmony_ci                battery->dsoc = 0;
25153d0407baSopenharmony_ci            }
25163d0407baSopenharmony_ci        }
25173d0407baSopenharmony_ci    }
25183d0407baSopenharmony_ci
25193d0407baSopenharmony_ci    if (battery->s2r) {
25203d0407baSopenharmony_ci        battery->s2r = false;
25213d0407baSopenharmony_ci        rk817_bat_calc_sm_linek(battery);
25223d0407baSopenharmony_ci    }
25233d0407baSopenharmony_ci
25243d0407baSopenharmony_ci    DBG("smooth: smooth_soc = %d, dsoc = %d\n", battery->smooth_soc, battery->dsoc);
25253d0407baSopenharmony_ci    DBG("smooth: delta_cap = %d, dsoc = %d\n", delta_cap, battery->dsoc);
25263d0407baSopenharmony_ci}
25273d0407baSopenharmony_ci
25283d0407baSopenharmony_cistatic void rk817_bat_calc_zero_linek(struct rk817_battery_device *battery)
25293d0407baSopenharmony_ci{
25303d0407baSopenharmony_ci    int dead_voltage, ocv_voltage;
25313d0407baSopenharmony_ci    int voltage_avg, current_avg, vsys;
25323d0407baSopenharmony_ci    int ocv_cap, dead_cap, xsoc;
25333d0407baSopenharmony_ci    int ocv_soc, dead_soc;
25343d0407baSopenharmony_ci    int pwroff_vol;
25353d0407baSopenharmony_ci    int min_gap_xsoc;
25363d0407baSopenharmony_ci    int powerpatch_res;
25373d0407baSopenharmony_ci
25383d0407baSopenharmony_ci    if ((abs(battery->current_avg) < 0x190) && (battery->dsoc / 0x3E8 > 0x05)) {
25393d0407baSopenharmony_ci        pwroff_vol = battery->pdata->pwroff_vol + 0x32;
25403d0407baSopenharmony_ci    } else {
25413d0407baSopenharmony_ci        pwroff_vol = battery->pdata->pwroff_vol;
25423d0407baSopenharmony_ci    }
25433d0407baSopenharmony_ci
25443d0407baSopenharmony_ci    /* calc estimate ocv voltage */
25453d0407baSopenharmony_ci    voltage_avg = rk817_bat_get_battery_voltage(battery);
25463d0407baSopenharmony_ci    current_avg = rk817_bat_get_avg_current(battery);
25473d0407baSopenharmony_ci    vsys = voltage_avg + (current_avg * DEF_PWRPATH_RES) / 0x3E8;
25483d0407baSopenharmony_ci
25493d0407baSopenharmony_ci    powerpatch_res = (voltage_avg - vsys) * 0x3E8 / current_avg;
25503d0407baSopenharmony_ci
25513d0407baSopenharmony_ci    battery->zero_voltage_avg = voltage_avg;
25523d0407baSopenharmony_ci    battery->zero_current_avg = current_avg;
25533d0407baSopenharmony_ci    battery->zero_vsys = vsys;
25543d0407baSopenharmony_ci
25553d0407baSopenharmony_ci    DBG("Zero: voltage_avg = %d, Vsys = %d\n", voltage_avg, vsys);
25563d0407baSopenharmony_ci    DBG("Zero: powerpatch_res = %d\n", powerpatch_res);
25573d0407baSopenharmony_ci    DBG("ZERO0: shtd_vol: poweroff_vol(usr) = %d\n"
25583d0407baSopenharmony_ci        "pwroff_vol = %d\n"
25593d0407baSopenharmony_ci        "zero_reserve_dsoc = %d\n",
25603d0407baSopenharmony_ci        battery->pdata->pwroff_vol, pwroff_vol, battery->pdata->zero_reserve_dsoc);
25613d0407baSopenharmony_ci
25623d0407baSopenharmony_ci    /* get the dead ocv voltage, pwroff_vol is vsys */
25633d0407baSopenharmony_ci    dead_voltage = pwroff_vol - current_avg * (battery->bat_res + DEF_PWRPATH_RES) / 0x3E8;
25643d0407baSopenharmony_ci
25653d0407baSopenharmony_ci    ocv_voltage = voltage_avg - (current_avg * battery->bat_res) / 0x3E8;
25663d0407baSopenharmony_ci    DBG("ZERO0: dead_voltage(shtd) = %d, ocv_voltage(now) = %d\n", dead_voltage, ocv_voltage);
25673d0407baSopenharmony_ci
25683d0407baSopenharmony_ci    /* calc estimate soc and cap */
25693d0407baSopenharmony_ci    dead_soc = rk817_bat_vol_to_soc(battery, dead_voltage);
25703d0407baSopenharmony_ci    dead_cap = rk817_bat_vol_to_cap(battery, dead_voltage);
25713d0407baSopenharmony_ci    DBG("ZERO0: dead_soc = %d, dead_cap = %d\n", dead_soc, dead_cap);
25723d0407baSopenharmony_ci
25733d0407baSopenharmony_ci    ocv_soc = rk817_bat_vol_to_soc(battery, ocv_voltage);
25743d0407baSopenharmony_ci    ocv_cap = rk817_bat_vol_to_cap(battery, ocv_voltage);
25753d0407baSopenharmony_ci    DBG("ZERO0: ocv_soc = %d, ocv_cap = %d\n", ocv_soc, ocv_cap);
25763d0407baSopenharmony_ci
25773d0407baSopenharmony_ci    /* xsoc: available rsoc */
25783d0407baSopenharmony_ci    xsoc = ocv_soc - dead_soc;
25793d0407baSopenharmony_ci
25803d0407baSopenharmony_ci    battery->zero_dead_voltage = dead_voltage;
25813d0407baSopenharmony_ci    battery->zero_dead_soc = dead_soc;
25823d0407baSopenharmony_ci    battery->zero_dead_cap = dead_cap;
25833d0407baSopenharmony_ci
25843d0407baSopenharmony_ci    battery->zero_batvol_to_ocv = ocv_voltage;
25853d0407baSopenharmony_ci    battery->zero_batocv_to_soc = ocv_soc;
25863d0407baSopenharmony_ci    battery->zero_batocv_to_cap = ocv_cap;
25873d0407baSopenharmony_ci
25883d0407baSopenharmony_ci    battery->zero_xsoc = xsoc;
25893d0407baSopenharmony_ci
25903d0407baSopenharmony_ci    DBG("Zero: xsoc = %d\n", xsoc);
25913d0407baSopenharmony_ci    /* min_gap_xsoc: reserve xsoc */
25923d0407baSopenharmony_ci    if (abs(current_avg) > ZERO_LOAD_LVL1) {
25933d0407baSopenharmony_ci        min_gap_xsoc = MIN_ZERO_GAP_XSOC3;
25943d0407baSopenharmony_ci    } else if (abs(current_avg) > ZERO_LOAD_LVL2) {
25953d0407baSopenharmony_ci        min_gap_xsoc = MIN_ZERO_GAP_XSOC2;
25963d0407baSopenharmony_ci    } else {
25973d0407baSopenharmony_ci        min_gap_xsoc = MIN_ZERO_GAP_XSOC1;
25983d0407baSopenharmony_ci    }
25993d0407baSopenharmony_ci
26003d0407baSopenharmony_ci    if ((xsoc <= 0x1E) && (battery->dsoc >= battery->pdata->zero_reserve_dsoc)) {
26013d0407baSopenharmony_ci        min_gap_xsoc = min_gap_xsoc + MIN_ZERO_GAP_CALIB;
26023d0407baSopenharmony_ci    }
26033d0407baSopenharmony_ci
26043d0407baSopenharmony_ci    battery->zero_remain_cap = battery->remain_cap;
26053d0407baSopenharmony_ci    battery->zero_timeout_cnt = 0;
26063d0407baSopenharmony_ci    if ((battery->dsoc / 0x3E8 <= 1) && (xsoc > 0)) {
26073d0407baSopenharmony_ci        battery->zero_linek = 0x190;
26083d0407baSopenharmony_ci        battery->zero_drop_sec = 0;
26093d0407baSopenharmony_ci    } else if (xsoc >= 0) {
26103d0407baSopenharmony_ci        battery->zero_drop_sec = 0;
26113d0407baSopenharmony_ci        battery->zero_linek = (battery->zero_dsoc + xsoc / 0x02) / DIV(xsoc);
26123d0407baSopenharmony_ci        /* battery energy mode to use up voltage */
26133d0407baSopenharmony_ci        if ((battery->pdata->energy_mode) && (xsoc - battery->dsoc / 0x3E8 >= MIN_ZERO_GAP_XSOC3) &&
26143d0407baSopenharmony_ci            (battery->dsoc / 0x3E8 <= 0x0A) && (battery->zero_linek < 0x12C)) {
26153d0407baSopenharmony_ci            battery->zero_linek = 0x12C;
26163d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step0...\n");
26173d0407baSopenharmony_ci            /* reserve enough power yet, slow down any way */
26183d0407baSopenharmony_ci        } else if ((xsoc - battery->dsoc / 0x3E8 >= min_gap_xsoc) ||
26193d0407baSopenharmony_ci                   ((xsoc - battery->dsoc / 0x3E8 >= MIN_ZERO_GAP_XSOC2) && (battery->dsoc / 0x3E8 <= 0x0A) &&
26203d0407baSopenharmony_ci                    (xsoc > 0x0F))) {
26213d0407baSopenharmony_ci            if (xsoc <= 0x14 && battery->dsoc / 0x3E8 >= battery->pdata->zero_reserve_dsoc) {
26223d0407baSopenharmony_ci                battery->zero_linek = 0x4B0;
26233d0407baSopenharmony_ci            } else if (xsoc - battery->dsoc / 0x3E8 >= 0x02 * min_gap_xsoc) {
26243d0407baSopenharmony_ci                battery->zero_linek = 0x190;
26253d0407baSopenharmony_ci            } else if (xsoc - battery->dsoc / 0x3E8 >= 0x03 + min_gap_xsoc) {
26263d0407baSopenharmony_ci                battery->zero_linek = 0x258;
26273d0407baSopenharmony_ci            } else {
26283d0407baSopenharmony_ci                battery->zero_linek = 0x320;
26293d0407baSopenharmony_ci            }
26303d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step1...\n");
26313d0407baSopenharmony_ci            /* control zero mode beginning enter */
26323d0407baSopenharmony_ci        } else if ((battery->zero_linek > 0x708) && (battery->dsoc / 0x3E8 > 0x46)) {
26333d0407baSopenharmony_ci            battery->zero_linek = 0x708;
26343d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step2...\n");
26353d0407baSopenharmony_ci            /* dsoc close to xsoc: it must reserve power */
26363d0407baSopenharmony_ci        } else if ((battery->zero_linek > 0x3E8) && (battery->zero_linek < 0x4B0)) {
26373d0407baSopenharmony_ci            battery->zero_linek = 0x4B0;
26383d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step3...\n");
26393d0407baSopenharmony_ci            /* dsoc[5~15], dsoc < xsoc */
26403d0407baSopenharmony_ci        } else if ((battery->dsoc / 0x3E8 <= 15 && battery->dsoc > 5) && (battery->zero_linek <= 0x4B0)) {
26413d0407baSopenharmony_ci            /* slow down */
26423d0407baSopenharmony_ci            if ((xsoc - battery->dsoc / 0x3E8) >= min_gap_xsoc) {
26433d0407baSopenharmony_ci                battery->zero_linek = 0x320;
26443d0407baSopenharmony_ci            } else {
26453d0407baSopenharmony_ci                battery->zero_linek = 0x4B0;
26463d0407baSopenharmony_ci            }
26473d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step4...\n");
26483d0407baSopenharmony_ci            /* dsoc[5, 100], dsoc < xsoc */
26493d0407baSopenharmony_ci        } else if ((battery->zero_linek < 0x3E8) && (battery->dsoc / 0x3E8 >= 5)) {
26503d0407baSopenharmony_ci            if ((xsoc - battery->dsoc / 0x3E8) < min_gap_xsoc) {
26513d0407baSopenharmony_ci                /* reserve power */
26523d0407baSopenharmony_ci                battery->zero_linek = 0x4B0;
26533d0407baSopenharmony_ci            } else {
26543d0407baSopenharmony_ci                if (abs(battery->current_avg) > 0x1F4) { /* heavy */
26553d0407baSopenharmony_ci                    battery->zero_linek = 0x384;
26563d0407baSopenharmony_ci                } else {
26573d0407baSopenharmony_ci                    battery->zero_linek = 0x3E8;
26583d0407baSopenharmony_ci                }
26593d0407baSopenharmony_ci            }
26603d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step5...\n");
26613d0407baSopenharmony_ci            /* dsoc[0~5], dsoc < xsoc */
26623d0407baSopenharmony_ci        } else if ((battery->zero_linek < 0x3E8) && (battery->dsoc / 0x3E8 <= 5)) {
26633d0407baSopenharmony_ci            if ((xsoc - battery->dsoc / 0x3E8) <= 0x03) {
26643d0407baSopenharmony_ci                battery->zero_linek = 0x4B0;
26653d0407baSopenharmony_ci            } else {
26663d0407baSopenharmony_ci                battery->zero_linek = 0x320;
26673d0407baSopenharmony_ci            }
26683d0407baSopenharmony_ci            DBG("ZERO-new: zero_linek adjust step6...\n");
26693d0407baSopenharmony_ci        }
26703d0407baSopenharmony_ci    } else {
26713d0407baSopenharmony_ci        /* xsoc < 0 */
26723d0407baSopenharmony_ci        battery->zero_linek = 0x3E8;
26733d0407baSopenharmony_ci        if (!battery->zero_drop_sec) {
26743d0407baSopenharmony_ci            battery->zero_drop_sec = get_boot_sec();
26753d0407baSopenharmony_ci        }
26763d0407baSopenharmony_ci        if (base2sec(battery->zero_drop_sec) >= WAIT_DSOC_DROP_SEC) {
26773d0407baSopenharmony_ci            DBG("ZERO0: t=%lu\n", base2sec(battery->zero_drop_sec));
26783d0407baSopenharmony_ci            battery->zero_drop_sec = 0;
26793d0407baSopenharmony_ci            battery->dsoc -= 0x3E8;
26803d0407baSopenharmony_ci            if (battery->dsoc < 0) {
26813d0407baSopenharmony_ci                battery->dsoc = 0;
26823d0407baSopenharmony_ci            }
26833d0407baSopenharmony_ci            battery->zero_dsoc = battery->dsoc;
26843d0407baSopenharmony_ci        }
26853d0407baSopenharmony_ci    }
26863d0407baSopenharmony_ci
26873d0407baSopenharmony_ci    if (voltage_avg < pwroff_vol - 0x46) {
26883d0407baSopenharmony_ci        if (!battery->shtd_drop_sec) {
26893d0407baSopenharmony_ci            battery->shtd_drop_sec = get_boot_sec();
26903d0407baSopenharmony_ci        }
26913d0407baSopenharmony_ci        if (base2sec(battery->shtd_drop_sec) > WAIT_SHTD_DROP_SEC) {
26923d0407baSopenharmony_ci            DBG("voltage extreme low...soc:%d->0\n", battery->dsoc);
26933d0407baSopenharmony_ci            battery->shtd_drop_sec = 0;
26943d0407baSopenharmony_ci            battery->dsoc = 0;
26953d0407baSopenharmony_ci        }
26963d0407baSopenharmony_ci    } else {
26973d0407baSopenharmony_ci        battery->shtd_drop_sec = 0;
26983d0407baSopenharmony_ci    }
26993d0407baSopenharmony_ci
27003d0407baSopenharmony_ci    DBG("Zero: zero_linek = %d\n", battery->zero_linek);
27013d0407baSopenharmony_ci}
27023d0407baSopenharmony_ci
27033d0407baSopenharmony_cistatic void rk817_bat_zero_algo_prepare(struct rk817_battery_device *battery)
27043d0407baSopenharmony_ci{
27053d0407baSopenharmony_ci    int tmp_dsoc;
27063d0407baSopenharmony_ci
27073d0407baSopenharmony_ci    tmp_dsoc = battery->zero_dsoc / 0x3E8;
27083d0407baSopenharmony_ci
27093d0407baSopenharmony_ci    if (tmp_dsoc != battery->smooth_soc / 0x3E8) {
27103d0407baSopenharmony_ci        battery->zero_dsoc = battery->smooth_soc;
27113d0407baSopenharmony_ci    }
27123d0407baSopenharmony_ci
27133d0407baSopenharmony_ci    DBG("zero_smooth: zero_dsoc = %d\n", battery->zero_dsoc);
27143d0407baSopenharmony_ci
27153d0407baSopenharmony_ci    rk817_bat_calc_zero_linek(battery);
27163d0407baSopenharmony_ci}
27173d0407baSopenharmony_ci
27183d0407baSopenharmony_cistatic void rk817_bat_calc_zero_algorithm(struct rk817_battery_device *battery)
27193d0407baSopenharmony_ci{
27203d0407baSopenharmony_ci    int tmp_soc;
27213d0407baSopenharmony_ci
27223d0407baSopenharmony_ci    tmp_soc = battery->zero_dsoc / 0x3E8;
27233d0407baSopenharmony_ci
27243d0407baSopenharmony_ci    if (tmp_soc == battery->dsoc / 0x3E8) {
27253d0407baSopenharmony_ci        return;
27263d0407baSopenharmony_ci    }
27273d0407baSopenharmony_ci
27283d0407baSopenharmony_ci    if (battery->zero_dsoc > battery->dsoc) {
27293d0407baSopenharmony_ci        return;
27303d0407baSopenharmony_ci    }
27313d0407baSopenharmony_ci
27323d0407baSopenharmony_ci    if (battery->zero_dsoc < battery->dsoc - 0x3E8) {
27333d0407baSopenharmony_ci        battery->dsoc -= 0x3E8;
27343d0407baSopenharmony_ci    } else {
27353d0407baSopenharmony_ci        battery->dsoc = battery->zero_dsoc;
27363d0407baSopenharmony_ci    }
27373d0407baSopenharmony_ci}
27383d0407baSopenharmony_ci
27393d0407baSopenharmony_cistatic void rk817_bat_zero_algorithm(struct rk817_battery_device *battery)
27403d0407baSopenharmony_ci{
27413d0407baSopenharmony_ci    int delta_cap = 0, delta_soc = 0;
27423d0407baSopenharmony_ci
27433d0407baSopenharmony_ci    battery->zero_timeout_cnt++;
27443d0407baSopenharmony_ci    delta_cap = battery->zero_remain_cap - battery->remain_cap;
27453d0407baSopenharmony_ci    delta_soc = battery->zero_linek * delta_cap / DIV(battery->fcc) / 0x0A;
27463d0407baSopenharmony_ci
27473d0407baSopenharmony_ci    DBG("zero algorithm start\n");
27483d0407baSopenharmony_ci    DBG("DEAD: dead_voltage: %d\n"
27493d0407baSopenharmony_ci        "dead_soc: %d\n"
27503d0407baSopenharmony_ci        "dead_cap: %d\n"
27513d0407baSopenharmony_ci        "powoff_vol: %d\n",
27523d0407baSopenharmony_ci        battery->zero_dead_voltage, battery->zero_dead_soc, battery->zero_dead_cap, battery->pdata->pwroff_vol);
27533d0407baSopenharmony_ci    DBG("DEAD: bat_voltage: %d\n"
27543d0407baSopenharmony_ci        "bat_current: %d\n"
27553d0407baSopenharmony_ci        "batvol_to_ocv: %d\n"
27563d0407baSopenharmony_ci        "batocv_to_soc: %d\n"
27573d0407baSopenharmony_ci        "batocv_to_cap: %d\n",
27583d0407baSopenharmony_ci        battery->zero_voltage_avg, battery->zero_current_avg, battery->zero_batvol_to_ocv, battery->zero_batocv_to_soc,
27593d0407baSopenharmony_ci        battery->zero_batocv_to_cap);
27603d0407baSopenharmony_ci    DBG("DEAD: Xsoc: %d, zero_reserve_dsoc: %d\n", battery->zero_xsoc, battery->pdata->zero_reserve_dsoc);
27613d0407baSopenharmony_ci    DBG("CAP: zero_remain_cap = %d, remain_cap = %d\n", battery->zero_remain_cap, battery->remain_cap);
27623d0407baSopenharmony_ci    DBG("Zero: zero_delta_cap = %d, zero_link = %d, delta_soc = %d\n", delta_cap, battery->zero_linek, delta_soc);
27633d0407baSopenharmony_ci    DBG("zero algorithm end\n");
27643d0407baSopenharmony_ci
27653d0407baSopenharmony_ci    if ((delta_soc >= MIN_ZERO_DSOC_ACCURACY) || (battery->zero_timeout_cnt > MIN_ZERO_OVERCNT) ||
27663d0407baSopenharmony_ci        (battery->zero_linek == 0)) {
27673d0407baSopenharmony_ci        DBG("ZERO1:--------- enter calc -----------\n");
27683d0407baSopenharmony_ci        battery->zero_timeout_cnt = 0;
27693d0407baSopenharmony_ci        battery->zero_dsoc -= delta_soc;
27703d0407baSopenharmony_ci        rk817_bat_calc_zero_algorithm(battery);
27713d0407baSopenharmony_ci        DBG("Zero: dsoc: %d\n", battery->dsoc);
27723d0407baSopenharmony_ci        rk817_bat_calc_zero_linek(battery);
27733d0407baSopenharmony_ci    }
27743d0407baSopenharmony_ci
27753d0407baSopenharmony_ci    if ((battery->rsoc / 0x3E8 < 1) && (battery->zero_batocv_to_cap > battery->fcc / 0x64)) {
27763d0407baSopenharmony_ci        DBG("ZERO2:---------check step1 -----------\n");
27773d0407baSopenharmony_ci        rk817_bat_init_coulomb_cap(battery, battery->zero_batocv_to_cap);
27783d0407baSopenharmony_ci        rk817_bat_calc_zero_linek(battery);
27793d0407baSopenharmony_ci    }
27803d0407baSopenharmony_ci}
27813d0407baSopenharmony_ci
27823d0407baSopenharmony_cistatic void rk817_bat_finish_algorithm(struct rk817_battery_device *battery)
27833d0407baSopenharmony_ci{
27843d0407baSopenharmony_ci    unsigned long finish_sec, soc_sec;
27853d0407baSopenharmony_ci    int plus_soc, finish_current, rest = 0;
27863d0407baSopenharmony_ci
27873d0407baSopenharmony_ci    /* rsoc */
27883d0407baSopenharmony_ci    if ((battery->remain_cap != battery->fcc) && (get_charge_status(battery) == CHARGE_FINISH)) {
27893d0407baSopenharmony_ci        battery->age_adjust_cap += (battery->fcc * 0x3E8 - battery->remain_cap);
27903d0407baSopenharmony_ci        rk817_bat_init_coulomb_cap(battery, battery->fcc);
27913d0407baSopenharmony_ci        rk817_bat_get_capacity_mah(battery);
27923d0407baSopenharmony_ci    }
27933d0407baSopenharmony_ci
27943d0407baSopenharmony_ci    /* dsoc */
27953d0407baSopenharmony_ci    if (battery->dsoc < 0x64 * 0x3E8) {
27963d0407baSopenharmony_ci        if (!battery->finish_base) {
27973d0407baSopenharmony_ci            battery->finish_base = get_boot_sec();
27983d0407baSopenharmony_ci        }
27993d0407baSopenharmony_ci
28003d0407baSopenharmony_ci        finish_current = (battery->rsoc - battery->dsoc) > FINISH_MAX_SOC_DELAY ? FINISH_CHRG_CUR2 : FINISH_CHRG_CUR1;
28013d0407baSopenharmony_ci        finish_sec = base2sec(battery->finish_base);
28023d0407baSopenharmony_ci
28033d0407baSopenharmony_ci        soc_sec = battery->fcc * 0xE10 / 0x64 / DIV(finish_current);
28043d0407baSopenharmony_ci        plus_soc = finish_sec / DIV(soc_sec);
28053d0407baSopenharmony_ci        if (finish_sec > soc_sec) {
28063d0407baSopenharmony_ci            rest = finish_sec % soc_sec;
28073d0407baSopenharmony_ci            battery->dsoc += plus_soc * 0x3E8;
28083d0407baSopenharmony_ci            battery->finish_base = get_boot_sec();
28093d0407baSopenharmony_ci            if (battery->finish_base > rest) {
28103d0407baSopenharmony_ci                battery->finish_base = get_boot_sec() - rest;
28113d0407baSopenharmony_ci            }
28123d0407baSopenharmony_ci        }
28133d0407baSopenharmony_ci        DBG("CHARGE_FINISH:dsoc<100,dsoc=%d\n"
28143d0407baSopenharmony_ci            "soc_time=%lu, sec_finish=%lu, plus_soc=%d, rest=%d\n",
28153d0407baSopenharmony_ci            battery->dsoc, soc_sec, finish_sec, plus_soc, rest);
28163d0407baSopenharmony_ci        DBG("battery->age_adjust_cap = %d\n", battery->age_adjust_cap);
28173d0407baSopenharmony_ci    }
28183d0407baSopenharmony_ci}
28193d0407baSopenharmony_ci
28203d0407baSopenharmony_cistatic void rk817_bat_display_smooth(struct rk817_battery_device *battery)
28213d0407baSopenharmony_ci{
28223d0407baSopenharmony_ci    /* discharge: reinit "zero & smooth" algorithm to avoid handling dsoc */
28233d0407baSopenharmony_ci    if (battery->s2r && !battery->sleep_chrg_online) {
28243d0407baSopenharmony_ci        DBG("s2r: discharge, reset algorithm...\n");
28253d0407baSopenharmony_ci        battery->s2r = false;
28263d0407baSopenharmony_ci        rk817_bat_zero_algo_prepare(battery);
28273d0407baSopenharmony_ci        rk817_bat_smooth_algo_prepare(battery);
28283d0407baSopenharmony_ci        return;
28293d0407baSopenharmony_ci    }
28303d0407baSopenharmony_ci
28313d0407baSopenharmony_ci    if (battery->work_mode == MODE_FINISH) {
28323d0407baSopenharmony_ci        DBG("step1: charge finish...\n");
28333d0407baSopenharmony_ci        rk817_bat_finish_algorithm(battery);
28343d0407baSopenharmony_ci
28353d0407baSopenharmony_ci        if ((get_charge_status(battery) != CHARGE_FINISH) && !rk817_bat_fake_finish_mode(battery)) {
28363d0407baSopenharmony_ci            if ((battery->current_avg < 0) && (battery->voltage_avg < battery->pdata->zero_algorithm_vol)) {
28373d0407baSopenharmony_ci                DBG("step1: change to zero mode...\n");
28383d0407baSopenharmony_ci                rk817_bat_zero_algo_prepare(battery);
28393d0407baSopenharmony_ci                battery->work_mode = MODE_ZERO;
28403d0407baSopenharmony_ci            } else {
28413d0407baSopenharmony_ci                DBG("step1: change to smooth mode...\n");
28423d0407baSopenharmony_ci                rk817_bat_smooth_algo_prepare(battery);
28433d0407baSopenharmony_ci                battery->work_mode = MODE_SMOOTH;
28443d0407baSopenharmony_ci            }
28453d0407baSopenharmony_ci        }
28463d0407baSopenharmony_ci    } else if (battery->work_mode == MODE_ZERO) {
28473d0407baSopenharmony_ci        DBG("step2: zero algorithm...\n");
28483d0407baSopenharmony_ci        rk817_bat_zero_algorithm(battery);
28493d0407baSopenharmony_ci        if ((battery->voltage_avg >= battery->pdata->zero_algorithm_vol + 0x32) || (battery->current_avg >= 0)) {
28503d0407baSopenharmony_ci            DBG("step2: change to smooth mode...\n");
28513d0407baSopenharmony_ci            rk817_bat_smooth_algo_prepare(battery);
28523d0407baSopenharmony_ci            battery->work_mode = MODE_SMOOTH;
28533d0407baSopenharmony_ci        } else if ((get_charge_status(battery) == CHARGE_FINISH) || rk817_bat_fake_finish_mode(battery)) {
28543d0407baSopenharmony_ci            DBG("step2: change to finish mode...\n");
28553d0407baSopenharmony_ci            rk817_bat_finish_algo_prepare(battery);
28563d0407baSopenharmony_ci            battery->work_mode = MODE_FINISH;
28573d0407baSopenharmony_ci        }
28583d0407baSopenharmony_ci    } else {
28593d0407baSopenharmony_ci        DBG("step3: smooth algorithm...\n");
28603d0407baSopenharmony_ci        rk817_bat_smooth_algorithm(battery);
28613d0407baSopenharmony_ci        if ((battery->current_avg < 0) && (battery->voltage_avg < battery->pdata->zero_algorithm_vol)) {
28623d0407baSopenharmony_ci            DBG("step3: change to zero mode...\n");
28633d0407baSopenharmony_ci            rk817_bat_zero_algo_prepare(battery);
28643d0407baSopenharmony_ci            battery->work_mode = MODE_ZERO;
28653d0407baSopenharmony_ci        } else if ((get_charge_status(battery) == CHARGE_FINISH) || rk817_bat_fake_finish_mode(battery)) {
28663d0407baSopenharmony_ci            DBG("step3: change to finish mode...\n");
28673d0407baSopenharmony_ci            rk817_bat_finish_algo_prepare(battery);
28683d0407baSopenharmony_ci            battery->work_mode = MODE_FINISH;
28693d0407baSopenharmony_ci        }
28703d0407baSopenharmony_ci    }
28713d0407baSopenharmony_ci}
28723d0407baSopenharmony_ci
28733d0407baSopenharmony_cistatic void rk817_bat_output_info(struct rk817_battery_device *battery)
28743d0407baSopenharmony_ci{
28753d0407baSopenharmony_ci    DBG("info start:\n");
28763d0407baSopenharmony_ci    DBG("info: voltage_k = %d\n", battery->voltage_k);
28773d0407baSopenharmony_ci    DBG("info: voltage_b = %d\n", battery->voltage_b);
28783d0407baSopenharmony_ci    DBG("info: voltage = %d\n", battery->voltage_avg);
28793d0407baSopenharmony_ci    DBG("info: voltage_sys = %d\n", battery->voltage_sys);
28803d0407baSopenharmony_ci    DBG("info: current = %d\n", battery->current_avg);
28813d0407baSopenharmony_ci
28823d0407baSopenharmony_ci    DBG("info: FCC = %d\n", battery->fcc);
28833d0407baSopenharmony_ci    DBG("info: remain_cap = %d\n", battery->remain_cap);
28843d0407baSopenharmony_ci    DBG("info: sm_remain_cap = %d\n", battery->sm_remain_cap);
28853d0407baSopenharmony_ci    DBG("info: sm_link = %d\n", battery->sm_linek);
28863d0407baSopenharmony_ci    DBG("info: smooth_soc = %d\n", battery->smooth_soc);
28873d0407baSopenharmony_ci
28883d0407baSopenharmony_ci    DBG("info: zero_remain_cap = %d\n", battery->zero_remain_cap);
28893d0407baSopenharmony_ci    DBG("info: zero_link = %d\n", battery->zero_linek);
28903d0407baSopenharmony_ci    DBG("info: zero_dsoc = %d\n", battery->zero_dsoc);
28913d0407baSopenharmony_ci
28923d0407baSopenharmony_ci    DBG("info: remain_cap = %d\n", battery->remain_cap);
28933d0407baSopenharmony_ci    DBG("info: dsoc = %d, dsoc/0x3E8 = %d\n", battery->dsoc, battery->dsoc / 0x3E8);
28943d0407baSopenharmony_ci    DBG("info: rsoc = %d\n", battery->rsoc);
28953d0407baSopenharmony_ci    DBG("info END.\n");
28963d0407baSopenharmony_ci}
28973d0407baSopenharmony_ci
28983d0407baSopenharmony_cistatic void rk817_battery_work(struct work_struct *work)
28993d0407baSopenharmony_ci{
29003d0407baSopenharmony_ci    struct rk817_battery_device *battery = container_of(work, struct rk817_battery_device, bat_delay_work.work);
29013d0407baSopenharmony_ci
29023d0407baSopenharmony_ci    rk817_bat_update_info(battery);
29033d0407baSopenharmony_ci    rk817_bat_lowpwr_check(battery);
29043d0407baSopenharmony_ci    rk817_bat_display_smooth(battery);
29053d0407baSopenharmony_ci    rk817_bat_power_supply_changed(battery);
29063d0407baSopenharmony_ci    rk817_bat_save_data(battery);
29073d0407baSopenharmony_ci    rk817_bat_output_info(battery);
29083d0407baSopenharmony_ci
29093d0407baSopenharmony_ci    if (rk817_bat_field_read(battery, CUR_CALIB_UPD)) {
29103d0407baSopenharmony_ci        rk817_bat_current_calibration(battery);
29113d0407baSopenharmony_ci        rk817_bat_init_voltage_kb(battery);
29123d0407baSopenharmony_ci        rk817_bat_field_write(battery, CUR_CALIB_UPD, 0x01);
29133d0407baSopenharmony_ci    }
29143d0407baSopenharmony_ci
29153d0407baSopenharmony_ci    queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work, msecs_to_jiffies(battery->monitor_ms));
29163d0407baSopenharmony_ci}
29173d0407baSopenharmony_ci
29183d0407baSopenharmony_cistatic irqreturn_t rk809_plug_in_isr(int irq, void *cg)
29193d0407baSopenharmony_ci{
29203d0407baSopenharmony_ci    struct rk817_battery_device *battery;
29213d0407baSopenharmony_ci
29223d0407baSopenharmony_ci    battery = (struct rk817_battery_device *)cg;
29233d0407baSopenharmony_ci    battery->plugin_trigger = 1;
29243d0407baSopenharmony_ci    battery->plugout_trigger = 0;
29253d0407baSopenharmony_ci    power_supply_changed(battery->bat);
29263d0407baSopenharmony_ci    if (battery->is_register_chg_psy) {
29273d0407baSopenharmony_ci        power_supply_changed(battery->chg_psy);
29283d0407baSopenharmony_ci    }
29293d0407baSopenharmony_ci
29303d0407baSopenharmony_ci    return IRQ_HANDLED;
29313d0407baSopenharmony_ci}
29323d0407baSopenharmony_ci
29333d0407baSopenharmony_cistatic irqreturn_t rk809_plug_out_isr(int irq, void *cg)
29343d0407baSopenharmony_ci{
29353d0407baSopenharmony_ci    struct rk817_battery_device *battery;
29363d0407baSopenharmony_ci
29373d0407baSopenharmony_ci    battery = (struct rk817_battery_device *)cg;
29383d0407baSopenharmony_ci    battery->plugin_trigger = 0;
29393d0407baSopenharmony_ci    battery->plugout_trigger = 1;
29403d0407baSopenharmony_ci    power_supply_changed(battery->bat);
29413d0407baSopenharmony_ci    if (battery->is_register_chg_psy) {
29423d0407baSopenharmony_ci        power_supply_changed(battery->chg_psy);
29433d0407baSopenharmony_ci    }
29443d0407baSopenharmony_ci
29453d0407baSopenharmony_ci    return IRQ_HANDLED;
29463d0407baSopenharmony_ci}
29473d0407baSopenharmony_ci
29483d0407baSopenharmony_cistatic int rk809_charge_init_irqs(struct rk817_battery_device *battery)
29493d0407baSopenharmony_ci{
29503d0407baSopenharmony_ci    struct rk808 *rk817 = battery->rk817;
29513d0407baSopenharmony_ci    struct platform_device *pdev = battery->pdev;
29523d0407baSopenharmony_ci    int ret, plug_in_irq, plug_out_irq;
29533d0407baSopenharmony_ci
29543d0407baSopenharmony_ci    battery->plugin_trigger = 0;
29553d0407baSopenharmony_ci    battery->plugout_trigger = 0;
29563d0407baSopenharmony_ci
29573d0407baSopenharmony_ci    plug_in_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_IN);
29583d0407baSopenharmony_ci    if (plug_in_irq < 0) {
29593d0407baSopenharmony_ci        dev_err(battery->dev, "plug_in_irq request failed!\n");
29603d0407baSopenharmony_ci        return plug_in_irq;
29613d0407baSopenharmony_ci    }
29623d0407baSopenharmony_ci
29633d0407baSopenharmony_ci    plug_out_irq = regmap_irq_get_virq(rk817->irq_data, RK817_IRQ_PLUG_OUT);
29643d0407baSopenharmony_ci    if (plug_out_irq < 0) {
29653d0407baSopenharmony_ci        dev_err(battery->dev, "plug_out_irq request failed!\n");
29663d0407baSopenharmony_ci        return plug_out_irq;
29673d0407baSopenharmony_ci    }
29683d0407baSopenharmony_ci
29693d0407baSopenharmony_ci    ret = devm_request_threaded_irq(battery->dev, plug_in_irq, NULL, rk809_plug_in_isr,
29703d0407baSopenharmony_ci                                    IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rk817_plug_in", battery);
29713d0407baSopenharmony_ci    if (ret) {
29723d0407baSopenharmony_ci        dev_err(&pdev->dev, "plug_in_irq request failed!\n");
29733d0407baSopenharmony_ci        return ret;
29743d0407baSopenharmony_ci    }
29753d0407baSopenharmony_ci
29763d0407baSopenharmony_ci    ret = devm_request_threaded_irq(battery->dev, plug_out_irq, NULL, rk809_plug_out_isr,
29773d0407baSopenharmony_ci                                    IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rk817_plug_out", battery);
29783d0407baSopenharmony_ci    if (ret) {
29793d0407baSopenharmony_ci        dev_err(&pdev->dev, "plug_out_irq request failed!\n");
29803d0407baSopenharmony_ci        return ret;
29813d0407baSopenharmony_ci    }
29823d0407baSopenharmony_ci
29833d0407baSopenharmony_ci    if (rk817_bat_field_read(battery, PLUG_IN_STS)) {
29843d0407baSopenharmony_ci        battery->plugin_trigger = 1;
29853d0407baSopenharmony_ci        battery->plugout_trigger = 0;
29863d0407baSopenharmony_ci    }
29873d0407baSopenharmony_ci
29883d0407baSopenharmony_ci    return 0;
29893d0407baSopenharmony_ci}
29903d0407baSopenharmony_ci
29913d0407baSopenharmony_ci#ifdef CONFIG_OF
29923d0407baSopenharmony_cistatic const struct of_device_id rk817_bat_of_match[] = {
29933d0407baSopenharmony_ci    {
29943d0407baSopenharmony_ci        .compatible = "rk817,battery",
29953d0407baSopenharmony_ci    },
29963d0407baSopenharmony_ci    {},
29973d0407baSopenharmony_ci};
29983d0407baSopenharmony_ciMODULE_DEVICE_TABLE(of, rk817_bat_of_match);
29993d0407baSopenharmony_ci#else
30003d0407baSopenharmony_cistatic const struct of_device_id rk817_bat_of_match[] = {
30013d0407baSopenharmony_ci    {},
30023d0407baSopenharmony_ci};
30033d0407baSopenharmony_ci#endif
30043d0407baSopenharmony_ci
30053d0407baSopenharmony_cistatic int rk817_battery_probe(struct platform_device *pdev)
30063d0407baSopenharmony_ci{
30073d0407baSopenharmony_ci    const struct of_device_id *of_id = of_match_device(rk817_bat_of_match, &pdev->dev);
30083d0407baSopenharmony_ci    struct rk817_battery_device *battery;
30093d0407baSopenharmony_ci    struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent);
30103d0407baSopenharmony_ci    struct i2c_client *client = rk817->i2c;
30113d0407baSopenharmony_ci    int i, ret;
30123d0407baSopenharmony_ci
30133d0407baSopenharmony_ci    if (!of_id) {
30143d0407baSopenharmony_ci        dev_err(&pdev->dev, "Failed to find matching dt id\n");
30153d0407baSopenharmony_ci        return -ENODEV;
30163d0407baSopenharmony_ci    }
30173d0407baSopenharmony_ci
30183d0407baSopenharmony_ci    battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL);
30193d0407baSopenharmony_ci    if (!battery) {
30203d0407baSopenharmony_ci        return -EINVAL;
30213d0407baSopenharmony_ci    }
30223d0407baSopenharmony_ci
30233d0407baSopenharmony_ci    battery->rk817 = rk817;
30243d0407baSopenharmony_ci    battery->client = client;
30253d0407baSopenharmony_ci    battery->dev = &pdev->dev;
30263d0407baSopenharmony_ci    platform_set_drvdata(pdev, battery);
30273d0407baSopenharmony_ci    battery->chip_id = rk817->variant;
30283d0407baSopenharmony_ci
30293d0407baSopenharmony_ci    battery->regmap = rk817->regmap;
30303d0407baSopenharmony_ci    if (IS_ERR(battery->regmap)) {
30313d0407baSopenharmony_ci        dev_err(battery->dev, "Failed to initialize regmap\n");
30323d0407baSopenharmony_ci        return -EINVAL;
30333d0407baSopenharmony_ci    }
30343d0407baSopenharmony_ci
30353d0407baSopenharmony_ci    for (i = 0; i < ARRAY_SIZE(rk817_battery_reg_fields); i++) {
30363d0407baSopenharmony_ci        const struct reg_field *reg_fields = rk817_battery_reg_fields;
30373d0407baSopenharmony_ci
30383d0407baSopenharmony_ci        battery->rmap_fields[i] = devm_regmap_field_alloc(battery->dev, battery->regmap, reg_fields[i]);
30393d0407baSopenharmony_ci        if (IS_ERR(battery->rmap_fields[i])) {
30403d0407baSopenharmony_ci            dev_err(battery->dev, "cannot allocate regmap field\n");
30413d0407baSopenharmony_ci            return PTR_ERR(battery->rmap_fields[i]);
30423d0407baSopenharmony_ci        }
30433d0407baSopenharmony_ci    }
30443d0407baSopenharmony_ci
30453d0407baSopenharmony_ci    ret = rk817_bat_parse_dt(battery);
30463d0407baSopenharmony_ci    if (ret < 0) {
30473d0407baSopenharmony_ci        dev_err(battery->dev, "battery parse dt failed!\n");
30483d0407baSopenharmony_ci        return ret;
30493d0407baSopenharmony_ci    }
30503d0407baSopenharmony_ci
30513d0407baSopenharmony_ci    rk817_bat_init_info(battery);
30523d0407baSopenharmony_ci    rk817_bat_init_fg(battery);
30533d0407baSopenharmony_ci
30543d0407baSopenharmony_ci    rk817_battery_debug_info(battery);
30553d0407baSopenharmony_ci    rk817_bat_update_info(battery);
30563d0407baSopenharmony_ci
30573d0407baSopenharmony_ci    rk817_bat_output_info(battery);
30583d0407baSopenharmony_ci    battery->bat_monitor_wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk817-bat-monitor-wq");
30593d0407baSopenharmony_ci    INIT_DELAYED_WORK(&battery->bat_delay_work, rk817_battery_work);
30603d0407baSopenharmony_ci    queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work, msecs_to_jiffies(TIMER_MS_COUNTS * 0X05));
30613d0407baSopenharmony_ci    INIT_WORK(&battery->resume_work, rk817_bat_resume_work);
30623d0407baSopenharmony_ci
30633d0407baSopenharmony_ci    ret = rk817_bat_init_power_supply(battery);
30643d0407baSopenharmony_ci    if (ret) {
30653d0407baSopenharmony_ci        dev_err(battery->dev, "rk817 power supply register failed!\n");
30663d0407baSopenharmony_ci        return ret;
30673d0407baSopenharmony_ci    }
30683d0407baSopenharmony_ci    if (battery->is_register_chg_psy) {
30693d0407baSopenharmony_ci        ret = rk809_chg_init_power_supply(battery);
30703d0407baSopenharmony_ci        if (ret) {
30713d0407baSopenharmony_ci            dev_err(battery->dev, "rk809 chg psy init failed!\n");
30723d0407baSopenharmony_ci            return ret;
30733d0407baSopenharmony_ci        }
30743d0407baSopenharmony_ci    }
30753d0407baSopenharmony_ci
30763d0407baSopenharmony_ci    if (battery->chip_id == RK809_ID) {
30773d0407baSopenharmony_ci        rk809_charge_init_irqs(battery);
30783d0407baSopenharmony_ci    }
30793d0407baSopenharmony_ci
30803d0407baSopenharmony_ci    wake_lock_init(&battery->wake_lock, WAKE_LOCK_SUSPEND, "rk817_bat_lock");
30813d0407baSopenharmony_ci
30823d0407baSopenharmony_ci    DBG("name: 0x%x", rk817_bat_field_read(battery, CHIP_NAME_H));
30833d0407baSopenharmony_ci    DBG("%x\n", rk817_bat_field_read(battery, CHIP_NAME_L));
30843d0407baSopenharmony_ci    DBG("driver version %s\n", DRIVER_VERSION);
30853d0407baSopenharmony_ci
30863d0407baSopenharmony_ci    return 0;
30873d0407baSopenharmony_ci}
30883d0407baSopenharmony_ci
30893d0407baSopenharmony_cistatic void rk817_battery_shutdown(struct platform_device *dev)
30903d0407baSopenharmony_ci{
30913d0407baSopenharmony_ci}
30923d0407baSopenharmony_ci
30933d0407baSopenharmony_cistatic time64_t rk817_get_rtc_sec(void)
30943d0407baSopenharmony_ci{
30953d0407baSopenharmony_ci    int err;
30963d0407baSopenharmony_ci    struct rtc_time tm;
30973d0407baSopenharmony_ci    struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
30983d0407baSopenharmony_ci
30993d0407baSopenharmony_ci    err = rtc_read_time(rtc, &tm);
31003d0407baSopenharmony_ci    if (err) {
31013d0407baSopenharmony_ci        dev_err(rtc->dev.parent, "read hardware clk failed\n");
31023d0407baSopenharmony_ci        return 0;
31033d0407baSopenharmony_ci    }
31043d0407baSopenharmony_ci
31053d0407baSopenharmony_ci    err = rtc_valid_tm(&tm);
31063d0407baSopenharmony_ci    if (err) {
31073d0407baSopenharmony_ci        dev_err(rtc->dev.parent, "invalid date time\n");
31083d0407baSopenharmony_ci        return 0;
31093d0407baSopenharmony_ci    }
31103d0407baSopenharmony_ci
31113d0407baSopenharmony_ci    return rtc_tm_to_time64(&tm);
31123d0407baSopenharmony_ci}
31133d0407baSopenharmony_ci
31143d0407baSopenharmony_ci#ifdef CONFIG_PM_SLEEP
31153d0407baSopenharmony_cistatic int rk817_bat_pm_suspend(struct device *dev)
31163d0407baSopenharmony_ci{
31173d0407baSopenharmony_ci    struct platform_device *pdev = to_platform_device(dev);
31183d0407baSopenharmony_ci    struct rk817_battery_device *battery = dev_get_drvdata(&pdev->dev);
31193d0407baSopenharmony_ci
31203d0407baSopenharmony_ci    cancel_delayed_work_sync(&battery->bat_delay_work);
31213d0407baSopenharmony_ci
31223d0407baSopenharmony_ci    battery->s2r = false;
31233d0407baSopenharmony_ci    battery->sleep_chrg_status = get_charge_status(battery);
31243d0407baSopenharmony_ci    battery->current_avg = rk817_bat_get_avg_current(battery);
31253d0407baSopenharmony_ci    if (battery->current_avg > 0 || (battery->sleep_chrg_status == CC_OR_CV_CHRG) ||
31263d0407baSopenharmony_ci        (battery->sleep_chrg_status == CHARGE_FINISH)) {
31273d0407baSopenharmony_ci        battery->sleep_chrg_online = 1;
31283d0407baSopenharmony_ci    } else {
31293d0407baSopenharmony_ci        battery->sleep_chrg_online = 0;
31303d0407baSopenharmony_ci    }
31313d0407baSopenharmony_ci
31323d0407baSopenharmony_ci    battery->remain_cap = rk817_bat_get_capacity_uah(battery);
31333d0407baSopenharmony_ci    battery->rsoc = rk817_bat_get_rsoc(battery);
31343d0407baSopenharmony_ci
31353d0407baSopenharmony_ci    battery->rtc_base = rk817_get_rtc_sec();
31363d0407baSopenharmony_ci    rk817_bat_save_data(battery);
31373d0407baSopenharmony_ci
31383d0407baSopenharmony_ci    if (battery->sleep_chrg_status != CHARGE_FINISH) {
31393d0407baSopenharmony_ci        battery->finish_base = get_boot_sec();
31403d0407baSopenharmony_ci    }
31413d0407baSopenharmony_ci
31423d0407baSopenharmony_ci    if ((battery->work_mode == MODE_ZERO) && (battery->current_avg >= 0)) {
31433d0407baSopenharmony_ci        DBG("suspend: MODE_ZERO exit...\n");
31443d0407baSopenharmony_ci        /* it need't do prepare for mode finish and smooth, it will
31453d0407baSopenharmony_ci         * be done in display_smooth
31463d0407baSopenharmony_ci         */
31473d0407baSopenharmony_ci        if (battery->sleep_chrg_status == CHARGE_FINISH) {
31483d0407baSopenharmony_ci            battery->work_mode = MODE_FINISH;
31493d0407baSopenharmony_ci            battery->finish_base = get_boot_sec();
31503d0407baSopenharmony_ci        } else {
31513d0407baSopenharmony_ci            battery->work_mode = MODE_SMOOTH;
31523d0407baSopenharmony_ci            rk817_bat_smooth_algo_prepare(battery);
31533d0407baSopenharmony_ci        }
31543d0407baSopenharmony_ci    }
31553d0407baSopenharmony_ci
31563d0407baSopenharmony_ci    DBG("suspend get_boot_sec: %lld\n", get_boot_sec());
31573d0407baSopenharmony_ci
31583d0407baSopenharmony_ci    DBG("suspend: dl=%d rl=%d c=%d v=%d cap=%d at=%ld ch=%d\n", battery->dsoc, battery->rsoc, battery->current_avg,
31593d0407baSopenharmony_ci        rk817_bat_get_battery_voltage(battery), rk817_bat_get_capacity_uah(battery), battery->sleep_dischrg_sec,
31603d0407baSopenharmony_ci        battery->sleep_chrg_online);
31613d0407baSopenharmony_ci    DBG("battery->sleep_chrg_status=%d\n", battery->sleep_chrg_status);
31623d0407baSopenharmony_ci
31633d0407baSopenharmony_ci    return 0;
31643d0407baSopenharmony_ci}
31653d0407baSopenharmony_ci
31663d0407baSopenharmony_cistatic int rk817_bat_rtc_sleep_sec(struct rk817_battery_device *battery)
31673d0407baSopenharmony_ci{
31683d0407baSopenharmony_ci    int interval_sec;
31693d0407baSopenharmony_ci
31703d0407baSopenharmony_ci    interval_sec = rk817_get_rtc_sec() - battery->rtc_base;
31713d0407baSopenharmony_ci
31723d0407baSopenharmony_ci    return (interval_sec > 0) ? interval_sec : 0;
31733d0407baSopenharmony_ci}
31743d0407baSopenharmony_ci
31753d0407baSopenharmony_cistatic void rk817_bat_relife_age_flag(struct rk817_battery_device *battery)
31763d0407baSopenharmony_ci{
31773d0407baSopenharmony_ci    u8 ocv_soc, ocv_cap, soc_level;
31783d0407baSopenharmony_ci
31793d0407baSopenharmony_ci    if (battery->voltage_relax <= 0) {
31803d0407baSopenharmony_ci        return;
31813d0407baSopenharmony_ci    }
31823d0407baSopenharmony_ci
31833d0407baSopenharmony_ci    ocv_soc = rk817_bat_vol_to_soc(battery, battery->voltage_relax);
31843d0407baSopenharmony_ci    ocv_cap = rk817_bat_vol_to_cap(battery, battery->voltage_relax);
31853d0407baSopenharmony_ci    DBG("<%s>. ocv_soc=%d, min=%lu, vol=%d\n", __func__, ocv_soc, battery->sleep_dischrg_sec / 60,
31863d0407baSopenharmony_ci        battery->voltage_relax);
31873d0407baSopenharmony_ci
31883d0407baSopenharmony_ci    /* sleep enough time and ocv_soc enough low */
31893d0407baSopenharmony_ci    if (!battery->age_allow_update && ocv_soc <= 0x0A) {
31903d0407baSopenharmony_ci        battery->age_voltage = battery->voltage_relax;
31913d0407baSopenharmony_ci        battery->age_ocv_cap = ocv_cap;
31923d0407baSopenharmony_ci        battery->age_ocv_soc = ocv_soc;
31933d0407baSopenharmony_ci        battery->age_adjust_cap = 0;
31943d0407baSopenharmony_ci
31953d0407baSopenharmony_ci        if (ocv_soc <= 1) {
31963d0407baSopenharmony_ci            battery->age_level = 0x64;
31973d0407baSopenharmony_ci        } else if (ocv_soc < 0x05) {
31983d0407baSopenharmony_ci            battery->age_level = 0x5A;
31993d0407baSopenharmony_ci        } else {
32003d0407baSopenharmony_ci            battery->age_level = 0x50;
32013d0407baSopenharmony_ci        }
32023d0407baSopenharmony_ci        soc_level = 0;
32033d0407baSopenharmony_ci        if (soc_level > battery->age_level) {
32043d0407baSopenharmony_ci            battery->age_allow_update = false;
32053d0407baSopenharmony_ci        } else {
32063d0407baSopenharmony_ci            battery->age_allow_update = true;
32073d0407baSopenharmony_ci            battery->age_keep_sec = get_boot_sec();
32083d0407baSopenharmony_ci        }
32093d0407baSopenharmony_ci
32103d0407baSopenharmony_ci        BAT_INFO("resume: age_vol:%d, age_ocv_cap:%d, age_ocv_soc:%d, "
32113d0407baSopenharmony_ci                 "soc_level:%d, age_allow_update:%d, "
32123d0407baSopenharmony_ci                 "age_level:%d\n",
32133d0407baSopenharmony_ci                 battery->age_voltage, battery->age_ocv_cap, ocv_soc, soc_level, battery->age_allow_update,
32143d0407baSopenharmony_ci                 battery->age_level);
32153d0407baSopenharmony_ci    }
32163d0407baSopenharmony_ci}
32173d0407baSopenharmony_ci
32183d0407baSopenharmony_cistatic void rk817_bat_init_capacity(struct rk817_battery_device *battery, u32 cap)
32193d0407baSopenharmony_ci{
32203d0407baSopenharmony_ci    int delta_cap;
32213d0407baSopenharmony_ci
32223d0407baSopenharmony_ci    delta_cap = cap - battery->remain_cap;
32233d0407baSopenharmony_ci    if (!delta_cap) {
32243d0407baSopenharmony_ci        return;
32253d0407baSopenharmony_ci    }
32263d0407baSopenharmony_ci
32273d0407baSopenharmony_ci    battery->age_adjust_cap += delta_cap;
32283d0407baSopenharmony_ci    rk817_bat_init_coulomb_cap(battery, cap);
32293d0407baSopenharmony_ci    rk817_bat_smooth_algo_prepare(battery);
32303d0407baSopenharmony_ci    rk817_bat_zero_algo_prepare(battery);
32313d0407baSopenharmony_ci}
32323d0407baSopenharmony_ci
32333d0407baSopenharmony_cistatic void rk817_bat_relax_vol_calib(struct rk817_battery_device *battery)
32343d0407baSopenharmony_ci{
32353d0407baSopenharmony_ci    int soc, cap, vol;
32363d0407baSopenharmony_ci
32373d0407baSopenharmony_ci    vol = battery->voltage_relax;
32383d0407baSopenharmony_ci    soc = rk817_bat_vol_to_soc(battery, vol);
32393d0407baSopenharmony_ci    cap = rk817_bat_vol_to_cap(battery, vol);
32403d0407baSopenharmony_ci    rk817_bat_init_capacity(battery, cap);
32413d0407baSopenharmony_ci    BAT_INFO("sleep ocv calib: rsoc=%d, cap=%d\n", soc, cap);
32423d0407baSopenharmony_ci}
32433d0407baSopenharmony_ci
32443d0407baSopenharmony_cistatic int rk817_bat_sleep_dischrg(struct rk817_battery_device *battery)
32453d0407baSopenharmony_ci{
32463d0407baSopenharmony_ci    bool ocv_soc_updated = false;
32473d0407baSopenharmony_ci    int tgt_dsoc, gap_soc, sleep_soc = 0;
32483d0407baSopenharmony_ci    int pwroff_vol = battery->pdata->pwroff_vol;
32493d0407baSopenharmony_ci    unsigned long sleep_sec = battery->sleep_dischrg_sec;
32503d0407baSopenharmony_ci    int sleep_cur;
32513d0407baSopenharmony_ci
32523d0407baSopenharmony_ci    DBG("<%s>. enter: dsoc=%d, rsoc=%d, rv=%d, v=%d, sleep_min=%lu\n", __func__, battery->dsoc, battery->rsoc,
32533d0407baSopenharmony_ci        battery->voltage_relax, battery->voltage_avg, sleep_sec / 60);
32543d0407baSopenharmony_ci
32553d0407baSopenharmony_ci    if (battery->voltage_relax >= battery->voltage_avg) {
32563d0407baSopenharmony_ci        rk817_bat_relax_vol_calib(battery);
32573d0407baSopenharmony_ci        rk817_bat_restart_relax(battery);
32583d0407baSopenharmony_ci        rk817_bat_relife_age_flag(battery);
32593d0407baSopenharmony_ci        ocv_soc_updated = true;
32603d0407baSopenharmony_ci    }
32613d0407baSopenharmony_ci
32623d0407baSopenharmony_ci    /* handle dsoc */
32633d0407baSopenharmony_ci    if (battery->dsoc <= battery->rsoc) {
32643d0407baSopenharmony_ci        if (battery->pdata->low_pwr_sleep) {
32653d0407baSopenharmony_ci            sleep_cur = LOW_PWR_SLP_CURR_MIN;
32663d0407baSopenharmony_ci        } else {
32673d0407baSopenharmony_ci            sleep_cur = SLP_CURR_MIN;
32683d0407baSopenharmony_ci        }
32693d0407baSopenharmony_ci        battery->sleep_sum_cap = (sleep_cur * sleep_sec / 0xE10);
32703d0407baSopenharmony_ci        sleep_soc = battery->sleep_sum_cap * 0X64 / DIV(battery->fcc);
32713d0407baSopenharmony_ci        tgt_dsoc = battery->dsoc - sleep_soc * 0x3E8;
32723d0407baSopenharmony_ci        if (sleep_soc > 0) {
32733d0407baSopenharmony_ci            BAT_INFO("calib0: rl=%d, dl=%d, intval=%d\n", battery->rsoc, battery->dsoc, sleep_soc);
32743d0407baSopenharmony_ci            if (battery->dsoc / 0x3E8 < 0X05) {
32753d0407baSopenharmony_ci                battery->dsoc -= 0x3E8;
32763d0407baSopenharmony_ci            } else if ((tgt_dsoc / 0x3E8 < 0X05) && (battery->dsoc / 0x3E8 >= 0X05)) {
32773d0407baSopenharmony_ci                if (battery->dsoc / 0x3E8 == 0X05) {
32783d0407baSopenharmony_ci                    battery->dsoc -= 0x3E8;
32793d0407baSopenharmony_ci                } else {
32803d0407baSopenharmony_ci                    battery->dsoc = 0X05 * 0x3E8;
32813d0407baSopenharmony_ci                }
32823d0407baSopenharmony_ci            } else if (tgt_dsoc / 0x3E8 > 0X05) {
32833d0407baSopenharmony_ci                battery->dsoc = tgt_dsoc;
32843d0407baSopenharmony_ci            }
32853d0407baSopenharmony_ci        }
32863d0407baSopenharmony_ci
32873d0407baSopenharmony_ci        DBG("%s: dsoc<=rsoc, sum_cap=%d==>sleep_soc=%d, tgt_dsoc=%d\n", __func__, battery->sleep_sum_cap, sleep_soc,
32883d0407baSopenharmony_ci            tgt_dsoc);
32893d0407baSopenharmony_ci    } else {
32903d0407baSopenharmony_ci        /* di->dsoc > di->rsoc */
32913d0407baSopenharmony_ci        if (battery->pdata->low_pwr_sleep) {
32923d0407baSopenharmony_ci            sleep_cur = LOW_PWR_SLP_CURR_MAX;
32933d0407baSopenharmony_ci        } else {
32943d0407baSopenharmony_ci            sleep_cur = SLP_CURR_MAX;
32953d0407baSopenharmony_ci        }
32963d0407baSopenharmony_ci        battery->sleep_sum_cap = (sleep_cur * sleep_sec / 0xE10);
32973d0407baSopenharmony_ci        sleep_soc = battery->sleep_sum_cap / DIV(battery->fcc / 100);
32983d0407baSopenharmony_ci        gap_soc = battery->dsoc - battery->rsoc;
32993d0407baSopenharmony_ci
33003d0407baSopenharmony_ci        DBG("calib1: rsoc=%d, dsoc=%d, intval=%d\n", battery->rsoc, battery->dsoc, sleep_soc);
33013d0407baSopenharmony_ci        if (gap_soc / 0x3E8 > sleep_soc) {
33023d0407baSopenharmony_ci            if ((gap_soc - 0x1388) > (sleep_soc * 0X02 * 0x3E8)) {
33033d0407baSopenharmony_ci                battery->dsoc -= (sleep_soc * 0X02 * 0x3E8);
33043d0407baSopenharmony_ci            } else {
33053d0407baSopenharmony_ci                battery->dsoc -= sleep_soc * 0x3E8;
33063d0407baSopenharmony_ci            }
33073d0407baSopenharmony_ci        } else {
33083d0407baSopenharmony_ci            battery->dsoc = battery->rsoc;
33093d0407baSopenharmony_ci        }
33103d0407baSopenharmony_ci
33113d0407baSopenharmony_ci        DBG("%s: dsoc>rsoc, sum_cap=%d=>sleep_soc=%d, gap_soc=%d\n", __func__, battery->sleep_sum_cap, sleep_soc,
33123d0407baSopenharmony_ci            gap_soc);
33133d0407baSopenharmony_ci    }
33143d0407baSopenharmony_ci
33153d0407baSopenharmony_ci    if (battery->voltage_avg <= pwroff_vol - 0x46) {
33163d0407baSopenharmony_ci        battery->dsoc = 0;
33173d0407baSopenharmony_ci        DBG("low power sleeping, shutdown... %d\n", battery->dsoc);
33183d0407baSopenharmony_ci    }
33193d0407baSopenharmony_ci
33203d0407baSopenharmony_ci    if (ocv_soc_updated && sleep_soc && (battery->rsoc - battery->dsoc) < 0x1388 && battery->dsoc < 0x28 * 0x3E8) {
33213d0407baSopenharmony_ci        battery->dsoc -= 0x3E8;
33223d0407baSopenharmony_ci        DBG("low power sleeping, reserved... %d\n", battery->dsoc);
33233d0407baSopenharmony_ci    }
33243d0407baSopenharmony_ci
33253d0407baSopenharmony_ci    if (battery->dsoc <= 0) {
33263d0407baSopenharmony_ci        battery->dsoc = 0;
33273d0407baSopenharmony_ci        DBG("sleep dsoc is %d...\n", battery->dsoc);
33283d0407baSopenharmony_ci    }
33293d0407baSopenharmony_ci
33303d0407baSopenharmony_ci    DBG("<%s>. out: dsoc=%d, rsoc=%d, sum_cap=%d\n", __func__, battery->dsoc, battery->rsoc, battery->sleep_sum_cap);
33313d0407baSopenharmony_ci
33323d0407baSopenharmony_ci    return sleep_soc;
33333d0407baSopenharmony_ci}
33343d0407baSopenharmony_ci
33353d0407baSopenharmony_cistatic void rk817_bat_resume_work(struct work_struct *work)
33363d0407baSopenharmony_ci{
33373d0407baSopenharmony_ci    struct rk817_battery_device *battery = container_of(work, struct rk817_battery_device, resume_work);
33383d0407baSopenharmony_ci    int interval_sec = 0, time_step = 0, pwroff_vol;
33393d0407baSopenharmony_ci
33403d0407baSopenharmony_ci    battery->s2r = true;
33413d0407baSopenharmony_ci    battery->current_avg = rk817_bat_get_avg_current(battery);
33423d0407baSopenharmony_ci    battery->voltage_relax = rk817_bat_get_relax_voltage(battery);
33433d0407baSopenharmony_ci    battery->voltage_avg = rk817_bat_get_battery_voltage(battery);
33443d0407baSopenharmony_ci    battery->remain_cap = rk817_bat_get_capacity_uah(battery);
33453d0407baSopenharmony_ci    battery->rsoc = rk817_bat_get_rsoc(battery);
33463d0407baSopenharmony_ci    interval_sec = rk817_bat_rtc_sleep_sec(battery);
33473d0407baSopenharmony_ci    battery->sleep_sum_sec += interval_sec;
33483d0407baSopenharmony_ci    pwroff_vol = battery->pdata->pwroff_vol;
33493d0407baSopenharmony_ci
33503d0407baSopenharmony_ci    if (!battery->sleep_chrg_online) {
33513d0407baSopenharmony_ci        /* only add up discharge sleep seconds */
33523d0407baSopenharmony_ci        battery->sleep_dischrg_sec += interval_sec;
33533d0407baSopenharmony_ci        if (battery->voltage_avg <= pwroff_vol + 0x32) {
33543d0407baSopenharmony_ci            time_step = DISCHRG_TIME_STEP1;
33553d0407baSopenharmony_ci        } else {
33563d0407baSopenharmony_ci            time_step = DISCHRG_TIME_STEP2;
33573d0407baSopenharmony_ci        }
33583d0407baSopenharmony_ci    }
33593d0407baSopenharmony_ci
33603d0407baSopenharmony_ci    DBG("resume: dl=%d rl=%d c=%d v=%d rv=%d "
33613d0407baSopenharmony_ci        "cap=%d dt=%d at=%ld ch=%d, sec = %d\n",
33623d0407baSopenharmony_ci        battery->dsoc, battery->rsoc, battery->current_avg, battery->voltage_avg, battery->voltage_relax,
33633d0407baSopenharmony_ci        rk817_bat_get_capacity_uah(battery), interval_sec, battery->sleep_dischrg_sec, battery->sleep_chrg_online,
33643d0407baSopenharmony_ci        interval_sec);
33653d0407baSopenharmony_ci
33663d0407baSopenharmony_ci    /* sleep: enough time and discharge */
33673d0407baSopenharmony_ci    if ((!battery->sleep_chrg_online) && (battery->sleep_dischrg_sec > time_step)) {
33683d0407baSopenharmony_ci        if (rk817_bat_sleep_dischrg(battery)) {
33693d0407baSopenharmony_ci            battery->sleep_dischrg_sec = 0;
33703d0407baSopenharmony_ci        }
33713d0407baSopenharmony_ci    }
33723d0407baSopenharmony_ci
33733d0407baSopenharmony_ci    rk817_bat_save_data(battery);
33743d0407baSopenharmony_ci
33753d0407baSopenharmony_ci    /* charge/lowpower lock: for battery work to update dsoc and rsoc */
33763d0407baSopenharmony_ci    if ((battery->sleep_chrg_online) ||
33773d0407baSopenharmony_ci        (!battery->sleep_chrg_online && battery->voltage_avg < battery->pdata->pwroff_vol)) {
33783d0407baSopenharmony_ci        wake_lock_timeout(&battery->wake_lock, msecs_to_jiffies(0x7D0));
33793d0407baSopenharmony_ci    }
33803d0407baSopenharmony_ci
33813d0407baSopenharmony_ci    queue_delayed_work(battery->bat_monitor_wq, &battery->bat_delay_work, msecs_to_jiffies(0x3E8));
33823d0407baSopenharmony_ci}
33833d0407baSopenharmony_ci
33843d0407baSopenharmony_cistatic int rk817_bat_pm_resume(struct device *dev)
33853d0407baSopenharmony_ci{
33863d0407baSopenharmony_ci    struct rk817_battery_device *battery = dev_get_drvdata(dev);
33873d0407baSopenharmony_ci
33883d0407baSopenharmony_ci    queue_work(battery->bat_monitor_wq, &battery->resume_work);
33893d0407baSopenharmony_ci
33903d0407baSopenharmony_ci    return 0;
33913d0407baSopenharmony_ci}
33923d0407baSopenharmony_ci#endif
33933d0407baSopenharmony_ci
33943d0407baSopenharmony_cistatic SIMPLE_DEV_PM_OPS(rk817_bat_pm_ops, rk817_bat_pm_suspend, rk817_bat_pm_resume);
33953d0407baSopenharmony_ci
33963d0407baSopenharmony_cistatic struct platform_driver rk817_battery_driver = {
33973d0407baSopenharmony_ci    .probe = rk817_battery_probe,
33983d0407baSopenharmony_ci    .shutdown = rk817_battery_shutdown,
33993d0407baSopenharmony_ci    .driver =
34003d0407baSopenharmony_ci        {
34013d0407baSopenharmony_ci            .name = "rk817-battery",
34023d0407baSopenharmony_ci            .pm = &rk817_bat_pm_ops,
34033d0407baSopenharmony_ci            .of_match_table = of_match_ptr(rk817_bat_of_match),
34043d0407baSopenharmony_ci        },
34053d0407baSopenharmony_ci};
34063d0407baSopenharmony_ci
34073d0407baSopenharmony_cistatic int __init rk817_battery_init(void)
34083d0407baSopenharmony_ci{
34093d0407baSopenharmony_ci    return platform_driver_register(&rk817_battery_driver);
34103d0407baSopenharmony_ci}
34113d0407baSopenharmony_cifs_initcall_sync(rk817_battery_init);
34123d0407baSopenharmony_ci
34133d0407baSopenharmony_cistatic void __exit rk817_battery_exit(void)
34143d0407baSopenharmony_ci{
34153d0407baSopenharmony_ci    platform_driver_unregister(&rk817_battery_driver);
34163d0407baSopenharmony_ci}
34173d0407baSopenharmony_cimodule_exit(rk817_battery_exit);
34183d0407baSopenharmony_ci
34193d0407baSopenharmony_ciMODULE_DESCRIPTION("RK817 Battery driver");
34203d0407baSopenharmony_ciMODULE_LICENSE("GPL");
3421