Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02045bcc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: qpnp-qg: Replace ktime_get with ktime_get_boottime"

parents 34acde82 b169d1a7
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,10 @@ struct qg_dt {
	int			s2_vbat_low_fifo_length;
	int			s2_vbat_low_fifo_length;
	int			s2_acc_length;
	int			s2_acc_length;
	int			s2_acc_intvl_ms;
	int			s2_acc_intvl_ms;
	int			sleep_s2_fifo_length;
	int			sleep_s2_acc_length;
	int			sleep_s2_acc_intvl_ms;
	int			fast_chg_s2_fifo_length;
	int			ocv_timer_expiry_min;
	int			ocv_timer_expiry_min;
	int			ocv_tol_threshold_uv;
	int			ocv_tol_threshold_uv;
	int			s3_entry_fifo_length;
	int			s3_entry_fifo_length;
@@ -61,6 +65,8 @@ struct qg_dt {
	bool			esr_discharge_enable;
	bool			esr_discharge_enable;
	bool			qg_ext_sense;
	bool			qg_ext_sense;
	bool			use_s7_ocv;
	bool			use_s7_ocv;
	bool			qg_sleep_config;
	bool			qg_fast_chg_cfg;
};
};


struct qg_esr_data {
struct qg_esr_data {
@@ -86,6 +92,7 @@ struct qpnp_qg {
	struct work_struct	udata_work;
	struct work_struct	udata_work;
	struct work_struct	scale_soc_work;
	struct work_struct	scale_soc_work;
	struct work_struct	qg_status_change_work;
	struct work_struct	qg_status_change_work;
	struct delayed_work	qg_sleep_exit_work;
	struct notifier_block	nb;
	struct notifier_block	nb;
	struct mutex		bus_lock;
	struct mutex		bus_lock;
	struct mutex		data_lock;
	struct mutex		data_lock;
@@ -136,6 +143,8 @@ struct qpnp_qg {
	u32			charge_counter_uah;
	u32			charge_counter_uah;
	u32			esr_avg;
	u32			esr_avg;
	u32			esr_last;
	u32			esr_last;
	u32			s2_state;
	u32			s2_state_mask;
	ktime_t			last_user_update_time;
	ktime_t			last_user_update_time;
	ktime_t			last_fifo_update_time;
	ktime_t			last_fifo_update_time;
	unsigned long		last_maint_soc_update_time;
	unsigned long		last_maint_soc_update_time;
@@ -182,6 +191,13 @@ enum ocv_type {
	PON_OCV_MAX,
	PON_OCV_MAX,
};
};


enum s2_state {
	S2_FAST_CHARGING = BIT(0),
	S2_LOW_VBAT = BIT(1),
	S2_SLEEP = BIT(2),
	S2_DEFAULT = BIT(3),
};

enum debug_mask {
enum debug_mask {
	QG_DEBUG_PON		= BIT(0),
	QG_DEBUG_PON		= BIT(0),
	QG_DEBUG_PROFILE	= BIT(1),
	QG_DEBUG_PROFILE	= BIT(1),
+3 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: GPL-2.0 */
/*
/*
 * Copyright (c) 2018 The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 */
 */


#ifndef __QG_DEFS_H__
#ifndef __QG_DEFS_H__
@@ -28,6 +28,8 @@
#define PROFILE_IRQ_DISABLE		"NO_PROFILE_IRQ_DISABLE"
#define PROFILE_IRQ_DISABLE		"NO_PROFILE_IRQ_DISABLE"
#define QG_INIT_STATE_IRQ_DISABLE	"QG_INIT_STATE_IRQ_DISABLE"
#define QG_INIT_STATE_IRQ_DISABLE	"QG_INIT_STATE_IRQ_DISABLE"
#define TTF_AWAKE_VOTER			"TTF_AWAKE_VOTER"
#define TTF_AWAKE_VOTER			"TTF_AWAKE_VOTER"
#define SLEEP_EXIT_DATA_VOTER		"SLEEP_EXIT_DATA_VOTER"
#define SLEEP_EXIT_VOTER		"SLEEP_EXIT_VOTER"


#define V_RAW_TO_UV(V_RAW)		div_u64(194637ULL * (u64)V_RAW, 1000)
#define V_RAW_TO_UV(V_RAW)		div_u64(194637ULL * (u64)V_RAW, 1000)
#define FIFO_V_RESET_VAL		0x8000
#define FIFO_V_RESET_VAL		0x8000
+256 −44
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/power_supply.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/timekeeping.h>
#include <linux/uaccess.h>
#include <linux/uaccess.h>
#include <linux/pmic-voter.h>
#include <linux/pmic-voter.h>
#include <linux/iio/consumer.h>
#include <linux/iio/consumer.h>
@@ -89,6 +90,8 @@ static struct attribute *qg_attrs[] = {
};
};
ATTRIBUTE_GROUPS(qg);
ATTRIBUTE_GROUPS(qg);


static int qg_process_rt_fifo(struct qpnp_qg *chip);

static bool is_battery_present(struct qpnp_qg *chip)
static bool is_battery_present(struct qpnp_qg *chip)
{
{
	u8 reg = 0;
	u8 reg = 0;
@@ -179,7 +182,7 @@ static int qg_update_fifo_length(struct qpnp_qg *chip, u8 length)
		pr_err("Failed to write S2 FIFO length, rc=%d\n", rc);
		pr_err("Failed to write S2 FIFO length, rc=%d\n", rc);


	/* update the S3 FIFO length, when S2 length is updated */
	/* update the S3 FIFO length, when S2 length is updated */
	if (length > 3)
	if (length > 3 && !chip->dt.qg_sleep_config)
		s3_entry_fifo_length = (chip->dt.s3_entry_fifo_length > 0) ?
		s3_entry_fifo_length = (chip->dt.s3_entry_fifo_length > 0) ?
			chip->dt.s3_entry_fifo_length : DEFAULT_S3_FIFO_LENGTH;
			chip->dt.s3_entry_fifo_length : DEFAULT_S3_FIFO_LENGTH;
	else	/* Use S3 length as 1 for any S2 length <= 3 */
	else	/* Use S3 length as 1 for any S2 length <= 3 */
@@ -308,6 +311,111 @@ static int qg_store_soc_params(struct qpnp_qg *chip)
	return rc;
	return rc;
}
}


static int qg_config_s2_state(struct qpnp_qg *chip,
		enum s2_state requested_state, bool state_enable,
		bool process_fifo)
{
	int rc, acc_interval, acc_length;
	u8 fifo_length, reg = 0, state = S2_DEFAULT;

	if ((chip->s2_state_mask & requested_state) && (state_enable == true))
		return 0; /* No change in state */

	if (!(chip->s2_state_mask & requested_state) && (state_enable == false))
		return 0; /* No change in state */

	if (state_enable)
		chip->s2_state_mask |= requested_state;
	else
		chip->s2_state_mask &= ~requested_state;

	/* define the priority of the states */
	if (chip->s2_state_mask & S2_FAST_CHARGING)
		state = S2_FAST_CHARGING;
	else if (chip->s2_state_mask & S2_LOW_VBAT)
		state = S2_LOW_VBAT;
	else if (chip->s2_state_mask & S2_SLEEP)
		state = S2_SLEEP;
	else
		state = S2_DEFAULT;

	if (state == chip->s2_state)
		return 0;

	switch (state) {
	case S2_FAST_CHARGING:
		fifo_length = chip->dt.fast_chg_s2_fifo_length;
		acc_interval = chip->dt.s2_acc_intvl_ms;
		acc_length = chip->dt.s2_acc_length;
		break;
	case S2_LOW_VBAT:
		fifo_length = chip->dt.s2_vbat_low_fifo_length;
		acc_interval = chip->dt.s2_acc_intvl_ms;
		acc_length = chip->dt.s2_acc_length;
		break;
	case S2_SLEEP:
		fifo_length = chip->dt.sleep_s2_fifo_length;
		acc_interval = chip->dt.sleep_s2_acc_intvl_ms;
		acc_length = chip->dt.sleep_s2_acc_length;
		break;
	case S2_DEFAULT:
		fifo_length = chip->dt.s2_fifo_length;
		acc_interval = chip->dt.s2_acc_intvl_ms;
		acc_length = chip->dt.s2_acc_length;
		break;
	default:
		pr_err("Invalid S2 state %d\n", state);
		return -EINVAL;
	}

	rc = qg_master_hold(chip, true);
	if (rc < 0) {
		pr_err("Failed to hold master, rc=%d\n", rc);
		return rc;
	}

	if (process_fifo) {
		rc = qg_process_rt_fifo(chip);
		if (rc < 0) {
			pr_err("Failed to process FIFO real-time, rc=%d\n", rc);
			goto done;
		}
	}

	rc = qg_update_fifo_length(chip, fifo_length);
	if (rc < 0) {
		pr_err("Failed to update S2 fifo-length, rc=%d\n", rc);
		goto done;
	}

	reg = acc_interval / 10;
	rc = qg_write(chip, chip->qg_base + QG_S2_NORMAL_MEAS_CTL3_REG,
					&reg, 1);
	if (rc < 0) {
		pr_err("Failed to update S2 acc intrvl, rc=%d\n", rc);
		goto done;
	}

	reg = ilog2(acc_length) - 1;
	rc = qg_masked_write(chip, chip->qg_base + QG_S2_NORMAL_MEAS_CTL2_REG,
					NUM_OF_ACCUM_MASK, reg);
	if (rc < 0) {
		pr_err("Failed to update S2 ACC length, rc=%d\n", rc);
		goto done;
	}

	chip->s2_state = state;

	qg_dbg(chip, QG_DEBUG_STATUS, "S2 New state=%x  fifo_length=%d interval=%d acc_length=%d\n",
				state, fifo_length, acc_interval, acc_length);

done:
	qg_master_hold(chip, false);
	/* FIFO restarted */
	chip->last_fifo_update_time = ktime_get_boottime();
	return rc;
}

static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length)
static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length)
{
{
	int rc = 0, i, j = 0, temp;
	int rc = 0, i, j = 0, temp;
@@ -492,7 +600,7 @@ static int qg_process_rt_fifo(struct qpnp_qg *chip)
static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
{
{
	int rc = 0;
	int rc = 0;
	ktime_t now = ktime_get();
	ktime_t now = ktime_get_boottime();
	s64 time_delta;
	s64 time_delta;


	/*
	/*
@@ -537,7 +645,7 @@ static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
			goto done;
			goto done;
		}
		}
		/* FIFOs restarted */
		/* FIFOs restarted */
		chip->last_fifo_update_time = ktime_get();
		chip->last_fifo_update_time = ktime_get_boottime();


		/* signal the read thread */
		/* signal the read thread */
		chip->data_ready = true;
		chip->data_ready = true;
@@ -559,7 +667,7 @@ static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
static int qg_vbat_low_wa(struct qpnp_qg *chip)
static int qg_vbat_low_wa(struct qpnp_qg *chip)
{
{
	int rc, i, temp = 0;
	int rc, i, temp = 0;
	u32 vbat_low_uv = 0, fifo_length = 0;
	u32 vbat_low_uv = 0;


	if ((chip->wa_flags & QG_VBAT_LOW_WA) && chip->vbat_low) {
	if ((chip->wa_flags & QG_VBAT_LOW_WA) && chip->vbat_low) {
		rc = qg_get_battery_temp(chip, &temp);
		rc = qg_get_battery_temp(chip, &temp);
@@ -589,37 +697,11 @@ static int qg_vbat_low_wa(struct qpnp_qg *chip)
		}
		}
	}
	}


	rc = get_fifo_length(chip, &fifo_length, false);
	rc = qg_config_s2_state(chip, S2_LOW_VBAT,
	if (rc < 0) {
			chip->vbat_low ? true : false, false);
		pr_err("Failed to get FIFO length, rc=%d\n", rc);
		return rc;
	}

	if (chip->vbat_low && fifo_length == chip->dt.s2_vbat_low_fifo_length)
		return 0;

	if (!chip->vbat_low && fifo_length == chip->dt.s2_fifo_length)
		return 0;

	rc = qg_master_hold(chip, true);
	if (rc < 0) {
		pr_err("Failed to hold master, rc=%d\n", rc);
		goto done;
	}

	fifo_length = chip->vbat_low ? chip->dt.s2_vbat_low_fifo_length :
					chip->dt.s2_fifo_length;

	rc = qg_update_fifo_length(chip, fifo_length);
	if (rc < 0)
	if (rc < 0)
		goto done;
		pr_err("Failed to configure for VBAT_LOW rc=%d\n", rc);


	qg_dbg(chip, QG_DEBUG_STATUS, "FIFO length updated to %d vbat_low=%d\n",
					fifo_length, chip->vbat_low);
done:
	qg_master_hold(chip, false);
	/* FIFOs restarted */
	chip->last_fifo_update_time = ktime_get();
	return rc;
	return rc;
}
}


@@ -690,6 +772,22 @@ static int qg_vbat_thresholds_config(struct qpnp_qg *chip)
	return rc;
	return rc;
}
}


static int qg_fast_charge_config(struct qpnp_qg *chip)
{
	int rc = 0;

	if (!chip->dt.qg_fast_chg_cfg)
		return 0;

	rc = qg_config_s2_state(chip, S2_FAST_CHARGING,
			(chip->charge_status == POWER_SUPPLY_STATUS_CHARGING)
			? true : false, false);
	if (rc < 0)
		pr_err("Failed to exit S2_SLEEP rc=%d\n", rc);

	return rc;
}

static void qg_retrieve_esr_params(struct qpnp_qg *chip)
static void qg_retrieve_esr_params(struct qpnp_qg *chip)
{
{
	u32 data = 0;
	u32 data = 0;
@@ -1035,7 +1133,7 @@ static int qg_esr_estimate(struct qpnp_qg *chip)
		goto done;
		goto done;
	}
	}
	/* FIFOs restarted */
	/* FIFOs restarted */
	chip->last_fifo_update_time = ktime_get();
	chip->last_fifo_update_time = ktime_get_boottime();


	if (chip->esr_avg) {
	if (chip->esr_avg) {
		chip->kdata.param[QG_ESR].data = chip->esr_avg;
		chip->kdata.param[QG_ESR].data = chip->esr_avg;
@@ -1122,7 +1220,7 @@ static void process_udata_work(struct work_struct *work)
#define MAX_FIFO_DELTA_PERCENT		10
#define MAX_FIFO_DELTA_PERCENT		10
static irqreturn_t qg_fifo_update_done_handler(int irq, void *data)
static irqreturn_t qg_fifo_update_done_handler(int irq, void *data)
{
{
	ktime_t now = ktime_get();
	ktime_t now = ktime_get_boottime();
	int rc, hw_delta_ms = 0, margin_ms = 0;
	int rc, hw_delta_ms = 0, margin_ms = 0;
	u32 fifo_length = 0;
	u32 fifo_length = 0;
	s64 time_delta_ms = 0;
	s64 time_delta_ms = 0;
@@ -1153,6 +1251,10 @@ static irqreturn_t qg_fifo_update_done_handler(int irq, void *data)
	if (rc < 0)
	if (rc < 0)
		pr_err("Failed to apply VBAT EMPTY config rc=%d\n", rc);
		pr_err("Failed to apply VBAT EMPTY config rc=%d\n", rc);


	rc = qg_fast_charge_config(chip);
	if (rc < 0)
		pr_err("Failed to apply fast-charge config rc=%d\n", rc);

	rc = qg_vbat_low_wa(chip);
	rc = qg_vbat_low_wa(chip);
	if (rc < 0) {
	if (rc < 0) {
		pr_err("Failed to apply VBAT LOW WA, rc=%d\n", rc);
		pr_err("Failed to apply VBAT LOW WA, rc=%d\n", rc);
@@ -1893,6 +1995,9 @@ static int qg_psy_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CAPACITY:
	case POWER_SUPPLY_PROP_CAPACITY:
		rc = qg_get_battery_capacity(chip, &pval->intval);
		rc = qg_get_battery_capacity(chip, &pval->intval);
		break;
		break;
	case POWER_SUPPLY_PROP_CAPACITY_RAW:
		pval->intval = chip->sys_soc;
		break;
	case POWER_SUPPLY_PROP_REAL_CAPACITY:
	case POWER_SUPPLY_PROP_REAL_CAPACITY:
		rc = qg_get_battery_capacity_real(chip, &pval->intval);
		rc = qg_get_battery_capacity_real(chip, &pval->intval);
		break;
		break;
@@ -2022,6 +2127,7 @@ static int qg_property_is_writeable(struct power_supply *psy,


static enum power_supply_property qg_psy_props[] = {
static enum power_supply_property qg_psy_props[] = {
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_CAPACITY_RAW,
	POWER_SUPPLY_PROP_REAL_CAPACITY,
	POWER_SUPPLY_PROP_REAL_CAPACITY,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -2308,6 +2414,33 @@ static int qg_battery_status_update(struct qpnp_qg *chip)
	return rc;
	return rc;
}
}


static void qg_sleep_exit_work(struct work_struct *work)
{
	int rc;
	struct qpnp_qg *chip = container_of(work,
			struct qpnp_qg, qg_sleep_exit_work.work);

	vote(chip->awake_votable, SLEEP_EXIT_VOTER, true, 0);

	mutex_lock(&chip->data_lock);
	/*
	 * if this work is executing, the system has been active
	 * for a while. So, force back the S2 active configuration
	 */
	qg_dbg(chip, QG_DEBUG_STATUS, "sleep_exit_work: exit S2_SLEEP\n");
	rc = qg_config_s2_state(chip, S2_SLEEP, false, true);
	if (rc < 0)
		pr_err("Failed to exit S2_SLEEP rc=%d\n", rc);

	vote(chip->awake_votable, SLEEP_EXIT_DATA_VOTER, true, 0);
	/* signal the read thread */
	chip->data_ready = true;
	wake_up_interruptible(&chip->qg_wait_q);

	mutex_unlock(&chip->data_lock);

	vote(chip->awake_votable, SLEEP_EXIT_VOTER, false, 0);
}


static void qg_status_change_work(struct work_struct *work)
static void qg_status_change_work(struct work_struct *work)
{
{
@@ -2480,6 +2613,7 @@ static ssize_t qg_device_read(struct file *file, char __user *buf, size_t count,
	vote(chip->awake_votable, FIFO_DONE_VOTER, false, 0);
	vote(chip->awake_votable, FIFO_DONE_VOTER, false, 0);
	vote(chip->awake_votable, FIFO_RT_DONE_VOTER, false, 0);
	vote(chip->awake_votable, FIFO_RT_DONE_VOTER, false, 0);
	vote(chip->awake_votable, SUSPEND_DATA_VOTER, false, 0);
	vote(chip->awake_votable, SUSPEND_DATA_VOTER, false, 0);
	vote(chip->awake_votable, SLEEP_EXIT_DATA_VOTER, false, 0);


	qg_dbg(chip, QG_DEBUG_DEVICE,
	qg_dbg(chip, QG_DEBUG_DEVICE,
		"QG device read complete Seq_no=%u Size=%ld\n",
		"QG device read complete Seq_no=%u Size=%ld\n",
@@ -2822,7 +2956,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
	bool use_pon_ocv = true;
	bool use_pon_ocv = true;
	unsigned long rtc_sec = 0;
	unsigned long rtc_sec = 0;
	u32 ocv_uv = 0, soc = 0, pon_soc = 0, full_soc = 0, cutoff_soc = 0;
	u32 ocv_uv = 0, soc = 0, pon_soc = 0, full_soc = 0, cutoff_soc = 0;
	u32 shutdown[SDAM_MAX] = {0};
	u32 shutdown[SDAM_MAX] = {0}, soc_raw = 0;
	char ocv_type[20] = "NONE";
	char ocv_type[20] = "NONE";


	if (!chip->profile_loaded) {
	if (!chip->profile_loaded) {
@@ -2901,6 +3035,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
	use_pon_ocv = false;
	use_pon_ocv = false;
	ocv_uv = shutdown[SDAM_OCV_UV];
	ocv_uv = shutdown[SDAM_OCV_UV];
	soc = shutdown[SDAM_SOC];
	soc = shutdown[SDAM_SOC];
	soc_raw = shutdown[SDAM_SOC] * 100;
	strlcpy(ocv_type, "SHUTDOWN_SOC", 20);
	strlcpy(ocv_type, "SHUTDOWN_SOC", 20);
	qg_dbg(chip, QG_DEBUG_PON, "Using SHUTDOWN_SOC @ PON\n");
	qg_dbg(chip, QG_DEBUG_PON, "Using SHUTDOWN_SOC @ PON\n");


@@ -2968,7 +3103,9 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
			soc = DIV_ROUND_UP(((pon_soc - cutoff_soc) * 100),
			soc = DIV_ROUND_UP(((pon_soc - cutoff_soc) * 100),
						(full_soc - cutoff_soc));
						(full_soc - cutoff_soc));
			soc = CAP(0, 100, soc);
			soc = CAP(0, 100, soc);
			soc_raw = soc * 100;
		} else {
		} else {
			soc_raw = pon_soc * 100;
			soc = pon_soc;
			soc = pon_soc;
		}
		}


@@ -2982,6 +3119,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
		return rc;
		return rc;
	}
	}


	chip->cc_soc = chip->sys_soc = soc_raw;
	chip->last_adj_ssoc = chip->catch_up_soc = chip->msoc = soc;
	chip->last_adj_ssoc = chip->catch_up_soc = chip->msoc = soc;
	chip->kdata.param[QG_PON_OCV_UV].data = ocv_uv;
	chip->kdata.param[QG_PON_OCV_UV].data = ocv_uv;
	chip->kdata.param[QG_PON_OCV_UV].valid = true;
	chip->kdata.param[QG_PON_OCV_UV].valid = true;
@@ -3098,6 +3236,8 @@ static int qg_hw_init(struct qpnp_qg *chip)
		}
		}
	}
	}


	chip->s2_state = S2_DEFAULT;
	chip->s2_state_mask |= S2_DEFAULT;
	/* signal the read thread */
	/* signal the read thread */
	chip->data_ready = true;
	chip->data_ready = true;
	wake_up_interruptible(&chip->qg_wait_q);
	wake_up_interruptible(&chip->qg_wait_q);
@@ -3108,7 +3248,7 @@ static int qg_hw_init(struct qpnp_qg *chip)
		pr_err("Failed to release master, rc=%d\n", rc);
		pr_err("Failed to release master, rc=%d\n", rc);
		return rc;
		return rc;
	}
	}
	chip->last_fifo_update_time = ktime_get();
	chip->last_fifo_update_time = ktime_get_boottime();


	if (chip->dt.ocv_timer_expiry_min != -EINVAL) {
	if (chip->dt.ocv_timer_expiry_min != -EINVAL) {
		if (chip->dt.ocv_timer_expiry_min < 2)
		if (chip->dt.ocv_timer_expiry_min < 2)
@@ -3452,6 +3592,10 @@ static void qg_create_debugfs(struct qpnp_qg *chip)
#define DEFAULT_S2_VBAT_LOW_LENGTH	2
#define DEFAULT_S2_VBAT_LOW_LENGTH	2
#define DEFAULT_S2_ACC_LENGTH		128
#define DEFAULT_S2_ACC_LENGTH		128
#define DEFAULT_S2_ACC_INTVL_MS		100
#define DEFAULT_S2_ACC_INTVL_MS		100
#define DEFAULT_SLEEP_S2_FIFO_LENGTH	8
#define DEFAULT_SLEEP_S2_ACC_LENGTH	256
#define DEFAULT_SLEEP_S2_ACC_INTVL_MS	200
#define DEFAULT_FAST_CHG_S2_FIFO_LENGTH	1
static int qg_parse_s2_dt(struct qpnp_qg *chip)
static int qg_parse_s2_dt(struct qpnp_qg *chip)
{
{
	int rc;
	int rc;
@@ -3487,6 +3631,48 @@ static int qg_parse_s2_dt(struct qpnp_qg *chip)
		chip->dt.s2_fifo_length, chip->dt.s2_vbat_low_fifo_length,
		chip->dt.s2_fifo_length, chip->dt.s2_vbat_low_fifo_length,
		chip->dt.s2_acc_length, chip->dt.s2_acc_intvl_ms);
		chip->dt.s2_acc_length, chip->dt.s2_acc_intvl_ms);


	if (of_property_read_bool(node, "qcom,qg-sleep-config")) {

		chip->dt.qg_sleep_config = true;

		rc = of_property_read_u32(node,
				"qcom,sleep-s2-fifo-length", &temp);
		if (rc < 0)
			chip->dt.sleep_s2_fifo_length =
					DEFAULT_SLEEP_S2_FIFO_LENGTH;
		else
			chip->dt.sleep_s2_fifo_length = temp;

		rc = of_property_read_u32(node,
				"qcom,sleep-s2-acc-length", &temp);
		if (rc < 0)
			chip->dt.sleep_s2_acc_length =
					DEFAULT_SLEEP_S2_ACC_LENGTH;
		else
			chip->dt.sleep_s2_acc_length = temp;

		rc = of_property_read_u32(node,
				"qcom,sleep-s2-acc-intvl-ms", &temp);
		if (rc < 0)
			chip->dt.sleep_s2_acc_intvl_ms =
					DEFAULT_SLEEP_S2_ACC_INTVL_MS;
		else
			chip->dt.sleep_s2_acc_intvl_ms = temp;
	}

	if (of_property_read_bool(node, "qcom,qg-fast-chg-config")) {

		chip->dt.qg_fast_chg_cfg = true;

		rc = of_property_read_u32(node,
				"qcom,fast-chg-s2-fifo-length", &temp);
		if (rc < 0)
			chip->dt.fast_chg_s2_fifo_length =
					DEFAULT_FAST_CHG_S2_FIFO_LENGTH;
		else
			chip->dt.fast_chg_s2_fifo_length = temp;
	}

	return 0;
	return 0;
}
}


@@ -3842,6 +4028,7 @@ static int process_suspend(struct qpnp_qg *chip)
		return 0;
		return 0;


	cancel_delayed_work_sync(&chip->ttf->ttf_work);
	cancel_delayed_work_sync(&chip->ttf->ttf_work);
	cancel_delayed_work_sync(&chip->qg_sleep_exit_work);


	chip->suspend_data = false;
	chip->suspend_data = false;


@@ -3850,6 +4037,13 @@ static int process_suspend(struct qpnp_qg *chip)


	/* ignore any suspend processing if we are charging */
	/* ignore any suspend processing if we are charging */
	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
		/* Reset the sleep config if we are charging */
		if (chip->dt.qg_sleep_config) {
			qg_dbg(chip, QG_DEBUG_STATUS, "Suspend: Charging - Exit S2_SLEEP\n");
			rc = qg_config_s2_state(chip, S2_SLEEP, false, true);
			if (rc < 0)
				pr_err("Failed to exit S2-sleep rc=%d\n", rc);
		}
		qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n");
		qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n");
		return 0;
		return 0;
	}
	}
@@ -3867,12 +4061,23 @@ static int process_suspend(struct qpnp_qg *chip)
		return rc;
		return rc;
	}
	}
	sleep_fifo_length &= SLEEP_IBAT_QUALIFIED_LENGTH_MASK;
	sleep_fifo_length &= SLEEP_IBAT_QUALIFIED_LENGTH_MASK;

	if (chip->dt.qg_sleep_config) {
		qg_dbg(chip, QG_DEBUG_STATUS, "Suspend: Forcing S2_SLEEP\n");
		rc = qg_config_s2_state(chip, S2_SLEEP, true, true);
		if (rc < 0)
			pr_err("Failed to config S2_SLEEP rc=%d\n", rc);
		if (chip->kdata.fifo_length > 0)
			chip->suspend_data = true;
	} else if (fifo_rt_length >=
			(chip->dt.s2_fifo_length - sleep_fifo_length)) {
		/*
		/*
		 * If the real-time FIFO count is greater than
		 * If the real-time FIFO count is greater than
		 * the the #fifo to enter sleep, save the FIFO data
		 * the the #fifo to enter sleep, save the FIFO data
	 * and reset the fifo count.
		 * and reset the fifo count. This is avoid a gauranteed wakeup
		 * due to fifo_done event as the curent FIFO length is already
		 * beyond the sleep length.
		 */
		 */
	if (fifo_rt_length >= (chip->dt.s2_fifo_length - sleep_fifo_length)) {
		rc = qg_master_hold(chip, true);
		rc = qg_master_hold(chip, true);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("Failed to hold master, rc=%d\n", rc);
			pr_err("Failed to hold master, rc=%d\n", rc);
@@ -3892,7 +4097,7 @@ static int process_suspend(struct qpnp_qg *chip)
			return rc;
			return rc;
		}
		}
		/* FIFOs restarted */
		/* FIFOs restarted */
		chip->last_fifo_update_time = ktime_get();
		chip->last_fifo_update_time = ktime_get_boottime();


		chip->suspend_data = true;
		chip->suspend_data = true;
	}
	}
@@ -3907,6 +4112,7 @@ static int process_suspend(struct qpnp_qg *chip)
	return rc;
	return rc;
}
}


#define QG_SLEEP_EXIT_TIME_MS		15000 /* 15 secs */
static int process_resume(struct qpnp_qg *chip)
static int process_resume(struct qpnp_qg *chip)
{
{
	u8 status2 = 0, rt_status = 0;
	u8 status2 = 0, rt_status = 0;
@@ -3921,6 +4127,10 @@ static int process_resume(struct qpnp_qg *chip)
	get_rtc_time(&rtc_sec);
	get_rtc_time(&rtc_sec);
	sleep_time_secs = rtc_sec - chip->suspend_time;
	sleep_time_secs = rtc_sec - chip->suspend_time;


	if (chip->dt.qg_sleep_config)
		schedule_delayed_work(&chip->qg_sleep_exit_work,
				msecs_to_jiffies(QG_SLEEP_EXIT_TIME_MS));

	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
	if (rc < 0) {
	if (rc < 0) {
		pr_err("Failed to read status2 register, rc=%d\n", rc);
		pr_err("Failed to read status2 register, rc=%d\n", rc);
@@ -4088,6 +4298,7 @@ static int qpnp_qg_probe(struct platform_device *pdev)
	platform_set_drvdata(pdev, chip);
	platform_set_drvdata(pdev, chip);
	INIT_WORK(&chip->udata_work, process_udata_work);
	INIT_WORK(&chip->udata_work, process_udata_work);
	INIT_WORK(&chip->qg_status_change_work, qg_status_change_work);
	INIT_WORK(&chip->qg_status_change_work, qg_status_change_work);
	INIT_DELAYED_WORK(&chip->qg_sleep_exit_work, qg_sleep_exit_work);
	mutex_init(&chip->bus_lock);
	mutex_init(&chip->bus_lock);
	mutex_init(&chip->soc_lock);
	mutex_init(&chip->soc_lock);
	mutex_init(&chip->data_lock);
	mutex_init(&chip->data_lock);
@@ -4256,6 +4467,7 @@ static int qpnp_qg_remove(struct platform_device *pdev)
	qg_batterydata_exit();
	qg_batterydata_exit();
	qg_soc_exit(chip);
	qg_soc_exit(chip);


	cancel_delayed_work_sync(&chip->qg_sleep_exit_work);
	cancel_work_sync(&chip->udata_work);
	cancel_work_sync(&chip->udata_work);
	cancel_work_sync(&chip->qg_status_change_work);
	cancel_work_sync(&chip->qg_status_change_work);
	sysfs_remove_groups(&chip->dev->kobj, qg_groups);
	sysfs_remove_groups(&chip->dev->kobj, qg_groups);