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

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

Merge "power: qpnp-fg: validate cc_soc in case of a FG lockup"

parents 9c532ebe ec7e8b08
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -271,6 +271,8 @@ Parent node optional properties:
					will be notified to userspace. If this
					limit is not specified, then the
					default limit would be 150C.
- qcom,fg-cc-soc-limit-pct:		Percentage of CC_SOC before resetting
					FG and restore the full CC_SOC value.

qcom,fg-soc node required properties:
- reg : offset and length of the PMIC peripheral register map.
+80 −2
Original line number Diff line number Diff line
@@ -592,9 +592,16 @@ struct fg_chip {
	bool			irqs_enabled;
	bool			use_last_soc;
	int			last_soc;
	/* Validating temperature */
	int			last_good_temp;
	int			batt_temp_low_limit;
	int			batt_temp_high_limit;
	/* Validating CC_SOC */
	struct work_struct	cc_soc_store_work;
	struct fg_wakeup_source	cc_soc_wakeup_source;
	int			cc_soc_limit_pct;
	bool			use_last_cc_soc;
	int64_t			last_cc_soc;
};

/* FG_MEMIF DEBUGFS structures */
@@ -1334,6 +1341,7 @@ static void fg_check_ima_error_handling(struct fg_chip *chip)
	}
	mutex_lock(&chip->ima_recovery_lock);
	fg_enable_irqs(chip, false);
	chip->use_last_cc_soc = true;
	chip->ima_error_handling = true;
	if (!work_pending(&chip->ima_error_recovery_work))
		schedule_work(&chip->ima_error_recovery_work);
@@ -2499,10 +2507,15 @@ static int update_sram_data(struct fg_chip *chip, int *resched_ms)
				pr_err("Couldn't save sram registers\n");
				goto out;
			}
			if (!chip->use_last_soc)
			if (!chip->use_last_soc) {
				chip->last_soc = get_monotonic_soc_raw(chip);
				chip->last_cc_soc = div64_s64(
					(int64_t)chip->last_soc *
					FULL_PERCENT_28BIT, FULL_SOC_RAW);
			}
			if (fg_debug_mask & FG_STATUS)
				pr_info("last_soc: %d\n", chip->last_soc);
				pr_info("last_soc: %d last_cc_soc: %lld\n",
					chip->last_soc, chip->last_cc_soc);
		} else {
			pr_err("update_sram failed\n");
			goto out;
@@ -4431,6 +4444,37 @@ done:
	fg_relax(&chip->gain_comp_wakeup_source);
}

static void cc_soc_store_work(struct work_struct *work)
{
	struct fg_chip *chip = container_of(work, struct fg_chip,
					cc_soc_store_work);
	int cc_soc_pct;

	if (!chip->nom_cap_uah) {
		pr_err("nom_cap_uah zero!\n");
		fg_relax(&chip->cc_soc_wakeup_source);
		return;
	}

	cc_soc_pct = get_sram_prop_now(chip, FG_DATA_CC_CHARGE);
	cc_soc_pct = div64_s64(cc_soc_pct * 100,
				chip->nom_cap_uah);
	chip->last_cc_soc = div64_s64((int64_t)chip->last_soc *
				FULL_PERCENT_28BIT, FULL_SOC_RAW);

	if (fg_debug_mask & FG_STATUS)
		pr_info("cc_soc_pct: %d last_cc_soc: %lld\n", cc_soc_pct,
			chip->last_cc_soc);

	if (fg_reset_on_lockup && (chip->cc_soc_limit_pct > 0 &&
			cc_soc_pct >= chip->cc_soc_limit_pct)) {
		pr_err("CC_SOC out of range\n");
		fg_check_ima_error_handling(chip);
	}

	fg_relax(&chip->cc_soc_wakeup_source);
}

#define SOC_FIRST_EST_DONE	BIT(5)
static bool is_first_est_done(struct fg_chip *chip)
{
@@ -4591,6 +4635,9 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *_chip)
			chip->last_soc = get_monotonic_soc_raw(chip);
		if (fg_debug_mask & FG_STATUS)
			pr_info("last_soc: %d\n", chip->last_soc);

		fg_stay_awake(&chip->cc_soc_wakeup_source);
		schedule_work(&chip->cc_soc_store_work);
	}

	if (chip->use_vbat_low_empty_soc) {
@@ -6445,6 +6492,11 @@ static int fg_of_init(struct fg_chip *chip)
		pr_info("batt-temp-low_limit: %d batt-temp-high_limit: %d\n",
			chip->batt_temp_low_limit, chip->batt_temp_high_limit);

	OF_READ_PROPERTY(chip->cc_soc_limit_pct, "fg-cc-soc-limit-pct", rc, 0);

	if (fg_debug_mask & FG_STATUS)
		pr_info("cc-soc-limit-pct: %d\n", chip->cc_soc_limit_pct);

	return rc;
}

@@ -6664,6 +6716,7 @@ static void fg_cancel_all_works(struct fg_chip *chip)
	cancel_work_sync(&chip->esr_extract_config_work);
	cancel_work_sync(&chip->slope_limiter_work);
	cancel_work_sync(&chip->dischg_gain_work);
	cancel_work_sync(&chip->cc_soc_store_work);
}

static void fg_cleanup(struct fg_chip *chip)
@@ -6688,6 +6741,7 @@ static void fg_cleanup(struct fg_chip *chip)
	wakeup_source_trash(&chip->slope_limit_wakeup_source.source);
	wakeup_source_trash(&chip->dischg_gain_wakeup_source.source);
	wakeup_source_trash(&chip->fg_reset_wakeup_source.source);
	wakeup_source_trash(&chip->cc_soc_wakeup_source.source);
}

static int fg_remove(struct spmi_device *spmi)
@@ -7491,6 +7545,25 @@ static int fg_init_iadc_config(struct fg_chip *chip)
	return 0;
}

static void fg_restore_cc_soc(struct fg_chip *chip)
{
	int rc;

	if (!chip->use_last_cc_soc || !chip->last_cc_soc)
		return;

	if (fg_debug_mask & FG_STATUS)
		pr_info("Restoring cc_soc: %lld\n", chip->last_cc_soc);

	rc = fg_mem_write(chip, (u8 *)&chip->last_cc_soc,
			fg_data[FG_DATA_CC_CHARGE].address, 4,
			fg_data[FG_DATA_CC_CHARGE].offset, 0);
	if (rc)
		pr_err("failed to update CC_SOC rc=%d\n", rc);
	else
		chip->use_last_cc_soc = false;
}

static void fg_restore_soc(struct fg_chip *chip)
{
	int rc;
@@ -7650,6 +7723,7 @@ wait:
		pr_info("IMA error recovery done...\n");
out:
	fg_restore_soc(chip);
	fg_restore_cc_soc(chip);
	fg_enable_irqs(chip, true);
	update_sram_data_work(&chip->update_sram_data.work);
	update_temp_data(&chip->update_temp_work.work);
@@ -7859,6 +7933,8 @@ static int fg_probe(struct spmi_device *spmi)
			"qpnp_fg_dischg_gain");
	wakeup_source_init(&chip->fg_reset_wakeup_source.source,
			"qpnp_fg_reset");
	wakeup_source_init(&chip->cc_soc_wakeup_source.source,
			"qpnp_fg_cc_soc");
	spin_lock_init(&chip->sec_access_lock);
	mutex_init(&chip->rw_lock);
	mutex_init(&chip->cyc_ctr.lock);
@@ -7888,6 +7964,7 @@ static int fg_probe(struct spmi_device *spmi)
	INIT_WORK(&chip->esr_extract_config_work, esr_extract_config_work);
	INIT_WORK(&chip->slope_limiter_work, slope_limiter_work);
	INIT_WORK(&chip->dischg_gain_work, discharge_gain_work);
	INIT_WORK(&chip->cc_soc_store_work, cc_soc_store_work);
	alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME,
			fg_cap_learning_alarm_cb);
	init_completion(&chip->sram_access_granted);
@@ -8061,6 +8138,7 @@ of_init_fail:
	wakeup_source_trash(&chip->slope_limit_wakeup_source.source);
	wakeup_source_trash(&chip->dischg_gain_wakeup_source.source);
	wakeup_source_trash(&chip->fg_reset_wakeup_source.source);
	wakeup_source_trash(&chip->cc_soc_wakeup_source.source);
	return rc;
}