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

Commit 916f9bbe authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa
Browse files

QUSB2PHY: Fix leakage current issue during wall charger disconnect



It is required to disable QUSB2PHY level shifter by writing to
TCSR_QUSB2PHY_CX2PX_LVL_SHIFT_KEEPER register during disconnect
to avoid leakage current. Hence add support for the same.

Change-Id: I666617d513314903533f2356b5db4b9ca3eac6e4
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent d3e41c96
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -163,6 +163,7 @@ Optional properties:
   "emu_phy_base" : phy base address used for programming emulation target phy.
   "emu_phy_base" : phy base address used for programming emulation target phy.
   "ref_clk_addr" : ref_clk bcr address used for on/off ref_clk before reset.
   "ref_clk_addr" : ref_clk bcr address used for on/off ref_clk before reset.
   "tcsr_phy_clk_scheme_sel": address used to determine QUSB PHY clk source.
   "tcsr_phy_clk_scheme_sel": address used to determine QUSB PHY clk source.
   "tcsr_phy_level_shift_keeper": address used to clamp QUSB PHY level shifter.
 - reg-names: Should be "qscratch_base". The qscratch register bank
 - reg-names: Should be "qscratch_base". The qscratch register bank
   allows us to manipulate QUSB PHY bits eg. to enable D+ pull-up using s/w
   allows us to manipulate QUSB PHY bits eg. to enable D+ pull-up using s/w
   control in device mode. The reg-names property is required if the
   control in device mode. The reg-names property is required if the
+30 −13
Original line number Original line Diff line number Diff line
@@ -124,6 +124,7 @@ struct qusb_phy {
	void __iomem		*tune2_efuse_reg;
	void __iomem		*tune2_efuse_reg;
	void __iomem		*ref_clk_base;
	void __iomem		*ref_clk_base;
	void __iomem		*tcsr_phy_clk_scheme_sel;
	void __iomem		*tcsr_phy_clk_scheme_sel;
	void __iomem		*tcsr_phy_lvl_shift_keeper;


	struct clk		*ref_clk_src;
	struct clk		*ref_clk_src;
	struct clk		*ref_clk;
	struct clk		*ref_clk;
@@ -402,13 +403,18 @@ static int qusb_phy_update_dpdm(struct usb_phy *phy, int value)
	case POWER_SUPPLY_DP_DM_DPF_DMF:
	case POWER_SUPPLY_DP_DM_DPF_DMF:
		dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPF_DMF\n");
		dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPF_DMF\n");
		if (!qphy->rm_pulldown) {
		if (!qphy->rm_pulldown) {
			ret = qusb_phy_enable_power(qphy, true);
			if (ret >= 0) {
				qphy->rm_pulldown = true;
				dev_dbg(phy->dev, "DP_DM_F: rm_pulldown:%d\n",
						qphy->rm_pulldown);
			}


			if (qphy->put_into_high_z_state) {
			if (qphy->put_into_high_z_state) {
				if (qphy->tcsr_phy_lvl_shift_keeper)
					writel_relaxed(0x1,
					       qphy->tcsr_phy_lvl_shift_keeper);


				/* Bring up DVDD */
				ret = qusb_phy_vdd(qphy, true);
				if (ret < 0)
					goto clk_error;
				qusb_phy_gdsc(qphy, true);
				qusb_phy_gdsc(qphy, true);
				qusb_phy_enable_clocks(qphy, true);
				qusb_phy_enable_clocks(qphy, true);


@@ -438,16 +444,7 @@ static int qusb_phy_update_dpdm(struct usb_phy *phy, int value)
					qphy->base + QUSB2PHY_PORT_POWERDOWN);
					qphy->base + QUSB2PHY_PORT_POWERDOWN);
				/* Make sure that above write is completed */
				/* Make sure that above write is completed */
				wmb();
				wmb();
			}

			ret = qusb_phy_enable_power(qphy, true);
			if (ret >= 0) {
				qphy->rm_pulldown = true;
				dev_dbg(phy->dev, "DP_DM_F: rm_pulldown:%d\n",
						qphy->rm_pulldown);
			}


			if (qphy->put_into_high_z_state) {
				qusb_phy_enable_clocks(qphy, false);
				qusb_phy_enable_clocks(qphy, false);
				qusb_phy_gdsc(qphy, false);
				qusb_phy_gdsc(qphy, false);
			}
			}
@@ -489,6 +486,9 @@ static int qusb_phy_update_dpdm(struct usb_phy *phy, int value)
			}
			}


			if (!qphy->cable_connected) {
			if (!qphy->cable_connected) {
				if (qphy->tcsr_phy_lvl_shift_keeper)
					writel_relaxed(0x0,
					       qphy->tcsr_phy_lvl_shift_keeper);
				dev_dbg(phy->dev, "turn off for HVDCP case\n");
				dev_dbg(phy->dev, "turn off for HVDCP case\n");
				ret = qusb_phy_enable_power(qphy, false);
				ret = qusb_phy_enable_power(qphy, false);
			}
			}
@@ -1002,6 +1002,9 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
			wmb();
			wmb();


			qusb_phy_enable_clocks(qphy, false);
			qusb_phy_enable_clocks(qphy, false);
			if (qphy->tcsr_phy_lvl_shift_keeper)
				writel_relaxed(0x0,
					qphy->tcsr_phy_lvl_shift_keeper);
			qusb_phy_enable_power(qphy, false);
			qusb_phy_enable_power(qphy, false);
			/*
			/*
			 * Set put_into_high_z_state to true so next USB
			 * Set put_into_high_z_state to true so next USB
@@ -1023,6 +1026,9 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
				qphy->base + QUSB2PHY_PORT_INTR_CTRL);
				qphy->base + QUSB2PHY_PORT_INTR_CTRL);
		} else {
		} else {
			qusb_phy_enable_power(qphy, true);
			qusb_phy_enable_power(qphy, true);
			if (qphy->tcsr_phy_lvl_shift_keeper)
				writel_relaxed(0x1,
					qphy->tcsr_phy_lvl_shift_keeper);
			qusb_phy_enable_clocks(qphy, true);
			qusb_phy_enable_clocks(qphy, true);
		}
		}
		qphy->suspended = false;
		qphy->suspended = false;
@@ -1177,6 +1183,17 @@ static int qusb_phy_probe(struct platform_device *pdev)
			dev_dbg(dev, "err reading tcsr_phy_clk_scheme_sel\n");
			dev_dbg(dev, "err reading tcsr_phy_clk_scheme_sel\n");
	}
	}


	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"tcsr_phy_level_shift_keeper");
	if (res) {
		qphy->tcsr_phy_lvl_shift_keeper = devm_ioremap_nocache(dev,
				res->start, resource_size(res));
		if (IS_ERR(qphy->tcsr_phy_lvl_shift_keeper)) {
			dev_err(dev, "err reading tcsr_phy_lvl_shift_keeper\n");
			qphy->tcsr_phy_lvl_shift_keeper = NULL;
		}
	}

	qphy->dpdm_pulsing_enabled = of_property_read_bool(dev->of_node,
	qphy->dpdm_pulsing_enabled = of_property_read_bool(dev->of_node,
					"qcom,enable-dpdm-pulsing");
					"qcom,enable-dpdm-pulsing");