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

Commit da3fdf3e authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: qmp: phy: Add support to read phy init sequence from device tree file



Currently QMP phy initialization sequence is hard coded in QMP phy driver
for every revision of phy. This makes the driver cluttered and adds static
global variables to hold offset and value tuples for un-needed phy
revisions. Hence enable driver to read this information from device tree
file. This allows two or more phys with same revision and different init
sequence to work with same phy driver. Also add delay parameter to register
offset, value tuples in order to add recommended delay after register
write.

Change-Id: Iefeb4675690d525d3b98688701e5d1754e616607
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent cb57967b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ Optional properties:
   the USB PHY and the controller must rely on external VBUS notification in
   order to manually relay the notification to the SSPHY.
 - qcom,emulation: Indicates that we are running on emulation platform.
 - qcom,qmp-phy-init-seq: QMP PHY initialization sequence with reg, diff clk
   value, single ended clk value, delay after register write.

Example:
	ssphy0: ssphy@f9b38000 {
+30 −1
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ struct qmp_reg_val {
	u32 offset;
	u32 diff_clk_sel_val;
	u32 se_clk_sel_val;
	u32 delay;
};

/* Use these offsets/values if PCIE_USB3_PHY_REVISION_ID0 == 0 */
@@ -344,6 +345,8 @@ struct msm_ssphy_qmp {
	bool			emulation;
	bool			misc_config;
	unsigned int		*phy_reg; /* revision based offset */
	unsigned int		*qmp_phy_init_seq;
	int			init_seq_len;
};

static const struct of_device_id msm_usb_id_table[] = {
@@ -495,6 +498,8 @@ static int configure_phy_regs(struct usb_phy *uphy,
		writel_relaxed(diff_clk_sel ?
				reg->diff_clk_sel_val : reg->se_clk_sel_val,
				phy->base + reg->offset);
		if (reg->delay)
			usleep_range(reg->delay, reg->delay + 10);
		reg++;
	}
	return 0;
@@ -559,6 +564,9 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy)
		return -ENODEV;
	}

	if (phy->qmp_phy_init_seq)
		reg = (struct qmp_reg_val *)phy->qmp_phy_init_seq;

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

	/* Make sure that above write completed to get PHY into POWER DOWN */
@@ -810,7 +818,7 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
	struct msm_ssphy_qmp *phy;
	struct device *dev = &pdev->dev;
	struct resource *res;
	int ret = 0;
	int ret = 0, size = 0;
	const struct of_device_id *phy_ver;

	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
@@ -920,6 +928,27 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev)
			dev_dbg(dev, "err reading tcsr_phy_clk_scheme_sel\n");
	}

	of_get_property(dev->of_node, "qcom,qmp-phy-init-seq", &size);
	if (size) {
		if (size % sizeof(*phy->qmp_phy_init_seq)) {
			dev_err(dev, "invalid init_seq_len\n");
			return -EINVAL;
		}
		phy->qmp_phy_init_seq = devm_kzalloc(dev,
						size, GFP_KERNEL);
		if (phy->qmp_phy_init_seq) {
			phy->init_seq_len =
				(size / sizeof(*phy->qmp_phy_init_seq));

			of_property_read_u32_array(dev->of_node,
				"qcom,qmp-phy-init-seq",
				phy->qmp_phy_init_seq,
				phy->init_seq_len);
		} else {
			dev_err(dev, "error allocating memory for phy_init_seq\n");
		}
	}

	phy->emulation = of_property_read_bool(dev->of_node,
						"qcom,emulation");