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

Commit 6ac85714 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-smbcharger: update SMBCHG restart workaround"

parents af3795d2 f7bb6acc
Loading
Loading
Loading
Loading
+148 −61
Original line number Original line Diff line number Diff line
@@ -352,6 +352,7 @@ enum wake_reason {
#define WEAK_CHARGER_ICL_VOTER	"WEAK_CHARGER_ICL_VOTER"
#define WEAK_CHARGER_ICL_VOTER	"WEAK_CHARGER_ICL_VOTER"
#define SW_AICL_ICL_VOTER	"SW_AICL_ICL_VOTER"
#define SW_AICL_ICL_VOTER	"SW_AICL_ICL_VOTER"
#define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER"
#define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER"
#define SHUTDOWN_WORKAROUND_ICL_VOTER "SHUTDOWN_WORKAROUND_ICL_VOTER"


/* USB SUSPEND VOTERS */
/* USB SUSPEND VOTERS */
/* userspace has suspended charging altogether */
/* userspace has suspended charging altogether */
@@ -1061,6 +1062,33 @@ static int get_prop_batt_current_now(struct smbchg_chip *chip)
	return ua;
	return ua;
}
}


#define DEFAULT_BATT_RESISTANCE_ID	0
static int get_prop_batt_resistance_id(struct smbchg_chip *chip)
{
	int rbatt, rc;

	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE_ID,
			&rbatt);
	if (rc) {
		pr_smb(PR_STATUS, "Couldn't get resistance id rc = %d\n", rc);
		rbatt = DEFAULT_BATT_RESISTANCE_ID;
	}
	return rbatt;
}

#define DEFAULT_BATT_FULL_CHG_CAPACITY	0
static int get_prop_batt_full_charge(struct smbchg_chip *chip)
{
	int bfc, rc;

	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CHARGE_FULL, &bfc);
	if (rc) {
		pr_smb(PR_STATUS, "Couldn't get charge_full rc = %d\n", rc);
		bfc = DEFAULT_BATT_FULL_CHG_CAPACITY;
	}
	return bfc;
}

#define DEFAULT_BATT_VOLTAGE_NOW	0
#define DEFAULT_BATT_VOLTAGE_NOW	0
static int get_prop_batt_voltage_now(struct smbchg_chip *chip)
static int get_prop_batt_voltage_now(struct smbchg_chip *chip)
{
{
@@ -1876,6 +1904,7 @@ static int smbchg_sw_esr_pulse_en(struct smbchg_chip *chip, bool en)
		return 0;
		return 0;
	}
	}


	fg_current_now = abs(fg_current_now) / 1000;
	icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA,
	icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA,
				fg_current_now - ESR_PULSE_CURRENT_DELTA_MA);
				fg_current_now - ESR_PULSE_CURRENT_DELTA_MA);
	rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma);
	rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma);
@@ -4013,11 +4042,11 @@ static void smbchg_chg_led_blink_set(struct smbchg_chip *chip,
		reg = CHG_LED_OFF << CHG_LED_SHIFT;
		reg = CHG_LED_OFF << CHG_LED_SHIFT;
	} else {
	} else {
		if (blinking == 1)
		if (blinking == 1)
			reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT;
		else if (blinking == 2)
			reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT;
			reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT;
		else
		else if (blinking == 2)
			reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT;
			reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT;
		else
			reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT;
	}
	}


	rc = smbchg_sec_masked_write(chip,
	rc = smbchg_sec_masked_write(chip,
@@ -4410,6 +4439,20 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,
	if (type == POWER_SUPPLY_TYPE_UNKNOWN)
	if (type == POWER_SUPPLY_TYPE_UNKNOWN)
		chip->usb_supply_type = type;
		chip->usb_supply_type = type;


	/*
	 * Update TYPE property to DCP for HVDCP/HVDCP3 charger types
	 * so that they can be recongized as AC chargers by healthd.
	 * Don't report UNKNOWN charger type to prevent healthd missing
	 * detecting this power_supply status change.
	 */
	if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3
			|| chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP)
		chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB_DCP;
	else if (chip->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN)
		chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB;
	else
		chip->usb_psy_d.type = chip->usb_supply_type;

	if (!chip->skip_usb_notification)
	if (!chip->skip_usb_notification)
		power_supply_changed(chip->usb_psy);
		power_supply_changed(chip->usb_psy);


@@ -4602,6 +4645,8 @@ static void handle_usb_removal(struct smbchg_chip *chip)
	/* Clear typec current status */
	/* Clear typec current status */
	if (chip->typec_psy)
	if (chip->typec_psy)
		chip->typec_current_ma = 0;
		chip->typec_current_ma = 0;
	/* cancel/wait for hvdcp pending work if any */
	cancel_delayed_work_sync(&chip->hvdcp_det_work);
	smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
	smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
	extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
	extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
	if (chip->dpdm_reg)
	if (chip->dpdm_reg)
@@ -5226,6 +5271,15 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip)
	 */
	 */
	chip->parallel.enabled_once = false;
	chip->parallel.enabled_once = false;


	/* Enable AICL */
	pr_smb(PR_MISC, "Enable AICL\n");
	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
			AICL_EN_BIT, AICL_EN_BIT);
	if (rc < 0) {
		pr_err("Couldn't enable AICL rc=%d\n", rc);
		goto out;
	}

	/* fake an insertion */
	/* fake an insertion */
	pr_smb(PR_MISC, "Faking Insertion\n");
	pr_smb(PR_MISC, "Faking Insertion\n");
	rc = fake_insertion_removal(chip, true);
	rc = fake_insertion_removal(chip, true);
@@ -5235,15 +5289,6 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip)
	}
	}
	chip->hvdcp_3_det_ignore_uv = false;
	chip->hvdcp_3_det_ignore_uv = false;


	/* Enable AICL */
	pr_smb(PR_MISC, "Enable AICL\n");
	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
			AICL_EN_BIT, 0);
	if (rc < 0) {
		pr_err("Couldn't enable AICL rc=%d\n", rc);
		return rc;
	}

out:
out:
	/*
	/*
	 * There are many QC 2.0 chargers that collapse before the aicl deglitch
	 * There are many QC 2.0 chargers that collapse before the aicl deglitch
@@ -5276,49 +5321,63 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip)
#define APSD_RERUN		BIT(0)
#define APSD_RERUN		BIT(0)
static int rerun_apsd(struct smbchg_chip *chip)
static int rerun_apsd(struct smbchg_chip *chip)
{
{
	int rc;
	int rc = 0;

	chip->hvdcp_3_det_ignore_uv = true;


	if (chip->schg_version == QPNP_SCHG_LITE) {
		pr_smb(PR_STATUS, "Re-running APSD\n");
		reinit_completion(&chip->src_det_raised);
		reinit_completion(&chip->src_det_raised);
		reinit_completion(&chip->usbin_uv_lowered);
		reinit_completion(&chip->usbin_uv_lowered);
		reinit_completion(&chip->src_det_lowered);
		reinit_completion(&chip->src_det_lowered);
		reinit_completion(&chip->usbin_uv_raised);
		reinit_completion(&chip->usbin_uv_raised);


		/* re-run APSD */
		/* re-run APSD */
	rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD,
		rc = smbchg_masked_write(chip,
				chip->usb_chgpth_base + USB_CMD_APSD,
				APSD_RERUN, APSD_RERUN);
				APSD_RERUN, APSD_RERUN);
		if (rc) {
		if (rc) {
			pr_err("Couldn't re-run APSD rc=%d\n", rc);
			pr_err("Couldn't re-run APSD rc=%d\n", rc);
		return rc;
			goto out;
		}
		}


		pr_smb(PR_MISC, "Waiting on rising usbin uv\n");
		pr_smb(PR_MISC, "Waiting on rising usbin uv\n");
		rc = wait_for_usbin_uv(chip, true);
		rc = wait_for_usbin_uv(chip, true);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("wait for usbin uv failed rc = %d\n", rc);
			pr_err("wait for usbin uv failed rc = %d\n", rc);
		return rc;
			goto out;
		}
		}


		pr_smb(PR_MISC, "Waiting on falling src det\n");
		pr_smb(PR_MISC, "Waiting on falling src det\n");
		rc = wait_for_src_detect(chip, false);
		rc = wait_for_src_detect(chip, false);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("wait for src detect failed rc = %d\n", rc);
			pr_err("wait for src detect failed rc = %d\n", rc);
		return rc;
			goto out;
		}
		}


		pr_smb(PR_MISC, "Waiting on falling usbin uv\n");
		pr_smb(PR_MISC, "Waiting on falling usbin uv\n");
		rc = wait_for_usbin_uv(chip, false);
		rc = wait_for_usbin_uv(chip, false);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("wait for usbin uv failed rc = %d\n", rc);
			pr_err("wait for usbin uv failed rc = %d\n", rc);
		return rc;
			goto out;
		}
		}


		pr_smb(PR_MISC, "Waiting on rising src det\n");
		pr_smb(PR_MISC, "Waiting on rising src det\n");
		rc = wait_for_src_detect(chip, true);
		rc = wait_for_src_detect(chip, true);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("wait for src detect failed rc = %d\n", rc);
			pr_err("wait for src detect failed rc = %d\n", rc);
		return rc;
			goto out;
		}
	} else {
		pr_smb(PR_STATUS, "Faking Removal\n");
		rc = fake_insertion_removal(chip, false);
		msleep(500);
		pr_smb(PR_STATUS, "Faking Insertion\n");
		rc = fake_insertion_removal(chip, true);
	}
	}


out:
	chip->hvdcp_3_det_ignore_uv = false;
	return rc;
	return rc;
}
}


@@ -5395,8 +5454,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip)
	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
			AICL_EN_BIT, 0);
			AICL_EN_BIT, 0);


	chip->hvdcp_3_det_ignore_uv = true;

	/* re-run APSD */
	/* re-run APSD */
	rc = rerun_apsd(chip);
	rc = rerun_apsd(chip);
	if (rc) {
	if (rc) {
@@ -5404,8 +5461,6 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip)
		goto out;
		goto out;
	}
	}


	chip->hvdcp_3_det_ignore_uv = false;

	pr_smb(PR_MISC, "Enable AICL\n");
	pr_smb(PR_MISC, "Enable AICL\n");
	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
			AICL_EN_BIT, AICL_EN_BIT);
			AICL_EN_BIT, AICL_EN_BIT);
@@ -5434,6 +5489,10 @@ static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip)
out:
out:
	chip->hvdcp_3_det_ignore_uv = false;
	chip->hvdcp_3_det_ignore_uv = false;
	restore_from_hvdcp_detection(chip);
	restore_from_hvdcp_detection(chip);
	if (!is_src_detect_high(chip)) {
		pr_smb(PR_MISC, "HVDCP removed - force removal\n");
		update_usb_status(chip, 0, true);
	}
	return rc;
	return rc;
}
}


@@ -5453,6 +5512,10 @@ static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip)
	if (rc < 0)
	if (rc < 0)
		pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc);
		pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc);


	if (!is_src_detect_high(chip)) {
		pr_smb(PR_MISC, "HVDCP removed\n");
		update_usb_status(chip, 0, 0);
	}
	smbchg_handle_hvdcp3_disable(chip);
	smbchg_handle_hvdcp3_disable(chip);


	return rc;
	return rc;
@@ -5631,6 +5694,9 @@ static int smbchg_usb_get_property(struct power_supply *psy,
		val->intval = chip->usb_online;
		val->intval = chip->usb_online;
		break;
		break;
	case POWER_SUPPLY_PROP_TYPE:
	case POWER_SUPPLY_PROP_TYPE:
		val->intval = chip->usb_psy_d.type;
		break;
	case POWER_SUPPLY_PROP_REAL_TYPE:
		val->intval = chip->usb_supply_type;
		val->intval = chip->usb_supply_type;
		break;
		break;
	case POWER_SUPPLY_PROP_HEALTH:
	case POWER_SUPPLY_PROP_HEALTH:
@@ -5688,6 +5754,7 @@ static enum power_supply_property smbchg_usb_properties[] = {
	POWER_SUPPLY_PROP_ONLINE,
	POWER_SUPPLY_PROP_ONLINE,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_TYPE,
	POWER_SUPPLY_PROP_TYPE,
	POWER_SUPPLY_PROP_REAL_TYPE,
	POWER_SUPPLY_PROP_HEALTH,
	POWER_SUPPLY_PROP_HEALTH,
};
};


@@ -5733,6 +5800,8 @@ static enum power_supply_property smbchg_battery_properties[] = {
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_RESISTANCE_ID,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE,
	POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE,
	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
@@ -5924,6 +5993,12 @@ static int smbchg_battery_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
		val->intval = get_prop_batt_voltage_now(chip);
		val->intval = get_prop_batt_voltage_now(chip);
		break;
		break;
	case POWER_SUPPLY_PROP_RESISTANCE_ID:
		val->intval = get_prop_batt_resistance_id(chip);
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL:
		val->intval = get_prop_batt_full_charge(chip);
		break;
	case POWER_SUPPLY_PROP_TEMP:
	case POWER_SUPPLY_PROP_TEMP:
		val->intval = get_prop_batt_temp(chip);
		val->intval = get_prop_batt_temp(chip);
		break;
		break;
@@ -7968,20 +8043,18 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip)
			pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n",
			pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n",
					rc);
					rc);


		pr_smb(PR_STATUS, "Faking Removal\n");
		rc = rerun_apsd(chip);
		fake_insertion_removal(chip, false);
		if (rc)
		msleep(500);
			pr_err("APSD rerun failed rc=%d\n", rc);
		pr_smb(PR_STATUS, "Faking Insertion\n");
		fake_insertion_removal(chip, true);


		read_usb_type(chip, &usb_type_name, &usb_supply_type);
		read_usb_type(chip, &usb_type_name, &usb_supply_type);
		if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) {
		if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) {
			msleep(500);
			msleep(500);
			pr_smb(PR_STATUS, "Fake Removal again as type!=DCP\n");
			pr_smb(PR_STATUS, "Rerun APSD as type !=DCP\n");
			fake_insertion_removal(chip, false);

			msleep(500);
			rc = rerun_apsd(chip);
			pr_smb(PR_STATUS, "Fake Insert again as type!=DCP\n");
			if (rc)
			fake_insertion_removal(chip, true);
				pr_err("APSD rerun failed rc=%d\n", rc);
		}
		}


		rc = vote(chip->usb_icl_votable,
		rc = vote(chip->usb_icl_votable,
@@ -7989,6 +8062,14 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip)
		if (rc < 0)
		if (rc < 0)
			pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n",
			pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n",
					rc);
					rc);

		/* Schedule work for HVDCP detection */
		if (!chip->hvdcp_not_supported) {
			cancel_delayed_work_sync(&chip->hvdcp_det_work);
			smbchg_stay_awake(chip, PM_DETECT_HVDCP);
			schedule_delayed_work(&chip->hvdcp_det_work,
					msecs_to_jiffies(HVDCP_NOTIFY_MS));
		}
	}
	}
}
}


@@ -8385,6 +8466,12 @@ static void smbchg_shutdown(struct platform_device *pdev)
	if (!is_hvdcp_present(chip))
	if (!is_hvdcp_present(chip))
		return;
		return;


	pr_smb(PR_MISC, "Reducing to 500mA\n");
	rc = vote(chip->usb_icl_votable, SHUTDOWN_WORKAROUND_ICL_VOTER, true,
			500);
	if (rc < 0)
		pr_err("Couldn't vote 500mA ICL\n");

	pr_smb(PR_MISC, "Disable Parallel\n");
	pr_smb(PR_MISC, "Disable Parallel\n");
	mutex_lock(&chip->parallel.lock);
	mutex_lock(&chip->parallel.lock);
	smbchg_parallel_en = 0;
	smbchg_parallel_en = 0;