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