b41e725d3065b4fa600f1c7ebd20b92b221534ce
[openwrt/staging/blocktrron.git] /
1 From 685566f8b765f522b7f4d4deb06bf84a557dc4ac Mon Sep 17 00:00:00 2001
2 From: Luo Jie <quic_luoj@quicinc.com>
3 Date: Tue, 9 Apr 2024 16:30:55 +0800
4 Subject: [PATCH] net: phy: qca808x: Add package clocks and resets for QCA8084
5
6 Parse the PHY package clocks from the PHY package DTS node.
7 These package level clocks will be enabled in the PHY package
8 init function.
9
10 Deassert PHY package reset, which is necessary for accessing
11 the PHY registers.
12
13 Change-Id: I254d0aa0a1155d3618c6f1fc7d7a5b6ecadccbaa
14 Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
15 ---
16 drivers/net/phy/qcom/qca808x.c | 67 ++++++++++++++++++++++++++++++++--
17 1 file changed, 64 insertions(+), 3 deletions(-)
18
19 --- a/drivers/net/phy/qcom/qca808x.c
20 +++ b/drivers/net/phy/qcom/qca808x.c
21 @@ -4,6 +4,7 @@
22 #include <linux/module.h>
23 #include <linux/of.h>
24 #include <linux/clk.h>
25 +#include <linux/reset.h>
26
27 #include "qcom.h"
28
29 @@ -148,10 +149,35 @@ MODULE_DESCRIPTION("Qualcomm Atheros QCA
30 MODULE_AUTHOR("Matus Ujhelyi, Luo Jie");
31 MODULE_LICENSE("GPL");
32
33 +enum {
34 + APB_BRIDGE_CLK,
35 + AHB_CLK,
36 + SEC_CTRL_AHB_CLK,
37 + TLMM_CLK,
38 + TLMM_AHB_CLK,
39 + CNOC_AHB_CLK,
40 + MDIO_AHB_CLK,
41 + PACKAGE_CLK_MAX
42 +};
43 +
44 struct qca808x_priv {
45 int led_polarity_mode;
46 };
47
48 +struct qca808x_shared_priv {
49 + struct clk *clk[PACKAGE_CLK_MAX];
50 +};
51 +
52 +static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = {
53 + [APB_BRIDGE_CLK] = "apb_bridge",
54 + [AHB_CLK] = "ahb",
55 + [SEC_CTRL_AHB_CLK] = "sec_ctrl_ahb",
56 + [TLMM_CLK] = "tlmm",
57 + [TLMM_AHB_CLK] = "tlmm_ahb",
58 + [CNOC_AHB_CLK] = "cnoc_ahb",
59 + [MDIO_AHB_CLK] = "mdio_ahb",
60 +};
61 +
62 static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
63 {
64 return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
65 @@ -853,11 +879,24 @@ static void qca8084_link_change_notify(s
66 QCA8084_IPG_10_TO_11_EN : 0);
67 }
68
69 +/* QCA8084 is a four-port PHY, which integrates the clock controller,
70 + * 4 PHY devices and 2 PCS interfaces (PCS0 and PCS1). PCS1 includes
71 + * XPCS and PCS to support 10G-QXGMII and SGMII. PCS0 includes one PCS
72 + * to support SGMII.
73 + *
74 + * The clocks and resets are sourced from the integrated clock controller
75 + * of the PHY package. This integrated clock controller is driven by a
76 + * QCA8K clock provider that supplies the clocks and resets to the four
77 + * PHYs, PCS and PHY package.
78 + */
79 static int qca8084_phy_package_probe_once(struct phy_device *phydev)
80 {
81 int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6};
82 struct phy_package_shared *shared = phydev->shared;
83 - int ret, clear, set;
84 + struct qca808x_shared_priv *shared_priv;
85 + struct reset_control *rstc;
86 + int i, ret, clear, set;
87 + struct clk *clk;
88
89 /* Program the MDIO address of PHY and PCS optionally, the MDIO
90 * address 0-6 is used for PHY and PCS MDIO devices by default.
91 @@ -889,17 +928,39 @@ static int qca8084_phy_package_probe_onc
92 set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]);
93 set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]);
94
95 - return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set);
96 + ret = qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set);
97 + if (ret)
98 + return ret;
99 +
100 + shared_priv = shared->priv;
101 + for (i = 0; i < ARRAY_SIZE(qca8084_package_clk_name); i++) {
102 + clk = of_clk_get_by_name(shared->np,
103 + qca8084_package_clk_name[i]);
104 + if (IS_ERR(clk))
105 + return dev_err_probe(&phydev->mdio.dev, PTR_ERR(clk),
106 + "package clock %s not ready\n",
107 + qca8084_package_clk_name[i]);
108 + shared_priv->clk[i] = clk;
109 + }
110 +
111 + rstc = of_reset_control_get_exclusive(shared->np, NULL);
112 + if (IS_ERR(rstc))
113 + return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc),
114 + "package reset not ready\n");
115 +
116 + /* Deassert PHY package. */
117 + return reset_control_deassert(rstc);
118 }
119
120 static int qca8084_probe(struct phy_device *phydev)
121 {
122 + struct qca808x_shared_priv *shared_priv;
123 struct device *dev = &phydev->mdio.dev;
124 struct reset_control *rstc;
125 struct clk *clk;
126 int ret;
127
128 - ret = devm_of_phy_package_join(dev, phydev, 0);
129 + ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv));
130 if (ret)
131 return ret;
132