0c773caf38d3fb16c8f04307c15e6b36a95ea0dd
[openwrt/staging/linusw.git] /
1 From: George Moussalem <george.moussalem@outlook.com>
2 Date: Sun, 19 Jan 2025 11:25:27 +0400
3 Subject: [PATCH] net: phy: qcom: ipq5018 enable configuration of DAC settings
4
5 Allow setting amplitude and bias current as needed on the IPQ5018 Internal
6 GE PHY. When the "qcom,dac" property is set in the DTS, the driver expects
7 a pair of u32 values:
8
9 (from QCA8337 datasheet)
10 11: follow DSP setting
11 10: bypass half amplitude and follow DSP half bias current
12 01: half amplitude follow DSP and bypass half bias current
13 00: full amplitude and full bias current
14
15 Signed-off-by: George Moussalem <george.moussalem@outlook.com>
16 ---
17 --- a/drivers/net/phy/qcom/ipq5018.c
18 +++ b/drivers/net/phy/qcom/ipq5018.c
19 @@ -13,6 +13,10 @@
20 #define IPQ5018_PHY_FIFO_CONTROL 0x19
21 #define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
22
23 +#define IPQ5018_PHY_DEBUG_EDAC 0x4380
24 +#define IPQ5018_PHY_MMD1_MDAC 0x8100
25 +#define IPQ5018_PHY_DAC_MASK GENMASK(15,8)
26 +
27 struct ipq5018_phy {
28 int num_clks;
29 struct clk_bulk_data *clks;
30 @@ -20,20 +24,35 @@ struct ipq5018_phy {
31
32 struct clk_hw *clk_rx, *clk_tx;
33 struct clk_hw_onecell_data *clk_data;
34 +
35 + u32 mdac;
36 + u32 edac;
37 };
38
39 static int ipq5018_probe(struct phy_device *phydev)
40 {
41 - struct ipq5018_phy *priv;
42 struct device *dev = &phydev->mdio.dev;
43 + struct ipq5018_phy *priv;
44 + u32 mdac, edac = 0;
45 char name[64];
46 - int ret;
47 + int ret, cnt;
48
49 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
50 if (!priv)
51 return dev_err_probe(dev, -ENOMEM,
52 "failed to allocate priv\n");
53
54 + cnt = of_property_count_u32_elems(dev->of_node, "qcom,dac");
55 + if (cnt == 2) {
56 + ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 0, &mdac);
57 + if (!ret)
58 + priv->mdac = mdac;
59 +
60 + ret = of_property_read_u32_index(dev->of_node, "qcom,dac", 1, &edac);
61 + if (!ret)
62 + priv->edac = edac;
63 + }
64 +
65 priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
66 if (priv->num_clks < 0)
67 return dev_err_probe(dev, priv->num_clks,
68 @@ -84,6 +103,8 @@ static int ipq5018_probe(struct phy_devi
69 return dev_err_probe(dev, ret,
70 "fail to register clock provider\n");
71
72 + phydev->priv = priv;
73 +
74 return 0;
75 }
76
77 @@ -112,12 +133,34 @@ static int ipq5018_cable_test_start(stru
78 return 0;
79 }
80
81 +static int ipq5018_config_init(struct phy_device *phydev)
82 +{
83 + struct ipq5018_phy *priv = phydev->priv;
84 + int ret;
85 +
86 + /* setting mdac in MMD1 */
87 + if (priv->mdac) {
88 + ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
89 + IPQ5018_PHY_DAC_MASK, priv->mdac);
90 + if (ret)
91 + return ret;
92 + }
93 +
94 + /* setting edac in debug register */
95 + if (priv->edac)
96 + return at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
97 + IPQ5018_PHY_DAC_MASK, priv->edac);
98 +
99 + return 0;
100 +}
101 +
102 static struct phy_driver ipq5018_internal_phy_driver[] = {
103 {
104 PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
105 .name = "Qualcomm IPQ5018 internal PHY",
106 .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
107 .probe = ipq5018_probe,
108 + .config_init = ipq5018_config_init,
109 .soft_reset = ipq5018_soft_reset,
110 .read_status = at803x_read_status,
111 .config_intr = at803x_config_intr,