[PATCH 4/7] imx8mp: power-domain: Expose high performance PLL clock

Sumit Garg sumit.garg at linaro.org
Tue Feb 20 14:10:53 CET 2024


PCIe PHY can use it when there is no external refclock provided.

Signed-off-by: Sumit Garg <sumit.garg at linaro.org>
---
 drivers/power/domain/imx8mp-hsiomix.c | 79 +++++++++++++++++++++++++--
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/drivers/power/domain/imx8mp-hsiomix.c b/drivers/power/domain/imx8mp-hsiomix.c
index 62145e0261b..4cefe642724 100644
--- a/drivers/power/domain/imx8mp-hsiomix.c
+++ b/drivers/power/domain/imx8mp-hsiomix.c
@@ -9,6 +9,8 @@
 #include <dm.h>
 #include <dm/device.h>
 #include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <power-domain-uclass.h>
 
 #include <dt-bindings/power/imx8mp-power.h>
@@ -18,6 +20,15 @@
 #define  USB_CLOCK_MODULE_EN	BIT(1)
 #define  PCIE_PHY_APB_RST	BIT(4)
 #define  PCIE_PHY_INIT_RST	BIT(5)
+#define GPR_REG1		0x4
+#define  PLL_LOCK		BIT(13)
+#define GPR_REG2		0x8
+#define  P_PLL_MASK		GENMASK(5, 0)
+#define  M_PLL_MASK		GENMASK(15, 6)
+#define  S_PLL_MASK		GENMASK(18, 16)
+#define GPR_REG3		0xc
+#define  PLL_CKE		BIT(17)
+#define  PLL_RST		BIT(31)
 
 struct imx8mp_hsiomix_priv {
 	void __iomem *base;
@@ -31,6 +42,53 @@ struct imx8mp_hsiomix_priv {
 	struct power_domain pd_pcie_phy;
 };
 
+static int hsio_pll_enable(struct udevice *dev)
+{
+	struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev);
+	unsigned long start;
+	u32 val;
+
+	/* Setup HSIO PLL */
+	val = readl(priv->base + GPR_REG2);
+	val &= ~(P_PLL_MASK | M_PLL_MASK | S_PLL_MASK);
+	val |= (FIELD_PREP(P_PLL_MASK, 12) | FIELD_PREP(M_PLL_MASK, 800) |
+		FIELD_PREP(S_PLL_MASK, 4));
+	writel(val, priv->base + GPR_REG2);
+
+	/* de-assert PLL reset */
+	setbits_le32(priv->base + GPR_REG3, PLL_RST);
+
+	/* enable PLL */
+	setbits_le32(priv->base + GPR_REG3, PLL_CKE);
+
+	/* Check if PLL is locked */
+	start = get_timer(0);
+	for (;;) {
+		if (readl(priv->base + GPR_REG1) & PLL_LOCK)
+			break;
+
+		if (get_timer(start) > 100) {
+			dev_err(dev, "failed to lock HSIO PLL\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(10);
+	}
+
+	return 0;
+}
+
+static void hsio_pll_disable(struct udevice *dev)
+{
+	struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev);
+
+	/* de-assert PLL reset */
+	clrbits_le32(priv->base + GPR_REG3, PLL_RST);
+
+	/* enable PLL */
+	clrbits_le32(priv->base + GPR_REG3, PLL_CKE);
+}
+
 static int imx8mp_hsiomix_on(struct power_domain *power_domain)
 {
 	struct udevice *dev = power_domain->dev;
@@ -69,16 +127,23 @@ static int imx8mp_hsiomix_on(struct power_domain *power_domain)
 	if (ret)
 		goto err_clk_pcie;
 
-	if (power_domain->id == IMX8MP_HSIOBLK_PD_USB)
+	if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) {
 		setbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN);
-	else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE)
+	} else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE) {
 		setbits_le32(priv->base + GPR_REG0, PCIE_CLOCK_MODULE_EN);
-	else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE_PHY)
+	} else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE_PHY) {
 		setbits_le32(priv->base + GPR_REG0, PCIE_PHY_APB_RST |
 						    PCIE_PHY_INIT_RST);
 
+		ret = hsio_pll_enable(dev);
+		if (ret)
+			goto err_hsio_pll;
+	}
+
 	return 0;
 
+err_hsio_pll:
+	clk_disable(&priv->clk_pcie);
 err_clk_pcie:
 	clk_disable(&priv->clk_usb);
 err_clk_usb:
@@ -93,13 +158,15 @@ static int imx8mp_hsiomix_off(struct power_domain *power_domain)
 	struct udevice *dev = power_domain->dev;
 	struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev);
 
-	if (power_domain->id == IMX8MP_HSIOBLK_PD_USB)
+	if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) {
 		clrbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN);
-	else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE)
+	} else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE) {
 		clrbits_le32(priv->base + GPR_REG0, PCIE_CLOCK_MODULE_EN);
-	else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE_PHY)
+	} else if (power_domain->id == IMX8MP_HSIOBLK_PD_PCIE_PHY) {
 		clrbits_le32(priv->base + GPR_REG0, PCIE_PHY_APB_RST |
 						    PCIE_PHY_INIT_RST);
+		hsio_pll_disable(dev);
+	}
 
 	clk_disable(&priv->clk_usb);
 	clk_disable(&priv->clk_pcie);
-- 
2.34.1



More information about the U-Boot mailing list