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

Commit d610af94 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qpnp-fg-gen3: Add support to configure force battery profile loading"

parents 6ce9b4fe bd811f3a
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -87,7 +87,8 @@ First Level Node - FG Gen3 device
	Value type: <u32>
	Definition: Percentage of monotonic SOC increase upon which the delta
		    SOC interrupt will be triggered. If this property is not
		    specified, then the default value will be 1.
		    specified, then the default value will be 1. Possible
		    values are in the range of 0 to 12.

- qcom,fg-recharge-soc-thr
	Usage:      optional
@@ -145,6 +146,13 @@ First Level Node - FG Gen3 device
	Value type: <bool>
	Definition: Enables the cycle counter feature.

- qcom,fg-force-load-profile
	Usage:      optional
	Value type: <bool>
	Definition: If set, battery profile will be force loaded if the profile
		    loaded earlier by bootloader doesn't match with the profile
		    available in the device tree.

==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
qcom,ascent_3450mah {
	/* #Ascent_860_82209_0000_3450mAh_averaged_MasterSlave_Jul20th2016*/
	qcom,max-voltage-uv = <4350000>;
	qcom,fg-cc-cv-threshold-mv = <4340>;
	qcom,nom-batt-capacity-mah = <3450>;
	qcom,batt-id-kohm = <60>;
	qcom,battery-beta = <3435>;
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
qcom,itech_3000mah {
	/* #Itech_B00826LF_3000mAh_ver1660_averaged_MasterSlave_Jul20th2016*/
	qcom,max-voltage-uv = <4350000>;
	qcom,fg-cc-cv-threshold-mv = <4340>;
	qcom,nom-batt-capacity-mah = <3000>;
	qcom,batt-id-kohm = <100>;
	qcom,battery-beta = <3450>;
+10 −3
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@
					CHARS_PER_ITEM) + 1)		\

#define FG_SRAM_ADDRESS_MAX		255
#define PROFILE_LEN			224
#define PROFILE_COMP_LEN		148
#define BUCKET_COUNT			8
#define BUCKET_SOC_PCT			(256 / BUCKET_COUNT)

@@ -121,6 +123,8 @@ enum fg_sram_param_id {
	FG_SRAM_CUTOFF_VOLT,
	FG_SRAM_EMPTY_VOLT,
	FG_SRAM_VBATT_LOW,
	FG_SRAM_FLOAT_VOLT,
	FG_SRAM_VBATT_FULL,
	FG_SRAM_ESR_TIMER_DISCHG_MAX,
	FG_SRAM_ESR_TIMER_DISCHG_INIT,
	FG_SRAM_ESR_TIMER_CHG_MAX,
@@ -177,6 +181,7 @@ struct fg_dt_props {
	int	esr_timer_charging;
	int	esr_timer_awake;
	int	esr_timer_asleep;
	bool	force_load_profile;
};

/* parameters from battery profile */
@@ -184,6 +189,7 @@ struct fg_batt_props {
	const char	*batt_type_str;
	char		*batt_profile;
	int		float_volt_uv;
	int		vbatt_full_mv;
	int		fastchg_curr_ma;
	int		batt_id_kohm;
};
@@ -200,8 +206,8 @@ struct fg_cyc_ctr_data {
struct fg_irq_info {
	const char		*name;
	const irq_handler_t	handler;
	int			irq;
	bool			wakeable;
	int			irq;
};

struct fg_chip {
@@ -217,7 +223,7 @@ struct fg_chip {
	struct votable		*awake_votable;
	struct fg_sram_param	*sp;
	int			*debug_mask;
	char			*batt_profile;
	char			batt_profile[PROFILE_LEN];
	struct fg_dt_props	dt;
	struct fg_batt_props	bp;
	struct fg_cyc_ctr_data	cyc_ctr;
@@ -227,10 +233,11 @@ struct fg_chip {
	u32			batt_soc_base;
	u32			batt_info_base;
	u32			mem_if_base;
	int			batt_id;
	int			nom_cap_uah;
	int			status;
	int			prev_status;
	bool			batt_id_avail;
	bool			profile_available;
	bool			profile_loaded;
	bool			battery_missing;
	struct completion	soc_update;
+186 −78
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@
#define CUTOFF_VOLT_OFFSET		0
#define SYS_TERM_CURR_WORD		6
#define SYS_TERM_CURR_OFFSET		0
#define VBATT_FULL_WORD			7
#define VBATT_FULL_OFFSET		0
#define DELTA_SOC_THR_WORD		12
#define DELTA_SOC_THR_OFFSET		3
#define RECHARGE_SOC_THR_WORD		14
@@ -89,6 +91,8 @@
#define EMPTY_VOLT_v2_OFFSET		3
#define VBATT_LOW_v2_WORD		16
#define VBATT_LOW_v2_OFFSET		0
#define FLOAT_VOLT_v2_WORD		16
#define FLOAT_VOLT_v2_OFFSET		2

static int fg_decode_value_16b(struct fg_sram_param *sp,
	enum fg_sram_param_id id, int val);
@@ -97,9 +101,9 @@ static int fg_decode_default(struct fg_sram_param *sp,
static int fg_decode_batt_soc(struct fg_sram_param *sp,
	enum fg_sram_param_id id, int val);
static void fg_encode_voltage(struct fg_sram_param *sp,
	enum fg_sram_param_id id, int val, u8 *buf);
	enum fg_sram_param_id id, int val_mv, u8 *buf);
static void fg_encode_current(struct fg_sram_param *sp,
	enum fg_sram_param_id id, int val, u8 *buf);
	enum fg_sram_param_id id, int val_ma, u8 *buf);
static void fg_encode_default(struct fg_sram_param *sp,
	enum fg_sram_param_id id, int val, u8 *buf);

@@ -134,11 +138,13 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = {
		-2500, fg_encode_voltage, NULL),
	PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 100000, 390625,
		-2500, fg_encode_voltage, NULL),
	PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
		244141, 0, fg_encode_voltage, NULL),
	PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
		1000000, 122070, 0, fg_encode_current, NULL),
	PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
		100000, 390625, 0, fg_encode_current, NULL),
	PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 256,
	PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048,
		100, 0, fg_encode_default, NULL),
	PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET,
		1, 256, 100, 0, fg_encode_default, NULL),
@@ -172,12 +178,16 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
		15625, -2000, fg_encode_voltage, NULL),
	PARAM(VBATT_LOW, VBATT_LOW_v2_WORD, VBATT_LOW_v2_OFFSET, 1, 1000,
		15625, -2000, fg_encode_voltage, NULL),
	PARAM(FLOAT_VOLT, FLOAT_VOLT_v2_WORD, FLOAT_VOLT_v2_OFFSET, 1, 1000,
		15625, -2000, fg_encode_voltage, NULL),
	PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000000,
		244141, 0, fg_encode_voltage, NULL),
	PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 3,
		1000000, 122070, 0, fg_encode_current, NULL),
	PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1,
		100000, 390625, 0, fg_encode_current, NULL),
	PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1,
		256, 100, 0, fg_encode_default, NULL),
		2048, 100, 0, fg_encode_default, NULL),
	PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD,
		RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default,
		NULL),
@@ -264,6 +274,12 @@ module_param_named(
	sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR
);

static bool fg_sram_dump;
module_param_named(
	sram_dump, fg_sram_dump, bool, S_IRUSR | S_IWUSR
);


/* All getters HERE */

static int fg_decode_value_16b(struct fg_sram_param *sp,
@@ -302,14 +318,14 @@ static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
}

static void fg_encode_voltage(struct fg_sram_param *sp,
				enum fg_sram_param_id  id, int val, u8 *buf)
				enum fg_sram_param_id  id, int val_mv, u8 *buf)
{
	int i, mask = 0xff;
	int64_t temp;

	val += sp[id].offset;
	temp = (int64_t)div_u64((u64)val * sp[id].numrtr, sp[id].denmtr);
	pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
	val_mv += sp[id].offset;
	temp = (int64_t)div_u64((u64)val_mv * sp[id].numrtr, sp[id].denmtr);
	pr_debug("temp: %llx id: %d, val_mv: %d, buf: [ ", temp, id, val_mv);
	for (i = 0; i < sp[id].len; i++) {
		buf[i] = temp & mask;
		temp >>= 8;
@@ -319,15 +335,15 @@ static void fg_encode_voltage(struct fg_sram_param *sp,
}

static void fg_encode_current(struct fg_sram_param *sp,
				enum fg_sram_param_id  id, int val, u8 *buf)
				enum fg_sram_param_id  id, int val_ma, u8 *buf)
{
	int i, mask = 0xff;
	int64_t temp;
	s64 current_ma;

	current_ma = val;
	current_ma = val_ma;
	temp = (int64_t)div_s64(current_ma * sp[id].numrtr, sp[id].denmtr);
	pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
	pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val_ma);
	for (i = 0; i < sp[id].len; i++) {
		buf[i] = temp & mask;
		temp >>= 8;
@@ -593,14 +609,12 @@ static int fg_get_batt_id(struct fg_chip *chip, int *val)
		return rc;
	}

	chip->batt_id_avail = true;
	fg_dbg(chip, FG_STATUS, "batt_id: %d\n", batt_id);

	*val = batt_id;
	return 0;
}

#define PROFILE_LEN			224
static int fg_get_batt_profile(struct fg_chip *chip)
{
	struct device_node *node = chip->dev->of_node;
@@ -614,13 +628,14 @@ static int fg_get_batt_profile(struct fg_chip *chip)
		return rc;
	}

	batt_id /= 1000;
	chip->batt_id = batt_id;
	batt_node = of_find_node_by_name(node, "qcom,battery-data");
	if (!batt_node) {
		pr_err("Batterydata not available\n");
		return -ENXIO;
	}

	batt_id /= 1000;
	profile_node = of_batterydata_get_best_profile(batt_node, batt_id,
				NULL);
	if (IS_ERR(profile_node))
@@ -652,6 +667,13 @@ static int fg_get_batt_profile(struct fg_chip *chip)
		chip->bp.fastchg_curr_ma = -EINVAL;
	}

	rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
			&chip->bp.vbatt_full_mv);
	if (rc < 0) {
		pr_err("battery cc_cv threshold unavailable, rc:%d\n", rc);
		chip->bp.vbatt_full_mv = -EINVAL;
	}

	data = of_get_property(profile_node, "qcom,fg-profile-data", &len);
	if (!data) {
		pr_err("No profile data available\n");
@@ -663,6 +685,7 @@ static int fg_get_batt_profile(struct fg_chip *chip)
		return -EINVAL;
	}

	chip->profile_available = true;
	memcpy(chip->batt_profile, data, len);
	return 0;
}
@@ -912,47 +935,83 @@ static int fg_get_cycle_count(struct fg_chip *chip)
	return count;
}

#define PROFILE_COMP_LEN		32
#define SOC_READY_WAIT_MS		2000
static void profile_load_work(struct work_struct *work)
static void dump_sram(u8 *buf, int len)
{
	struct fg_chip *chip = container_of(work,
				struct fg_chip,
				profile_load_work.work);
	int rc;
	u8 buf[PROFILE_COMP_LEN], val;
	bool tried_again = false, profiles_same = false;
	int i;
	char str[16];

	if (!chip->batt_id_avail) {
		pr_err("batt_id not available\n");
		return;
	for (i = 0; i < len; i += 4) {
		str[0] = '\0';
		fill_string(str, sizeof(str), buf + i, 4);
		pr_info("%03d %s\n", PROFILE_LOAD_WORD + (i / 4), str);
	}
}

static bool is_profile_load_required(struct fg_chip *chip)
{
	u8 buf[PROFILE_COMP_LEN], val;
	bool profiles_same = false;
	int rc;

	rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
			PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
	if (rc < 0) {
		pr_err("failed to read profile integrity rc=%d\n", rc);
		return;
		return false;
	}

	vote(chip->awake_votable, PROFILE_LOAD, true, 0);
	/* Check if integrity bit is set */
	if (val == 0x01) {
		fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
		rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
				buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
		if (rc < 0) {
			pr_err("Error in reading battery profile, rc:%d\n", rc);
			goto out;
			return false;
		}
		profiles_same = memcmp(chip->batt_profile, buf,
					PROFILE_COMP_LEN) == 0;
		if (profiles_same) {
			fg_dbg(chip, FG_STATUS, "Battery profile is same\n");
			goto done;
			fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
			return false;
		}
		fg_dbg(chip, FG_STATUS, "profiles are different?\n");

		if (!chip->dt.force_load_profile) {
			pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
			if (fg_sram_dump) {
				pr_info("FG: loaded profile:\n");
				dump_sram(buf, PROFILE_COMP_LEN);
				pr_info("FG: available profile:\n");
				dump_sram(chip->batt_profile, PROFILE_LEN);
			}
			return false;
		}

		fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
	} else {
		fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
		if (fg_sram_dump) {
			pr_info("FG: profile to be loaded:\n");
			dump_sram(chip->batt_profile, PROFILE_LEN);
		}
	}
	return true;
}

#define SOC_READY_WAIT_MS		2000
static void profile_load_work(struct work_struct *work)
{
	struct fg_chip *chip = container_of(work,
				struct fg_chip,
				profile_load_work.work);
	bool tried_again = false;
	u8 buf[2], val;
	int rc;

	vote(chip->awake_votable, PROFILE_LOAD, true, 0);
	if (!is_profile_load_required(chip))
		goto done;

	clear_cycle_counter(chip);
	fg_dbg(chip, FG_STATUS, "profile loading started\n");
	rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0);
@@ -1182,6 +1241,32 @@ static int fg_hw_init(struct fg_chip *chip)
		return rc;
	}

	/* This SRAM register is only present in v2.0 */
	if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4 &&
		chip->bp.float_volt_uv > 0) {
		fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT,
			chip->bp.float_volt_uv / 1000, buf);
		rc = fg_sram_write(chip, chip->sp[FG_SRAM_FLOAT_VOLT].addr_word,
			chip->sp[FG_SRAM_FLOAT_VOLT].addr_byte, buf,
			chip->sp[FG_SRAM_FLOAT_VOLT].len, FG_IMA_DEFAULT);
		if (rc < 0) {
			pr_err("Error in writing float_volt, rc=%d\n", rc);
			return rc;
		}
	}

	if (chip->bp.vbatt_full_mv > 0) {
		fg_encode(chip->sp, FG_SRAM_VBATT_FULL, chip->bp.vbatt_full_mv,
			buf);
		rc = fg_sram_write(chip, chip->sp[FG_SRAM_VBATT_FULL].addr_word,
			chip->sp[FG_SRAM_VBATT_FULL].addr_byte, buf,
			chip->sp[FG_SRAM_VBATT_FULL].len, FG_IMA_DEFAULT);
		if (rc < 0) {
			pr_err("Error in writing vbatt_full, rc=%d\n", rc);
			return rc;
		}
	}

	fg_encode(chip->sp, FG_SRAM_CHG_TERM_CURR, chip->dt.chg_term_curr_ma,
		buf);
	rc = fg_sram_write(chip, chip->sp[FG_SRAM_CHG_TERM_CURR].addr_word,
@@ -1311,28 +1396,6 @@ static int fg_memif_init(struct fg_chip *chip)
	return fg_ima_init(chip);
}

static int fg_batt_profile_init(struct fg_chip *chip)
{
	int rc;

	if (!chip->batt_profile) {
		chip->batt_profile = devm_kcalloc(chip->dev, PROFILE_LEN,
						sizeof(*chip->batt_profile),
						GFP_KERNEL);
		if (!chip->batt_profile)
			return -ENOMEM;
	}

	rc = fg_get_batt_profile(chip);
	if (rc < 0) {
		pr_err("Error in getting battery profile, rc:%d\n", rc);
		return rc;
	}

	schedule_delayed_work(&chip->profile_load_work, msecs_to_jiffies(0));
	return 0;
}

/* INTERRUPT HANDLERS STAY HERE */

static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
@@ -1360,16 +1423,16 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
	chip->battery_missing = (status & BT_MISS_BIT);

	if (chip->battery_missing) {
		chip->batt_id_avail = false;
		chip->profile_available = false;
		chip->profile_loaded = false;
		clear_cycle_counter(chip);
	} else {
		rc = fg_batt_profile_init(chip);
		rc = fg_get_batt_profile(chip);
		if (rc < 0) {
			pr_err("Error in initializing battery profile, rc=%d\n",
				rc);
			pr_err("Error in getting battery profile, rc:%d\n", rc);
			return IRQ_HANDLED;
		}
		schedule_delayed_work(&chip->profile_load_work, 0);
	}

	return IRQ_HANDLED;
@@ -1445,39 +1508,78 @@ static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
	/* BATT_SOC irqs */
	[MSOC_FULL_IRQ] = {
		"msoc-full", fg_soc_irq_handler, true },
		.name		= "msoc-full",
		.handler	= fg_soc_irq_handler,
	},
	[MSOC_HIGH_IRQ] = {
		"msoc-high", fg_soc_irq_handler, true },
		.name		= "msoc-high",
		.handler	= fg_soc_irq_handler,
		.wakeable	= true,
	},
	[MSOC_EMPTY_IRQ] = {
		"msoc-empty", fg_empty_soc_irq_handler, true },
		.name		= "msoc-empty",
		.handler	= fg_empty_soc_irq_handler,
		.wakeable	= true,
	},
	[MSOC_LOW_IRQ] = {
		"msoc-low", fg_soc_irq_handler },
		.name		= "msoc-low",
		.handler	= fg_soc_irq_handler,
		.wakeable	= true,
	},
	[MSOC_DELTA_IRQ] = {
		"msoc-delta", fg_delta_soc_irq_handler, true },
		.name		= "msoc-delta",
		.handler	= fg_delta_soc_irq_handler,
		.wakeable	= true,
	},
	[BSOC_DELTA_IRQ] = {
		"bsoc-delta", fg_delta_soc_irq_handler, true },
		.name		= "bsoc-delta",
		.handler	= fg_dummy_irq_handler,
	},
	[SOC_READY_IRQ] = {
		"soc-ready", fg_first_est_irq_handler, true },
		.name		= "soc-ready",
		.handler	= fg_first_est_irq_handler,
		.wakeable	= true,
	},
	[SOC_UPDATE_IRQ] = {
		"soc-update", fg_soc_update_irq_handler },
		.name		= "soc-update",
		.handler	= fg_soc_update_irq_handler,
	},
	/* BATT_INFO irqs */
	[BATT_TEMP_DELTA_IRQ] = {
		"batt-temp-delta", fg_delta_batt_temp_irq_handler },
		.name		= "batt-temp-delta",
		.handler	= fg_delta_batt_temp_irq_handler,
	},
	[BATT_MISSING_IRQ] = {
		"batt-missing", fg_batt_missing_irq_handler, true },
		.name		= "batt-missing",
		.handler	= fg_batt_missing_irq_handler,
		.wakeable	= true,
	},
	[ESR_DELTA_IRQ] = {
		"esr-delta", fg_dummy_irq_handler },
		.name		= "esr-delta",
		.handler	= fg_dummy_irq_handler,
	},
	[VBATT_LOW_IRQ] = {
		"vbatt-low", fg_vbatt_low_irq_handler, true },
		.name		= "vbatt-low",
		.handler	= fg_vbatt_low_irq_handler,
		.wakeable	= true,
	},
	[VBATT_PRED_DELTA_IRQ] = {
		"vbatt-pred-delta", fg_dummy_irq_handler },
		.name		= "vbatt-pred-delta",
		.handler	= fg_dummy_irq_handler,
	},
	/* MEM_IF irqs */
	[DMA_GRANT_IRQ] = {
		"dma-grant", fg_dummy_irq_handler },
		.name		= "dma-grant",
		.handler	= fg_dummy_irq_handler,
	},
	[MEM_XCP_IRQ] = {
		"mem-xcp", fg_dummy_irq_handler },
		.name		= "mem-xcp",
		.handler	= fg_dummy_irq_handler,
	},
	[IMA_RDY_IRQ] = {
		"ima-rdy", fg_dummy_irq_handler },
		.name		= "ima-rdy",
		.handler	= fg_dummy_irq_handler,
	},
};

static int fg_get_irq_index_byname(const char *name)
@@ -1638,6 +1740,11 @@ static int fg_parse_dt(struct fg_chip *chip)
		}
	}

	rc = fg_get_batt_profile(chip);
	if (rc < 0)
		pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
			chip->batt_id, rc);

	/* Read all the optional properties below */
	rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
	if (rc < 0)
@@ -1724,6 +1831,9 @@ static int fg_parse_dt(struct fg_chip *chip)
	if (chip->cyc_ctr.en)
		chip->cyc_ctr.id = 1;

	chip->dt.force_load_profile = of_property_read_bool(node,
					"qcom,fg-force-load-profile");

	return 0;
}

@@ -1836,10 +1946,8 @@ static int fg_gen3_probe(struct platform_device *pdev)
		goto exit;
	}

	rc = fg_batt_profile_init(chip);
	if (rc < 0)
		dev_warn(chip->dev, "Error in initializing battery profile, rc:%d\n",
			rc);
	if (chip->profile_available)
		schedule_delayed_work(&chip->profile_load_work, 0);

	device_init_wakeup(chip->dev, true);
	pr_debug("FG GEN3 driver successfully probed\n");