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

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

Merge "usb: phy-msm-usb: Add support for QUSB2 PHY"

parents facac04d a3eafa95
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ Required properties :
	    1 - Chipidea PHY (obsolete)
	    2 - Synopsis Pico PHY
	    3 - Synopsis Femto PHY
	    4 - QUSB ULPI PHY
- qcom,hsusb-otg-mode: Operational mode. Can be one of
            1 - Peripheral only mode
	    2 - Host only mode
@@ -56,6 +57,7 @@ Required properties :
		PHY POR signal. Required for overriding PHY parameters.
	"phy_csr_clk": Required for accessing PHY CSR registers through
		AHB2PHY interface.
	"phy_ref_clk": Required when PHY have referance clock,
	"xo": XO clock. The source clock that is used as a reference clock
		to the PHY.
	"bimc_clk", "snoc_clk", "pcnoc_clk": bus voting clocks. Used to
+77 −2
Original line number Diff line number Diff line
@@ -344,6 +344,12 @@ static int ulpi_read(struct usb_phy *phy, u32 reg)
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	int cnt = 0;

	if (motg->pdata->phy_type == QUSB_ULPI_PHY && reg > 0x3F) {
		pr_debug("%s: ULPI vendor-specific reg 0x%02x not supported\n",
			__func__, reg);
		return 0;
	}

	/* initiate read operation */
	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
	       USB_ULPI_VIEWPORT);
@@ -371,6 +377,12 @@ static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	int cnt = 0;

	if (motg->pdata->phy_type == QUSB_ULPI_PHY && reg > 0x3F) {
		pr_debug("%s: ULPI vendor-specific reg 0x%02x not supported\n",
			__func__, reg);
		return 0;
	}

	/* initiate write operation */
	writel(ULPI_RUN | ULPI_WRITE |
	       ULPI_ADDR(reg) | ULPI_DATA(val),
@@ -565,10 +577,13 @@ static int msm_otg_link_reset(struct msm_otg *motg)
	return 0;
}

#define QUSB2PHY_PORT_POWERDOWN		0xB4
#define QUSB2PHY_PORT_UTMI_CTRL2	0xC4

static void msm_usb_phy_reset(struct msm_otg *motg)
{
	u32 val;
	int ret;
	int ret, *seq;

	switch (motg->pdata->phy_type) {
	case SNPS_PICO_PHY:
@@ -589,6 +604,45 @@ static void msm_usb_phy_reset(struct msm_otg *motg)
		val |= PHY_POR_DEASSERT;
		writel_relaxed(val, motg->usb_phy_ctrl_reg);
		break;
	case QUSB_ULPI_PHY:
		ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
		if (ret) {
			pr_err("phy_reset_clk assert failed %d\n", ret);
			break;
		}

		/* need to delay 10us for PHY to reset */
		usleep(10);

		ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
		if (ret) {
			pr_err("phy_reset_clk de-assert failed %d\n", ret);
			break;
		}

		/* Ensure that RESET operation is completed. */
		mb();

		writel_relaxed(0x23,
				motg->phy_csr_regs + QUSB2PHY_PORT_POWERDOWN);
		writel_relaxed(0x0,
				motg->phy_csr_regs + QUSB2PHY_PORT_UTMI_CTRL2);

		/* Program tuning parameters for PHY */
		seq = motg->pdata->phy_init_seq;
		if (seq) {
			while (seq[0] >= 0) {
				writel_relaxed(seq[1],
						motg->phy_csr_regs + seq[0]);
				seq += 2;
			}
		}

		/* ensure above writes are completed before re-enabling PHY */
		wmb();
		writel_relaxed(0x22,
				motg->phy_csr_regs + QUSB2PHY_PORT_POWERDOWN);
		break;
	case SNPS_FEMTO_PHY:
		if (!motg->phy_por_clk) {
			pr_err("phy_por_clk missing\n");
@@ -4993,6 +5047,26 @@ static int msm_otg_probe(struct platform_device *pdev)
		pdata = pdev->dev.platform_data;
	}

	if (pdata->phy_type == QUSB_ULPI_PHY) {
		if (of_property_match_string(pdev->dev.of_node,
					"clock-names", "phy_ref_clk") >= 0) {
			motg->phy_ref_clk = devm_clk_get(&pdev->dev,
						"phy_ref_clk");
			if (IS_ERR(motg->phy_ref_clk)) {
				ret = PTR_ERR(motg->phy_ref_clk);
				goto disable_phy_csr_clk;
			} else {
				ret = clk_prepare_enable(motg->phy_ref_clk);
				if (ret) {
					dev_err(&pdev->dev,
						"fail to enable phy ref clk %d\n",
						ret);
					goto disable_phy_csr_clk;
				}
			}
		}
	}

	motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
							GFP_KERNEL);
	if (!motg->phy.otg) {
@@ -5091,7 +5165,8 @@ static int msm_otg_probe(struct platform_device *pdev)
	 * The link does not have any PHY specific registers.
	 * Hence set motg->usb_phy_ctrl_reg to.
	 */
	if (motg->pdata->phy_type == SNPS_FEMTO_PHY) {
	if (motg->pdata->phy_type == SNPS_FEMTO_PHY ||
		pdata->phy_type == QUSB_ULPI_PHY) {
		res = platform_get_resource_byname(pdev,
				IORESOURCE_MEM, "phy_csr");
		if (!res) {
+2 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ enum msm_usb_phy_type {
	CI_PHY,			/* not supported */
	SNPS_PICO_PHY,
	SNPS_FEMTO_PHY,
	QUSB_ULPI_PHY,
};

#define IDEV_CHG_MAX	1500
@@ -421,6 +422,7 @@ struct msm_otg {
	struct clk *phy_por_clk;
	struct clk *phy_csr_clk;
	struct clk *bus_clks[USB_NUM_BUS_CLOCKS];
	struct clk *phy_ref_clk;
	long core_clk_rate;
	struct resource *io_res;
	void __iomem *regs;