From 324c5b908a5294390ed9659a6439758cb20ecd61 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Tue, 9 Apr 2024 16:30:55 +0800
Subject: [PATCH 07/50] net: phy: qca808x: Add package clocks and resets for
 QCA8084

Parse the PHY package clocks from the PHY package DTS node.
These package level clocks will be enabled in the PHY package
init function.

Deassert PHY package reset, which is necessary for accessing
the PHY registers.

Change-Id: I254d0aa0a1155d3618c6f1fc7d7a5b6ecadccbaa
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
 drivers/net/phy/qcom/qca808x.c | 67 ++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 3 deletions(-)

--- a/drivers/net/phy/qcom/qca808x.c
+++ b/drivers/net/phy/qcom/qca808x.c
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/reset.h>
 
 #include "qcom.h"
 
@@ -148,10 +149,35 @@ MODULE_DESCRIPTION("Qualcomm Atheros QCA
 MODULE_AUTHOR("Matus Ujhelyi, Luo Jie");
 MODULE_LICENSE("GPL");
 
+enum {
+	APB_BRIDGE_CLK,
+	AHB_CLK,
+	SEC_CTRL_AHB_CLK,
+	TLMM_CLK,
+	TLMM_AHB_CLK,
+	CNOC_AHB_CLK,
+	MDIO_AHB_CLK,
+	PACKAGE_CLK_MAX
+};
+
 struct qca808x_priv {
 	int led_polarity_mode;
 };
 
+struct qca808x_shared_priv {
+	struct clk *clk[PACKAGE_CLK_MAX];
+};
+
+static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = {
+	[APB_BRIDGE_CLK] =	"apb_bridge",
+	[AHB_CLK] =		"ahb",
+	[SEC_CTRL_AHB_CLK] =	"sec_ctrl_ahb",
+	[TLMM_CLK] =		"tlmm",
+	[TLMM_AHB_CLK] =	"tlmm_ahb",
+	[CNOC_AHB_CLK] =	"cnoc_ahb",
+	[MDIO_AHB_CLK] =	"mdio_ahb",
+};
+
 static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
 {
 	return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
@@ -853,11 +879,24 @@ static void qca8084_link_change_notify(s
 			       QCA8084_IPG_10_TO_11_EN : 0);
 }
 
+/* QCA8084 is a four-port PHY, which integrates the clock controller,
+ * 4 PHY devices and 2 PCS interfaces (PCS0 and PCS1). PCS1 includes
+ * XPCS and PCS to support 10G-QXGMII and SGMII. PCS0 includes one PCS
+ * to support SGMII.
+ *
+ * The clocks and resets are sourced from the integrated clock controller
+ * of the PHY package. This integrated clock controller is driven by a
+ * QCA8K clock provider that supplies the clocks and resets to the four
+ * PHYs, PCS and PHY package.
+ */
 static int qca8084_phy_package_probe_once(struct phy_device *phydev)
 {
 	int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6};
 	struct phy_package_shared *shared = phydev->shared;
-	int ret, clear, set;
+	struct qca808x_shared_priv *shared_priv;
+	struct reset_control *rstc;
+	int i, ret, clear, set;
+	struct clk *clk;
 
 	/* Program the MDIO address of PHY and PCS optionally, the MDIO
 	 * address 0-6 is used for PHY and PCS MDIO devices by default.
@@ -889,17 +928,39 @@ static int qca8084_phy_package_probe_onc
 	set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]);
 	set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]);
 
-	return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set);
+	ret =  qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set);
+	if (ret)
+		return ret;
+
+	shared_priv = shared->priv;
+	for (i = 0; i < ARRAY_SIZE(qca8084_package_clk_name); i++) {
+		clk = of_clk_get_by_name(shared->np,
+					 qca8084_package_clk_name[i]);
+		if (IS_ERR(clk))
+			return dev_err_probe(&phydev->mdio.dev, PTR_ERR(clk),
+					     "package clock %s not ready\n",
+					     qca8084_package_clk_name[i]);
+		shared_priv->clk[i] = clk;
+	}
+
+	rstc = of_reset_control_get_exclusive(shared->np, NULL);
+	if (IS_ERR(rstc))
+		return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc),
+				     "package reset not ready\n");
+
+	/* Deassert PHY package. */
+	return reset_control_deassert(rstc);
 }
 
 static int qca8084_probe(struct phy_device *phydev)
 {
+	struct qca808x_shared_priv *shared_priv;
 	struct device *dev = &phydev->mdio.dev;
 	struct reset_control *rstc;
 	struct clk *clk;
 	int ret;
 
-	ret = devm_of_phy_package_join(dev, phydev, 0);
+	ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));
 	if (ret)
 		return ret;
 
