1
1
openwrt/target/linux/qualcommbe/patches-6.18/0307-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch
Alexandru Gagniuc 809ca978d1 qualcommbe: kernel-6.18: update patches
Generate new patches for 6.18 from my ipq95xx development branch.

Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21506
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-05-28 10:15:20 +02:00

137 lines
4.2 KiB
Diff

From 3d5e5c940f98e6c627afe57123c4765c9306ca50 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] 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>
Alex G: Use accessors for struct phy_package_shared
Update to match the patches that will be upstream.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
---
drivers/net/phy/qcom/qca808x.c | 74 ++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/qcom/qca808x.c
+++ b/drivers/net/phy/qcom/qca808x.c
@@ -150,11 +150,40 @@ 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,
+ MDIO_MASTER_AHB_CLK,
+ SWITCH_CORE_CLK,
+ PACKAGE_CLK_MAX
+};
+
struct qca808x_priv {
int led_polarity_mode;
struct qcom_phy_hw_stats hw_stats;
};
+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",
+ [MDIO_MASTER_AHB_CLK] = "mdio_master_ahb",
+ [SWITCH_CORE_CLK] = "switch_core",
+};
+
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),
@@ -879,11 +908,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 device_node *np = phy_package_get_node(phydev);
- 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.
@@ -914,17 +956,43 @@ 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 = phy_package_get_priv(phydev);
+ for (i = 0; i < ARRAY_SIZE(qca8084_package_clk_name); i++) {
+ clk = of_clk_get_by_name(np, qca8084_package_clk_name[i]);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) == -EINVAL)
+ clk = NULL;
+ else
+ 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(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;