1 From a6e68f0f8769f79c67cdcfb6302feecd36197dec Mon Sep 17 00:00:00 2001
2 From: Frank Sae <Frank.Sae@motor-comm.com>
3 Date: Thu, 2 Feb 2023 11:00:35 +0800
4 Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8521 gigabit
7 Add dts support for Motorcomm yt8521 gigabit ethernet phy.
8 Add ytphy_rgmii_clk_delay_config function to support dst config for
9 the delay of rgmii clk. This funciont is common for yt8521, yt8531s
11 This patch has been verified on AM335x platform.
13 Signed-off-by: Frank Sae <Frank.Sae@motor-comm.com>
14 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
17 drivers/net/phy/motorcomm.c | 253 ++++++++++++++++++++++++++++--------
18 1 file changed, 199 insertions(+), 54 deletions(-)
20 --- a/drivers/net/phy/motorcomm.c
21 +++ b/drivers/net/phy/motorcomm.c
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/phy.h>
26 +#include <linux/of.h>
28 #define PHY_ID_YT8511 0x0000010a
29 #define PHY_ID_YT8521 0x0000011a
31 * 1b1 use inverted tx_clk_rgmii.
33 #define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14)
34 -/* TX Gig-E Delay is bits 3:0, default 0x1
35 - * TX Fast-E Delay is bits 7:4, default 0xf
36 - * RX Delay is bits 13:10, default 0x0
38 - * On = 2250ps, off = 0ps
40 #define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10)
41 -#define YT8521_RC1R_RX_DELAY_EN (0xF << 10)
42 -#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10)
43 #define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
44 -#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4)
45 -#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4)
46 #define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
47 -#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0)
48 -#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0)
49 #define YT8521_RC1R_RGMII_0_000_NS 0
50 #define YT8521_RC1R_RGMII_0_150_NS 1
51 #define YT8521_RC1R_RGMII_0_300_NS 2
54 /* Extended Register end */
56 +#define YTPHY_DTS_OUTPUT_CLK_DIS 0
57 +#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
58 +#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
61 /* combo_advertising is used for case of YT8521 in combo mode,
62 * this means that yt8521 may work in utp or fiber mode which depends
63 @@ -641,6 +634,142 @@ static int yt8521_write_page(struct phy_
67 + * struct ytphy_cfg_reg_map - map a config value to a register value
68 + * @cfg: value in device configuration
69 + * @reg: value in the register
71 +struct ytphy_cfg_reg_map {
76 +static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
77 + /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */
78 + { 0, YT8521_RC1R_RGMII_0_000_NS },
79 + { 150, YT8521_RC1R_RGMII_0_150_NS },
80 + { 300, YT8521_RC1R_RGMII_0_300_NS },
81 + { 450, YT8521_RC1R_RGMII_0_450_NS },
82 + { 600, YT8521_RC1R_RGMII_0_600_NS },
83 + { 750, YT8521_RC1R_RGMII_0_750_NS },
84 + { 900, YT8521_RC1R_RGMII_0_900_NS },
85 + { 1050, YT8521_RC1R_RGMII_1_050_NS },
86 + { 1200, YT8521_RC1R_RGMII_1_200_NS },
87 + { 1350, YT8521_RC1R_RGMII_1_350_NS },
88 + { 1500, YT8521_RC1R_RGMII_1_500_NS },
89 + { 1650, YT8521_RC1R_RGMII_1_650_NS },
90 + { 1800, YT8521_RC1R_RGMII_1_800_NS },
91 + { 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
92 + { 2100, YT8521_RC1R_RGMII_2_100_NS },
93 + { 2250, YT8521_RC1R_RGMII_2_250_NS },
95 + /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */
96 + { 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS },
97 + { 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS },
98 + { 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS },
99 + { 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS },
100 + { 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS },
101 + { 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS },
102 + { 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS },
103 + { 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS },
104 + { 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS },
105 + { 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS },
106 + { 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS },
107 + { 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS },
108 + { 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS },
109 + { 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS },
110 + { 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS },
111 + { 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS }
114 +static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
115 + const char *prop_name,
116 + const struct ytphy_cfg_reg_map *tbl,
121 + struct device_node *node = phydev->mdio.dev.of_node;
122 + int tb_size_half = tb_size / 2;
126 + if (of_property_read_u32(node, prop_name, &val))
129 + /* when rxc_dly_en is NULL, it is get the delay for tx, only half of
130 + * tb_size is valid.
133 + tb_size = tb_size_half;
135 + for (i = 0; i < tb_size; i++) {
136 + if (tbl[i].cfg == val) {
137 + if (rxc_dly_en && i < tb_size_half)
143 + phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n",
144 + val, prop_name, dflt);
147 + /* when rxc_dly_en is not NULL, it is get the delay for rx.
148 + * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
149 + * so YT8521_CCR_RXC_DLY_EN should not be set.
157 +static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
159 + int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
160 + u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN;
161 + u32 rx_reg, tx_reg;
165 + rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps",
166 + ytphy_rgmii_delays, tb_size,
168 + YT8521_RC1R_RGMII_1_950_NS);
169 + tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps",
170 + ytphy_rgmii_delays, tb_size, NULL,
171 + YT8521_RC1R_RGMII_1_950_NS);
173 + switch (phydev->interface) {
174 + case PHY_INTERFACE_MODE_RGMII:
177 + case PHY_INTERFACE_MODE_RGMII_RXID:
178 + val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg);
180 + case PHY_INTERFACE_MODE_RGMII_TXID:
182 + val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg);
184 + case PHY_INTERFACE_MODE_RGMII_ID:
185 + val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) |
186 + FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg);
188 + default: /* do not support other modes */
189 + return -EOPNOTSUPP;
192 + ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG,
193 + YT8521_CCR_RXC_DLY_EN, rxc_dly_en);
197 + /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */
198 + mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK;
199 + return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val);
203 * yt8521_probe() - read chip config then set suitable polling_mode
204 * @phydev: a pointer to a &struct phy_device
206 @@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_
208 static int yt8521_probe(struct phy_device *phydev)
210 + struct device_node *node = phydev->mdio.dev.of_node;
211 struct device *dev = &phydev->mdio.dev;
212 struct yt8521_priv *priv;
218 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
219 @@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_devic
224 + if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz", &freq))
225 + freq = YTPHY_DTS_OUTPUT_CLK_DIS;
227 + if (phydev->drv->phy_id == PHY_ID_YT8521) {
229 + case YTPHY_DTS_OUTPUT_CLK_DIS:
230 + mask = YT8521_SCR_SYNCE_ENABLE;
233 + case YTPHY_DTS_OUTPUT_CLK_25M:
234 + mask = YT8521_SCR_SYNCE_ENABLE |
235 + YT8521_SCR_CLK_SRC_MASK |
236 + YT8521_SCR_CLK_FRE_SEL_125M;
237 + val = YT8521_SCR_SYNCE_ENABLE |
238 + FIELD_PREP(YT8521_SCR_CLK_SRC_MASK,
239 + YT8521_SCR_CLK_SRC_REF_25M);
241 + case YTPHY_DTS_OUTPUT_CLK_125M:
242 + mask = YT8521_SCR_SYNCE_ENABLE |
243 + YT8521_SCR_CLK_SRC_MASK |
244 + YT8521_SCR_CLK_FRE_SEL_125M;
245 + val = YT8521_SCR_SYNCE_ENABLE |
246 + YT8521_SCR_CLK_FRE_SEL_125M |
247 + FIELD_PREP(YT8521_SCR_CLK_SRC_MASK,
248 + YT8521_SCR_CLK_SRC_PLL_125M);
251 + phydev_warn(phydev, "Freq err:%u\n", freq);
254 + } else if (phydev->drv->phy_id == PHY_ID_YT8531S) {
257 + phydev_warn(phydev, "PHY id err\n");
261 + return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask,
266 @@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_devi
268 static int yt8521_config_init(struct phy_device *phydev)
270 + struct device_node *node = phydev->mdio.dev.of_node;
275 old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE);
277 goto err_restore_page;
279 - switch (phydev->interface) {
280 - case PHY_INTERFACE_MODE_RGMII:
281 - val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS;
282 - val |= YT8521_RC1R_RX_DELAY_DIS;
284 - case PHY_INTERFACE_MODE_RGMII_RXID:
285 - val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS;
286 - val |= YT8521_RC1R_RX_DELAY_EN;
288 - case PHY_INTERFACE_MODE_RGMII_TXID:
289 - val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN;
290 - val |= YT8521_RC1R_RX_DELAY_DIS;
292 - case PHY_INTERFACE_MODE_RGMII_ID:
293 - val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN;
294 - val |= YT8521_RC1R_RX_DELAY_EN;
296 - case PHY_INTERFACE_MODE_SGMII:
298 - default: /* do not support other modes */
300 - goto err_restore_page;
303 /* set rgmii delay mode */
304 if (phydev->interface != PHY_INTERFACE_MODE_SGMII) {
305 - ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG,
306 - (YT8521_RC1R_RX_DELAY_MASK |
307 - YT8521_RC1R_FE_TX_DELAY_MASK |
308 - YT8521_RC1R_GE_TX_DELAY_MASK),
310 + ret = ytphy_rgmii_clk_delay_config(phydev);
312 goto err_restore_page;
315 - /* disable auto sleep */
316 - ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG,
317 - YT8521_ESC1R_SLEEP_SW, 0);
319 - goto err_restore_page;
321 - /* enable RXC clock when no wire plug */
322 - ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG,
323 - YT8521_CGR_RX_CLK_EN, 0);
325 - goto err_restore_page;
326 + if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) {
327 + /* disable auto sleep */
328 + ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG,
329 + YT8521_ESC1R_SLEEP_SW, 0);
331 + goto err_restore_page;
334 + if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) {
335 + /* enable RXC clock when no wire plug */
336 + ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG,
337 + YT8521_CGR_RX_CLK_EN, 0);
339 + goto err_restore_page;
342 return phy_restore_page(phydev, old_page, ret);