static int msm_ssphy_qmp_init(struct usb_phy *uphy)
{
	struct msm_ssphy_qmp *phy = container_of(uphy, struct msm_ssphy_qmp,
					phy);
	int ret;
	unsigned init_timeout_usec = INIT_MAX_TIME_USEC;
	u32 revid;
	const struct qmp_reg_val *reg = NULL, *misc = NULL;

	dev_info(uphy->dev, "Initializing QMP phy\n");

	if (phy->emulation)
		return 0;

	if (!phy->clk_enabled) {
		ret = msm_ssphy_qmp_init_clocks(phy);
		if (ret) {
			dev_err(uphy->dev, "failed to init clocks %d\n", ret);
			return ret;
		}
	}

	
	revid = (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID3) & 0xFF) << 24;
	revid |= (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID2) & 0xFF) << 16;
	revid |= (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID1) & 0xFF) << 8;
	revid |= readl_relaxed(phy->base + PCIE_USB3_PHY_REVISION_ID0) & 0xFF;

	dev_info(uphy->dev, "QMP phy revid = %x\n", revid);

	switch (revid) {
	case 0x10000000:
		reg = qmp_settings_rev0;
		misc = qmp_settings_rev0_misc;
		break;
	case 0x10000001:
		reg = qmp_settings_rev1;
		misc = qmp_settings_rev1_misc;
		break;
	default:
		dev_err(uphy->dev, "Unknown revid 0x%x, cannot initialize PHY\n",
			revid);
		return -ENODEV;
	}

	
	if (phy->ahb2phy)
		writel_relaxed(0x11, phy->ahb2phy + PERIPH_SS_AHB2PHY_TOP_CFG);

	writel_relaxed(0x01, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL);

	
	ret = configure_phy_regs(uphy, reg);
	if (ret) {
		dev_err(uphy->dev, "Failed the main PHY configuration\n");
		return ret;
	}

	
	if (phy->override_pll_cal) {
		reg = qmp_override_pll;
		ret = configure_phy_regs(uphy, reg);
		if (ret) {
			dev_err(uphy->dev,
				"Failed the PHY PLL override configuration\n");
			return ret;
		}
	}
	if (phy->misc_config) {
		ret = configure_phy_regs(uphy, misc);
		if (ret) {
			dev_err(uphy->dev, "Failed the misc PHY configuration\n");
			return ret;
		}
	}

	writel_relaxed(0x00, phy->base + PCIE_USB3_PHY_SW_RESET);
	writel_relaxed(0x03, phy->base + PCIE_USB3_PHY_START);

	if (!phy->switch_pipe_clk_src)
		
		clk_prepare_enable(phy->pipe_clk);

	
	do {
		if (readl_relaxed(phy->base + PCIE_USB3_PHY_PCS_STATUS) &
			PHYSTATUS)
			usleep(1);
		else
			break;
	} while (--init_timeout_usec);

	if (!init_timeout_usec) {
		dev_err(uphy->dev, "QMP PHY initialization timeout\n");
		return -EBUSY;
	};

	if (phy->switch_pipe_clk_src)
		clk_set_rate(phy->pipe_clk, 125000000);

	return 0;
}
Пример #2
0
/* SSPHY Initialization */
static int msm_ssphy_qmp_init(struct usb_phy *uphy)
{
	struct msm_ssphy_qmp *phy = container_of(uphy, struct msm_ssphy_qmp,
					phy);
	int ret;
	unsigned init_timeout_usec = INIT_MAX_TIME_USEC;
	u32 revid;
	const struct qmp_reg_val *reg = NULL, *misc = NULL;

	dev_dbg(uphy->dev, "Initializing QMP phy\n");

	if (phy->emulation)
		return 0;

	if (!phy->clk_enabled) {
		ret = msm_ssphy_qmp_init_clocks(phy);
		if (ret) {
			dev_err(uphy->dev, "failed to init clocks %d\n", ret);
			return ret;
		}
	}

	/* Rev ID is made up each of the LSBs of REVISION_ID[0-3] */
	revid = (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID3) & 0xFF) << 24;
	revid |= (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID2) & 0xFF) << 16;
	revid |= (readl_relaxed(phy->base +
			PCIE_USB3_PHY_REVISION_ID1) & 0xFF) << 8;
	revid |= readl_relaxed(phy->base + PCIE_USB3_PHY_REVISION_ID0) & 0xFF;

	switch (revid) {
	case 0x10000000:
		reg = qmp_settings_rev0;
		misc = qmp_settings_rev0_misc;
		break;
	case 0x10000001:
		reg = qmp_settings_rev1;
		misc = qmp_settings_rev1_misc;
		break;
	default:
		dev_err(uphy->dev, "Unknown revid 0x%x, cannot initialize PHY\n",
			revid);
		return -ENODEV;
	}

	/* Configure AHB2PHY for one wait state reads/writes */
	if (phy->ahb2phy)
		writel_relaxed(0x11, phy->ahb2phy + PERIPH_SS_AHB2PHY_TOP_CFG);

	writel_relaxed(0x01, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL);

	/* Main configuration */
	if (configure_phy_regs(uphy, reg)) {
		dev_err(uphy->dev, "Failed the main PHY configuration\n");
		return ret;
	}

	/* Feature specific configurations */
	if (phy->override_pll_cal) {
		reg = qmp_override_pll;
		if (configure_phy_regs(uphy, reg)) {
			dev_err(uphy->dev,
				"Failed the PHY PLL override configuration\n");
			return ret;
		}
	}
	if (phy->misc_config) {
		configure_phy_regs(uphy, misc);
		dev_err(uphy->dev, "Failed the misc PHY configuration\n");
		return ret;
	}

	writel_relaxed(0x00, phy->base + PCIE_USB3_PHY_SW_RESET);
	writel_relaxed(0x03, phy->base + PCIE_USB3_PHY_START);

	if (!phy->switch_pipe_clk_src)
		/* this clock wasn't enabled before, enable it now */
		clk_prepare_enable(phy->pipe_clk);

	/* Wait for PHY initialization to be done */
	do {
		if (readl_relaxed(phy->base + PCIE_USB3_PHY_PCS_STATUS) &
			PHYSTATUS)
			usleep(1);
		else
			break;
	} while (--init_timeout_usec);

	if (!init_timeout_usec) {
		dev_err(uphy->dev, "QMP PHY initialization timeout\n");
		return -EBUSY;
	};

	/*
	 * After PHY initilization above, the PHY is generating
	 * the usb3_pipe_clk in 125MHz. Therefore now we can (if needed)
	 * switch the gcc_usb3_pipe_clk to 125MHz as well, so the
	 * gcc_usb3_pipe_clk is sourced now from the usb3_pipe3_clk
	 * instead of from the xo clock.
	 */
	if (phy->switch_pipe_clk_src)
		clk_set_rate(phy->pipe_clk, 125000000);

	return 0;
}