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

Commit 7bea04c2 authored by Ashay Jaiswal's avatar Ashay Jaiswal Committed by Vamshi Krishna B V
Browse files

power: qpnp-smbcharger: add voting logic for enabling/disabling HVDCP



HVDCP can be enabled from multiple location in the charger driver. Update
HVDCP enable/disable logic to use voting mechanism.

Also optimize shutdown() hook and Fix ICL voting on USB removal,
update usb status after APSD re-reun, release hvdcp wakelock when usb
removed and enable parallel charger only if charger is present.

CRs-Fixed: 1050520
Change-Id: Ifa42d0d13a10ce803d5ce19e59659d56d0c92f43
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: default avatarVamshi Krishna B V <vbv@codeaurora.org>
parent b27bf012
Loading
Loading
Loading
Loading
+70 −25
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ struct smbchg_chip {
	struct votable			*hw_aicl_rerun_disable_votable;
	struct votable			*hw_aicl_rerun_enable_indirect_votable;
	struct votable			*aicl_deglitch_short_votable;

	struct votable			*hvdcp_enable_votable;
	/* extcon for VBUS / ID notification to USB */
	struct extcon_dev		*extcon;
};
@@ -413,6 +413,10 @@ enum wake_reason {
					"VARB_WRKARND_SHORT_DEGLITCH_VOTER"
/* QC 2.0 */
#define HVDCP_SHORT_DEGLITCH_VOTER	"HVDCP_SHORT_DEGLITCH_VOTER"
/* Hvdcp enable voters*/
#define HVDCP_PMIC_VOTER	"HVDCP_PMIC_VOTER"
#define HVDCP_OTG_VOTER		"HVDCP_OTG_VOTER"
#define HVDCP_PULSING_VOTER	"HVDCP_PULSING_VOTER"

static const unsigned int smbchg_extcon_cable[] = {
	EXTCON_USB,
@@ -2435,6 +2439,27 @@ static int dc_suspend_vote_cb(struct votable *votable,
	return rc;
}

#define HVDCP_EN_BIT	BIT(3)
static int smbchg_hvdcp_enable_cb(struct votable *votable,
						void *data,
						int enable,
						const char *client)
{
	int rc = 0;
	struct smbchg_chip *chip = data;

	pr_err("smbchg_hvdcp_enable_cb HVDCP %s\n",
			enable ? "enabled" : "disabled");
	rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_EN_BIT, enable ? HVDCP_EN_BIT : 0);
	if (rc < 0)
		dev_err(chip->dev, "Couldn't %s HVDCP rc=%d\n",
				enable ? "enable" : "disable", rc);

	return rc;
}

static int set_fastchg_current_vote_cb(struct votable *votable,
						void *data,
						int fcc_ma,
@@ -3795,7 +3820,6 @@ struct regulator_ops smbchg_otg_reg_ops = {
#define USBIN_ADAPTER_9V		0x3
#define USBIN_ADAPTER_5V_9V_CONT	0x2
#define USBIN_ADAPTER_5V_UNREGULATED_9V	0x5
#define HVDCP_EN_BIT			BIT(3)
static int smbchg_external_otg_regulator_enable(struct regulator_dev *rdev)
{
	int rc = 0;
@@ -3819,9 +3843,7 @@ static int smbchg_external_otg_regulator_enable(struct regulator_dev *rdev)
	 * allowance to 9V, so that the audio boost operating in reverse never
	 * gets detected as a valid input
	 */
	rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_EN_BIT, 0);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_OTG_VOTER, true, 0);
	if (rc < 0) {
		dev_err(chip->dev, "Couldn't disable HVDCP rc=%d\n", rc);
		return rc;
@@ -3855,9 +3877,7 @@ static int smbchg_external_otg_regulator_disable(struct regulator_dev *rdev)
	 * value in order to allow normal USBs to be recognized as a valid
	 * input.
	 */
	rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_EN_BIT, HVDCP_EN_BIT);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_OTG_VOTER, false, 1);
	if (rc < 0) {
		dev_err(chip->dev, "Couldn't enable HVDCP rc=%d\n", rc);
		return rc;
@@ -4435,10 +4455,13 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip,
		goto out;
	}

	/* otherwise if it is unknown, set type after the vote */
	if (type == POWER_SUPPLY_TYPE_UNKNOWN)
	/* otherwise if it is unknown, set type after removing the vote */
	if (type == POWER_SUPPLY_TYPE_UNKNOWN) {
		rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, 0);
		if (rc < 0)
			pr_err("Couldn't vote for new USB ICL rc=%d\n", rc);
		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.
@@ -4577,9 +4600,7 @@ static void restore_from_hvdcp_detection(struct smbchg_chip *chip)
		pr_err("Couldn't configure HVDCP 9V rc=%d\n", rc);

	/* enable HVDCP */
	rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_EN_BIT, HVDCP_EN_BIT);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1);
	if (rc < 0)
		pr_err("Couldn't enable HVDCP rc=%d\n", rc);

@@ -4647,6 +4668,7 @@ static void handle_usb_removal(struct smbchg_chip *chip)
		chip->typec_current_ma = 0;
	/* cancel/wait for hvdcp pending work if any */
	cancel_delayed_work_sync(&chip->hvdcp_det_work);
	smbchg_relax(chip, PM_DETECT_HVDCP);
	smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
	extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
	if (chip->dpdm_reg)
@@ -5118,8 +5140,7 @@ static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip)

	/* disable HVDCP */
	pr_smb(PR_MISC, "Disable HVDCP\n");
	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG,
			HVDCP_EN_BIT, 0);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, true, 0);
	if (rc < 0) {
		pr_err("Couldn't disable HVDCP rc=%d\n", rc);
		goto out;
@@ -5228,9 +5249,7 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip)

	/* enable HVDCP */
	pr_smb(PR_MISC, "Enable HVDCP\n");
	rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_EN_BIT, HVDCP_EN_BIT);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1);
	if (rc < 0) {
		pr_err("Couldn't enable HVDCP rc=%d\n", rc);
		return rc;
@@ -6250,6 +6269,7 @@ static irqreturn_t fastchg_handler(int irq, void *_chip)
	struct smbchg_chip *chip = _chip;

	pr_smb(PR_INTERRUPT, "p2f triggered\n");
	if (is_usb_present(chip) || is_dc_present(chip))
		smbchg_parallel_usb_check_ok(chip);
	if (chip->batt_psy)
		power_supply_changed(chip->batt_psy);
@@ -6863,7 +6883,22 @@ static int smbchg_hw_init(struct smbchg_chip *chip)
			chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]);

	/* Setup 9V HVDCP */
	if (!chip->hvdcp_not_supported) {
	if (chip->hvdcp_not_supported) {
		rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER,
				true, 0);
		if (rc < 0) {
			dev_err(chip->dev, "Couldn't disable HVDCP rc=%d\n",
					rc);
			return rc;
		}
	} else {
		rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER,
				true, 1);
		if (rc < 0) {
			dev_err(chip->dev, "Couldn't enable HVDCP rc=%d\n",
					rc);
			return rc;
		}
		rc = smbchg_sec_masked_write(chip,
				chip->usb_chgpth_base + CHGPTH_CFG,
				HVDCP_ADAPTER_SEL_MASK, HVDCP_9V);
@@ -8211,6 +8246,15 @@ static int smbchg_probe(struct platform_device *pdev)
		goto votables_cleanup;
	}

	chip->hvdcp_enable_votable = create_votable(
			"HVDCP_ENABLE",
			VOTE_MIN,
			smbchg_hvdcp_enable_cb, chip);
	if (IS_ERR(chip->hvdcp_enable_votable)) {
		rc = PTR_ERR(chip->hvdcp_enable_votable);
		goto votables_cleanup;
	}

	INIT_WORK(&chip->usb_set_online_work, smbchg_usb_update_online_work);
	INIT_DELAYED_WORK(&chip->parallel_en_work,
			smbchg_parallel_usb_en_work);
@@ -8397,6 +8441,7 @@ static int smbchg_probe(struct platform_device *pdev)

	rerun_hvdcp_det_if_necessary(chip);

	update_usb_status(chip, is_usb_present(chip), false);
	dump_regs(chip);
	create_debugfs_entries(chip);
	dev_info(chip->dev,
@@ -8493,11 +8538,9 @@ static void smbchg_shutdown(struct platform_device *pdev)
	disable_irq(chip->otg_oc_irq);
	disable_irq(chip->power_ok_irq);
	disable_irq(chip->recharge_irq);
	disable_irq(chip->src_detect_irq);
	disable_irq(chip->taper_irq);
	disable_irq(chip->usbid_change_irq);
	disable_irq(chip->usbin_ov_irq);
	disable_irq(chip->usbin_uv_irq);
	disable_irq(chip->vbat_low_irq);
	disable_irq(chip->wdog_timeout_irq);

@@ -8540,8 +8583,7 @@ static void smbchg_shutdown(struct platform_device *pdev)

	/* disable HVDCP */
	pr_smb(PR_MISC, "Disable HVDCP\n");
	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG,
			HVDCP_EN_BIT, 0);
	rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER, true, 0);
	if (rc < 0)
		pr_err("Couldn't disable HVDCP rc=%d\n", rc);

@@ -8558,6 +8600,9 @@ static void smbchg_shutdown(struct platform_device *pdev)
	if (rc < 0)
		pr_err("Couldn't fake insertion rc=%d\n", rc);

	disable_irq(chip->src_detect_irq);
	disable_irq(chip->usbin_uv_irq);

	pr_smb(PR_MISC, "Wait 1S to settle\n");
	msleep(1000);
	chip->hvdcp_3_det_ignore_uv = false;