mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-23 02:12:52 +00:00
139 lines
4.2 KiB
Diff
139 lines
4.2 KiB
Diff
|
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(-)
|
||
|
|
||
|
diff --git a/drivers/net/phy/qcom/qca808x.c b/drivers/net/phy/qcom/qca808x.c
|
||
|
index 85bb299fe0a3..632cad1ad190 100644
|
||
|
--- 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 QCA808X PHY driver");
|
||
|
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(struct phy_device *phydev)
|
||
|
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_once(struct phy_device *phydev)
|
||
|
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;
|
||
|
|
||
|
--
|
||
|
2.45.2
|
||
|
|