blob: 4d67203ee7084960579e2b3ed3d179bf8178a48f [file] [log] [blame]
Yanhong Wang1d6c3412023-06-15 17:36:42 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Motorcomm 8531 PHY driver.
4 *
5 * Copyright (C) 2023 StarFive Technology Co., Ltd.
6 */
7
8#include <config.h>
Yanhong Wang1d6c3412023-06-15 17:36:42 +08009#include <malloc.h>
10#include <phy.h>
11#include <linux/bitfield.h>
12
Nicolas Frattarolif08686a2023-08-05 12:35:01 +020013#define PHY_ID_YT8511 0x0000010a
Yanhong Wang1d6c3412023-06-15 17:36:42 +080014#define PHY_ID_YT8531 0x4f51e91b
Frank Sae63f2cad2024-09-12 05:02:25 -070015#define PHY_ID_YT8821 0x4f51ea19
Yanhong Wang1d6c3412023-06-15 17:36:42 +080016#define PHY_ID_MASK GENMASK(31, 0)
17
18/* Extended Register's Address Offset Register */
19#define YTPHY_PAGE_SELECT 0x1E
20
21/* Extended Register's Data Register */
22#define YTPHY_PAGE_DATA 0x1F
23
24#define YTPHY_SYNCE_CFG_REG 0xA012
25
Lukasz Tekieli3282aee2024-01-28 20:22:47 +010026#define YT8531_PAD_DRIVE_STRENGTH_CFG_REG 0xA010
27#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13)
28#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */
29#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */
30#define YT8531_RGMII_RX_DS_DEFAULT 0x3
31
Yanhong Wang1d6c3412023-06-15 17:36:42 +080032#define YTPHY_DTS_OUTPUT_CLK_DIS 0
33#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
34#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
35
Nicolas Frattarolif08686a2023-08-05 12:35:01 +020036#define YT8511_EXT_CLK_GATE 0x0c
37#define YT8511_EXT_DELAY_DRIVE 0x0d
38#define YT8511_EXT_SLEEP_CTRL 0x27
39
40/* 2b00 25m from pll
41 * 2b01 25m from xtl *default*
42 * 2b10 62.m from pll
43 * 2b11 125m from pll
44 */
45#define YT8511_CLK_125M (BIT(2) | BIT(1))
46#define YT8511_PLLON_SLP BIT(14)
47
48/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */
49#define YT8511_DELAY_RX BIT(0)
50
51/* TX Gig-E Delay is bits 7:4, default 0x5
52 * TX Fast-E Delay is bits 15:12, default 0xf
53 * Delay = 150ps * N - 250ps
54 * On = 2000ps, off = 50ps
55 */
56#define YT8511_DELAY_GE_TX_EN (0xf << 4)
57#define YT8511_DELAY_GE_TX_DIS (0x2 << 4)
58#define YT8511_DELAY_FE_TX_EN (0xf << 12)
59#define YT8511_DELAY_FE_TX_DIS (0x2 << 12)
60
Yanhong Wang1d6c3412023-06-15 17:36:42 +080061#define YT8531_SCR_SYNCE_ENABLE BIT(6)
62/* 1b0 output 25m clock *default*
63 * 1b1 output 125m clock
64 */
65#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4)
66#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1)
67#define YT8531_SCR_CLK_SRC_PLL_125M 0
68#define YT8531_SCR_CLK_SRC_UTP_RX 1
69#define YT8531_SCR_CLK_SRC_SDS_RX 2
70#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3
71#define YT8531_SCR_CLK_SRC_REF_25M 4
72#define YT8531_SCR_CLK_SRC_SSC_25M 5
73
74/* 1b0 use original tx_clk_rgmii *default*
75 * 1b1 use inverted tx_clk_rgmii.
76 */
77#define YT8531_RC1R_TX_CLK_SEL_INVERTED BIT(14)
78#define YT8531_RC1R_RX_DELAY_MASK GENMASK(13, 10)
79#define YT8531_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
80#define YT8531_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
81#define YT8531_RC1R_RGMII_0_000_NS 0
82#define YT8531_RC1R_RGMII_0_150_NS 1
83#define YT8531_RC1R_RGMII_0_300_NS 2
84#define YT8531_RC1R_RGMII_0_450_NS 3
85#define YT8531_RC1R_RGMII_0_600_NS 4
86#define YT8531_RC1R_RGMII_0_750_NS 5
87#define YT8531_RC1R_RGMII_0_900_NS 6
88#define YT8531_RC1R_RGMII_1_050_NS 7
89#define YT8531_RC1R_RGMII_1_200_NS 8
90#define YT8531_RC1R_RGMII_1_350_NS 9
91#define YT8531_RC1R_RGMII_1_500_NS 10
92#define YT8531_RC1R_RGMII_1_650_NS 11
93#define YT8531_RC1R_RGMII_1_800_NS 12
94#define YT8531_RC1R_RGMII_1_950_NS 13
95#define YT8531_RC1R_RGMII_2_100_NS 14
96#define YT8531_RC1R_RGMII_2_250_NS 15
97
98/* Phy gmii clock gating Register */
99#define YT8531_CLOCK_GATING_REG 0xC
100#define YT8531_CGR_RX_CLK_EN BIT(12)
101
102/* Specific Status Register */
103#define YTPHY_SPECIFIC_STATUS_REG 0x11
104#define YTPHY_DUPLEX_MASK BIT(13)
105#define YTPHY_DUPLEX_SHIFT 13
Frank Sae8e896f22024-09-12 05:02:24 -0700106#define YTPHY_SPEED_MASK ((0x3 << 14) | BIT(9))
107#define YTPHY_SPEED_10M ((0x0 << 14))
108#define YTPHY_SPEED_100M ((0x1 << 14))
109#define YTPHY_SPEED_1000M ((0x2 << 14))
Frank Sae63f2cad2024-09-12 05:02:25 -0700110#define YTPHY_SPEED_10G ((0x3 << 14))
111#define YTPHY_SPEED_2500M ((0x0 << 14) | BIT(9))
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800112
113#define YT8531_EXTREG_SLEEP_CONTROL1_REG 0x27
114#define YT8531_ESC1R_SLEEP_SW BIT(15)
115#define YT8531_ESC1R_PLLON_SLP BIT(14)
116
117#define YT8531_RGMII_CONFIG1_REG 0xA003
118
119#define YT8531_CHIP_CONFIG_REG 0xA001
120#define YT8531_CCR_SW_RST BIT(15)
121/* 1b0 disable 1.9ns rxc clock delay *default*
122 * 1b1 enable 1.9ns rxc clock delay
123 */
124#define YT8531_CCR_RXC_DLY_EN BIT(8)
125#define YT8531_CCR_RXC_DLY_1_900_NS 1900
126
Lukasz Tekieli3282aee2024-01-28 20:22:47 +0100127#define YT8531_CCR_CFG_LDO_MASK GENMASK(5, 4)
128#define YT8531_CCR_CFG_LDO_3V3 0x0
129#define YT8531_CCR_CFG_LDO_1V8 0x2
130
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800131/* bits in struct ytphy_plat_priv->flag */
132#define TX_CLK_ADJ_ENABLED BIT(0)
133#define AUTO_SLEEP_DISABLED BIT(1)
134#define KEEP_PLL_ENABLED BIT(2)
135#define TX_CLK_10_INVERTED BIT(3)
136#define TX_CLK_100_INVERTED BIT(4)
137#define TX_CLK_1000_INVERTED BIT(5)
138
Frank Sae63f2cad2024-09-12 05:02:25 -0700139#define YT8821_SDS_EXT_CSR_CTRL_REG 0x23
140#define YT8821_SDS_EXT_CSR_VCO_LDO_EN BIT(15)
141#define YT8821_SDS_EXT_CSR_VCO_BIAS_LPF_EN BIT(8)
142
143#define YT8821_UTP_EXT_PI_CTRL_REG 0x56
144#define YT8821_UTP_EXT_PI_RST_N_FIFO BIT(5)
145#define YT8821_UTP_EXT_PI_TX_CLK_SEL_AFE BIT(4)
146#define YT8821_UTP_EXT_PI_RX_CLK_3_SEL_AFE BIT(3)
147#define YT8821_UTP_EXT_PI_RX_CLK_2_SEL_AFE BIT(2)
148#define YT8821_UTP_EXT_PI_RX_CLK_1_SEL_AFE BIT(1)
149#define YT8821_UTP_EXT_PI_RX_CLK_0_SEL_AFE BIT(0)
150
151#define YT8821_UTP_EXT_VCT_CFG6_CTRL_REG 0x97
152#define YT8821_UTP_EXT_FECHO_AMP_TH_HUGE GENMASK(15, 8)
153
154#define YT8821_UTP_EXT_ECHO_CTRL_REG 0x336
155#define YT8821_UTP_EXT_TRACE_LNG_GAIN_THR_1000 GENMASK(14, 8)
156
157#define YT8821_UTP_EXT_GAIN_CTRL_REG 0x340
158#define YT8821_UTP_EXT_TRACE_MED_GAIN_THR_1000 GENMASK(6, 0)
159
160#define YT8821_UTP_EXT_RPDN_CTRL_REG 0x34E
161#define YT8821_UTP_EXT_RPDN_BP_FFE_LNG_2500 BIT(15)
162#define YT8821_UTP_EXT_RPDN_BP_FFE_SHT_2500 BIT(7)
163#define YT8821_UTP_EXT_RPDN_IPR_SHT_2500 GENMASK(6, 0)
164
165#define YT8821_UTP_EXT_TH_20DB_2500_CTRL_REG 0x36A
166#define YT8821_UTP_EXT_TH_20DB_2500 GENMASK(15, 0)
167
168#define YT8821_UTP_EXT_TRACE_CTRL_REG 0x372
169#define YT8821_UTP_EXT_TRACE_LNG_GAIN_THE_2500 GENMASK(14, 8)
170#define YT8821_UTP_EXT_TRACE_MED_GAIN_THE_2500 GENMASK(6, 0)
171
172#define YT8821_UTP_EXT_ALPHA_IPR_CTRL_REG 0x374
173#define YT8821_UTP_EXT_ALPHA_SHT_2500 GENMASK(14, 8)
174#define YT8821_UTP_EXT_IPR_LNG_2500 GENMASK(6, 0)
175
176#define YT8821_UTP_EXT_PLL_CTRL_REG 0x450
177#define YT8821_UTP_EXT_PLL_SPARE_CFG GENMASK(7, 0)
178
179#define YT8821_UTP_EXT_DAC_IMID_CH_2_3_CTRL_REG 0x466
180#define YT8821_UTP_EXT_DAC_IMID_CH_3_10_ORG GENMASK(14, 8)
181#define YT8821_UTP_EXT_DAC_IMID_CH_2_10_ORG GENMASK(6, 0)
182
183#define YT8821_UTP_EXT_DAC_IMID_CH_0_1_CTRL_REG 0x467
184#define YT8821_UTP_EXT_DAC_IMID_CH_1_10_ORG GENMASK(14, 8)
185#define YT8821_UTP_EXT_DAC_IMID_CH_0_10_ORG GENMASK(6, 0)
186
187#define YT8821_UTP_EXT_DAC_IMSB_CH_2_3_CTRL_REG 0x468
188#define YT8821_UTP_EXT_DAC_IMSB_CH_3_10_ORG GENMASK(14, 8)
189#define YT8821_UTP_EXT_DAC_IMSB_CH_2_10_ORG GENMASK(6, 0)
190
191#define YT8821_UTP_EXT_DAC_IMSB_CH_0_1_CTRL_REG 0x469
192#define YT8821_UTP_EXT_DAC_IMSB_CH_1_10_ORG GENMASK(14, 8)
193#define YT8821_UTP_EXT_DAC_IMSB_CH_0_10_ORG GENMASK(6, 0)
194
195#define YT8821_UTP_EXT_MU_COARSE_FR_CTRL_REG 0x4B3
196#define YT8821_UTP_EXT_MU_COARSE_FR_F_FFE GENMASK(14, 12)
197#define YT8821_UTP_EXT_MU_COARSE_FR_F_FBE GENMASK(10, 8)
198
199#define YT8821_UTP_EXT_MU_FINE_FR_CTRL_REG 0x4B5
200#define YT8821_UTP_EXT_MU_FINE_FR_F_FFE GENMASK(14, 12)
201#define YT8821_UTP_EXT_MU_FINE_FR_F_FBE GENMASK(10, 8)
202
203#define YT8821_UTP_EXT_VGA_LPF1_CAP_CTRL_REG 0x4D2
204#define YT8821_UTP_EXT_VGA_LPF1_CAP_OTHER GENMASK(7, 4)
205#define YT8821_UTP_EXT_VGA_LPF1_CAP_2500 GENMASK(3, 0)
206
207#define YT8821_UTP_EXT_VGA_LPF2_CAP_CTRL_REG 0x4D3
208#define YT8821_UTP_EXT_VGA_LPF2_CAP_OTHER GENMASK(7, 4)
209#define YT8821_UTP_EXT_VGA_LPF2_CAP_2500 GENMASK(3, 0)
210
211#define YT8821_UTP_EXT_TXGE_NFR_FR_THP_CTRL_REG 0x660
212#define YT8821_UTP_EXT_NFR_TX_ABILITY BIT(3)
213
214#define YT8821_CHIP_MODE_FORCE_BX2500 1
215
216/* chip config register */
217#define YTPHY_CCR_MODE_SEL_MASK GENMASK(2, 0)
218
219#define YTPHY_REG_SPACE_SELECT_REG 0xA000
220#define YTPHY_RSSR_SPACE_MASK BIT(1)
221#define YTPHY_RSSR_FIBER_SPACE (0x1 << 1)
222#define YTPHY_RSSR_UTP_SPACE (0x0 << 1)
223
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800224struct ytphy_plat_priv {
225 u32 rx_delay_ps;
226 u32 tx_delay_ps;
227 u32 clk_out_frequency;
228 u32 flag;
229};
230
231/**
232 * struct ytphy_cfg_reg_map - map a config value to a register value
233 * @cfg: value in device configuration
234 * @reg: value in the register
235 */
236struct ytphy_cfg_reg_map {
237 u32 cfg;
238 u32 reg;
239};
240
241static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
242 /* for tx delay / rx delay with YT8531_CCR_RXC_DLY_EN is not set. */
243 { 0, YT8531_RC1R_RGMII_0_000_NS },
244 { 150, YT8531_RC1R_RGMII_0_150_NS },
245 { 300, YT8531_RC1R_RGMII_0_300_NS },
246 { 450, YT8531_RC1R_RGMII_0_450_NS },
247 { 600, YT8531_RC1R_RGMII_0_600_NS },
248 { 750, YT8531_RC1R_RGMII_0_750_NS },
249 { 900, YT8531_RC1R_RGMII_0_900_NS },
250 { 1050, YT8531_RC1R_RGMII_1_050_NS },
251 { 1200, YT8531_RC1R_RGMII_1_200_NS },
252 { 1350, YT8531_RC1R_RGMII_1_350_NS },
253 { 1500, YT8531_RC1R_RGMII_1_500_NS },
254 { 1650, YT8531_RC1R_RGMII_1_650_NS },
255 { 1800, YT8531_RC1R_RGMII_1_800_NS },
256 { 1950, YT8531_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
257 { 2100, YT8531_RC1R_RGMII_2_100_NS },
258 { 2250, YT8531_RC1R_RGMII_2_250_NS },
259
260 /* only for rx delay with YT8531_CCR_RXC_DLY_EN is set. */
261 { 0 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_000_NS },
262 { 150 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_150_NS },
263 { 300 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_300_NS },
264 { 450 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_450_NS },
265 { 600 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_600_NS },
266 { 750 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_750_NS },
267 { 900 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_900_NS },
268 { 1050 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_050_NS },
269 { 1200 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_200_NS },
270 { 1350 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_350_NS },
271 { 1500 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_500_NS },
272 { 1650 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_650_NS },
273 { 1800 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_800_NS },
274 { 1950 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_950_NS },
275 { 2100 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_100_NS },
276 { 2250 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_250_NS }
277};
278
279static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
280 u32 val,
281 u16 *rxc_dly_en)
282{
283 int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
284 int tb_size_half = tb_size / 2;
285 int i;
286
287 /* when rxc_dly_en is NULL, it is get the delay for tx, only half of
288 * tb_size is valid.
289 */
290 if (!rxc_dly_en)
291 tb_size = tb_size_half;
292
293 for (i = 0; i < tb_size; i++) {
294 if (ytphy_rgmii_delays[i].cfg == val) {
295 if (rxc_dly_en && i < tb_size_half)
296 *rxc_dly_en = 0;
297 return ytphy_rgmii_delays[i].reg;
298 }
299 }
300
301 pr_warn("Unsupported value %d, using default (%u)\n",
302 val, YT8531_RC1R_RGMII_1_950_NS);
303
304 /* when rxc_dly_en is not NULL, it is get the delay for rx.
305 * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
306 * so YT8531_CCR_RXC_DLY_EN should not be set.
307 */
308 if (rxc_dly_en)
309 *rxc_dly_en = 0;
310
311 return YT8531_RC1R_RGMII_1_950_NS;
312}
313
314static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask,
315 u16 set)
316{
317 int ret;
318
319 ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum);
320 if (ret < 0)
321 return ret;
322
323 return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set);
324}
325
Lukasz Tekieli3282aee2024-01-28 20:22:47 +0100326static int ytphy_read_ext(struct phy_device *phydev, u16 regnum)
327{
328 int ret;
329
330 ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum);
331 if (ret < 0)
332 return ret;
333
334 return phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA);
335}
336
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800337static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
338{
339 struct ytphy_plat_priv *priv = phydev->priv;
340 u16 rxc_dly_en = YT8531_CCR_RXC_DLY_EN;
341 u32 rx_reg, tx_reg;
342 u16 mask, val = 0;
343 int ret;
344
345 rx_reg = ytphy_get_delay_reg_value(phydev, priv->rx_delay_ps,
346 &rxc_dly_en);
347 tx_reg = ytphy_get_delay_reg_value(phydev, priv->tx_delay_ps,
348 NULL);
349
350 switch (phydev->interface) {
351 case PHY_INTERFACE_MODE_RGMII:
352 rxc_dly_en = 0;
353 break;
354 case PHY_INTERFACE_MODE_RGMII_RXID:
355 val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg);
356 break;
357 case PHY_INTERFACE_MODE_RGMII_TXID:
358 rxc_dly_en = 0;
359 val |= FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
360 break;
361 case PHY_INTERFACE_MODE_RGMII_ID:
362 val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg) |
363 FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
364 break;
365 default: /* do not support other modes */
366 return -EOPNOTSUPP;
367 }
368
369 ret = ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG,
370 YT8531_CCR_RXC_DLY_EN, rxc_dly_en);
371 if (ret < 0)
372 return ret;
373
374 /* Generally, it is not necessary to adjust YT8531_RC1R_FE_TX_DELAY */
375 mask = YT8531_RC1R_RX_DELAY_MASK | YT8531_RC1R_GE_TX_DELAY_MASK;
376 return ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, mask, val);
377}
378
379static int yt8531_parse_status(struct phy_device *phydev)
380{
381 int val;
382 int speed, speed_mode;
383
384 val = phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_SPECIFIC_STATUS_REG);
385 if (val < 0)
386 return val;
387
Frank Sae8e896f22024-09-12 05:02:24 -0700388 speed_mode = (val & YTPHY_SPEED_MASK);
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800389 switch (speed_mode) {
Frank Sae8e896f22024-09-12 05:02:24 -0700390 case YTPHY_SPEED_1000M:
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800391 speed = SPEED_1000;
392 break;
Frank Sae8e896f22024-09-12 05:02:24 -0700393 case YTPHY_SPEED_100M:
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800394 speed = SPEED_100;
395 break;
Frank Sae8e896f22024-09-12 05:02:24 -0700396 case YTPHY_SPEED_10M:
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800397 speed = SPEED_10;
398 break;
399 }
400
401 phydev->speed = speed;
402 phydev->duplex = (val & YTPHY_DUPLEX_MASK) >> YTPHY_DUPLEX_SHIFT;
403
404 return 0;
405}
406
407static int yt8531_startup(struct phy_device *phydev)
408{
409 struct ytphy_plat_priv *priv = phydev->priv;
410 u16 val = 0;
411 int ret;
412
413 ret = genphy_update_link(phydev);
414 if (ret)
415 return ret;
416
417 ret = yt8531_parse_status(phydev);
418 if (ret)
419 return ret;
420
421 if (phydev->speed < 0)
422 return -EINVAL;
423
424 if (!(priv->flag & TX_CLK_ADJ_ENABLED))
425 return 0;
426
427 switch (phydev->speed) {
428 case SPEED_1000:
429 if (priv->flag & TX_CLK_1000_INVERTED)
430 val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
431 break;
432 case SPEED_100:
433 if (priv->flag & TX_CLK_100_INVERTED)
434 val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
435 break;
436 case SPEED_10:
437 if (priv->flag & TX_CLK_10_INVERTED)
438 val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
439 break;
440 default:
441 printf("UNKNOWN SPEED\n");
442 return -EINVAL;
443 }
444
445 ret = ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG,
446 YT8531_RC1R_TX_CLK_SEL_INVERTED, val);
447 if (ret < 0)
448 pr_warn("Modify TX_CLK_SEL err:%d\n", ret);
449
450 return 0;
451}
452
453static void ytphy_dt_parse(struct phy_device *phydev)
454{
455 struct ytphy_plat_priv *priv = phydev->priv;
456
457 priv->clk_out_frequency = ofnode_read_u32_default(phydev->node,
458 "motorcomm,clk-out-frequency-hz",
459 YTPHY_DTS_OUTPUT_CLK_DIS);
460 priv->rx_delay_ps = ofnode_read_u32_default(phydev->node,
461 "rx-internal-delay-ps",
462 YT8531_RC1R_RGMII_1_950_NS);
463 priv->tx_delay_ps = ofnode_read_u32_default(phydev->node,
464 "tx-internal-delay-ps",
465 YT8531_RC1R_RGMII_1_950_NS);
466
467 if (ofnode_read_bool(phydev->node, "motorcomm,auto-sleep-disabled"))
468 priv->flag |= AUTO_SLEEP_DISABLED;
469
470 if (ofnode_read_bool(phydev->node, "motorcomm,keep-pll-enabled"))
471 priv->flag |= KEEP_PLL_ENABLED;
472
473 if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-adj-enabled"))
474 priv->flag |= TX_CLK_ADJ_ENABLED;
475
476 if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-10-inverted"))
477 priv->flag |= TX_CLK_10_INVERTED;
478
479 if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-100-inverted"))
480 priv->flag |= TX_CLK_100_INVERTED;
481
482 if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-1000-inverted"))
483 priv->flag |= TX_CLK_1000_INVERTED;
484}
485
Nicolas Frattarolif08686a2023-08-05 12:35:01 +0200486static int yt8511_config(struct phy_device *phydev)
487{
488 u32 ge, fe;
489 int ret;
490
491 ret = genphy_config_aneg(phydev);
492 if (ret < 0)
493 return ret;
494
495 switch (phydev->interface) {
496 case PHY_INTERFACE_MODE_RGMII:
497 ge = YT8511_DELAY_GE_TX_DIS;
498 fe = YT8511_DELAY_FE_TX_DIS;
499 break;
500 case PHY_INTERFACE_MODE_RGMII_RXID:
501 ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS;
502 fe = YT8511_DELAY_FE_TX_DIS;
503 break;
504 case PHY_INTERFACE_MODE_RGMII_TXID:
505 ge = YT8511_DELAY_GE_TX_EN;
506 fe = YT8511_DELAY_FE_TX_EN;
507 break;
508 case PHY_INTERFACE_MODE_RGMII_ID:
509 ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN;
510 fe = YT8511_DELAY_FE_TX_EN;
511 break;
512 default: /* do not support other modes */
513 return -EOPNOTSUPP;
514 }
515
516 ret = ytphy_modify_ext(phydev, YT8511_EXT_CLK_GATE,
517 (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge);
518 if (ret < 0)
519 return ret;
520 /* set clock mode to 125m */
521 ret = ytphy_modify_ext(phydev, YT8511_EXT_CLK_GATE,
522 YT8511_CLK_125M, YT8511_CLK_125M);
523 if (ret < 0)
524 return ret;
525 ret = ytphy_modify_ext(phydev, YT8511_EXT_DELAY_DRIVE,
526 YT8511_DELAY_FE_TX_EN, fe);
527 if (ret < 0)
528 return ret;
529 /* sleep control, disable PLL in sleep for now */
530 ret = ytphy_modify_ext(phydev, YT8511_EXT_SLEEP_CTRL, YT8511_PLLON_SLP,
531 0);
532 if (ret < 0)
533 return ret;
534
535 return 0;
536}
537
Lukasz Tekieli3282aee2024-01-28 20:22:47 +0100538/**
539 * struct ytphy_ldo_vol_map - map a current value to a register value
540 * @vol: ldo voltage
541 * @ds: value in the register
542 * @cur: value in device configuration
543 */
544struct ytphy_ldo_vol_map {
545 u32 vol;
546 u32 ds;
547 u32 cur;
548};
549
550static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = {
551 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 0, .cur = 1200},
552 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 1, .cur = 2100},
553 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 2, .cur = 2700},
554 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 3, .cur = 2910},
555 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 4, .cur = 3110},
556 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 5, .cur = 3600},
557 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 6, .cur = 3970},
558 {.vol = YT8531_CCR_CFG_LDO_1V8, .ds = 7, .cur = 4350},
559 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 0, .cur = 3070},
560 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 1, .cur = 4080},
561 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 2, .cur = 4370},
562 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 3, .cur = 4680},
563 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 4, .cur = 5020},
564 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 5, .cur = 5450},
565 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 6, .cur = 5740},
566 {.vol = YT8531_CCR_CFG_LDO_3V3, .ds = 7, .cur = 6140},
567};
568
569static u32 yt8531_get_ldo_vol(struct phy_device *phydev)
570{
571 u32 val;
572
573 val = ytphy_read_ext(phydev, YT8531_CHIP_CONFIG_REG);
574 val = FIELD_GET(YT8531_CCR_CFG_LDO_MASK, val);
575
576 return val <= YT8531_CCR_CFG_LDO_1V8 ? val : YT8531_CCR_CFG_LDO_1V8;
577}
578
579static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur)
580{
581 u32 vol;
582 int i;
583
584 vol = yt8531_get_ldo_vol(phydev);
585 for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) {
586 if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur)
587 return yt8531_ldo_vol[i].ds;
588 }
589
590 return -EINVAL;
591}
592
593static int yt8531_set_ds(struct phy_device *phydev)
594{
595 u32 ds_field_low, ds_field_hi, val;
596 int ret, ds;
597
598 /* set rgmii rx clk driver strength */
599 if (!ofnode_read_u32(phydev->node, "motorcomm,rx-clk-drv-microamp", &val)) {
600 ds = yt8531_get_ds_map(phydev, val);
601 if (ds < 0) {
602 pr_warn("No matching current value was found.");
603 return -EINVAL;
604 }
605 } else {
606 ds = YT8531_RGMII_RX_DS_DEFAULT;
607 }
608
609 ret = ytphy_modify_ext(phydev,
610 YT8531_PAD_DRIVE_STRENGTH_CFG_REG,
611 YT8531_RGMII_RXC_DS_MASK,
612 FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds));
613 if (ret < 0)
614 return ret;
615
616 /* set rgmii rx data driver strength */
617 if (!ofnode_read_u32(phydev->node, "motorcomm,rx-data-drv-microamp", &val)) {
618 ds = yt8531_get_ds_map(phydev, val);
619 if (ds < 0) {
620 pr_warn("No matching current value was found.");
621 return -EINVAL;
622 }
623 } else {
624 ds = YT8531_RGMII_RX_DS_DEFAULT;
625 }
626
627 ds_field_hi = FIELD_GET(BIT(2), ds);
628 ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi);
629
630 ds_field_low = FIELD_GET(GENMASK(1, 0), ds);
631 ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low);
632
633 ret = ytphy_modify_ext(phydev,
634 YT8531_PAD_DRIVE_STRENGTH_CFG_REG,
635 YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK,
636 ds_field_low | ds_field_hi);
637 if (ret < 0)
638 return ret;
639
640 return 0;
641}
642
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800643static int yt8531_config(struct phy_device *phydev)
644{
645 struct ytphy_plat_priv *priv = phydev->priv;
646 u16 mask, val;
647 int ret;
648
649 ret = genphy_config_aneg(phydev);
650 if (ret < 0)
651 return ret;
652
653 ytphy_dt_parse(phydev);
654 switch (priv->clk_out_frequency) {
655 case YTPHY_DTS_OUTPUT_CLK_DIS:
656 mask = YT8531_SCR_SYNCE_ENABLE;
657 val = 0;
658 break;
659 case YTPHY_DTS_OUTPUT_CLK_25M:
660 mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
661 YT8531_SCR_CLK_FRE_SEL_125M;
662 val = YT8531_SCR_SYNCE_ENABLE |
663 FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
664 YT8531_SCR_CLK_SRC_REF_25M);
665 break;
666 case YTPHY_DTS_OUTPUT_CLK_125M:
667 mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
668 YT8531_SCR_CLK_FRE_SEL_125M;
669 val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M |
670 FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
671 YT8531_SCR_CLK_SRC_PLL_125M);
672 break;
673 default:
674 pr_warn("Freq err:%u\n", priv->clk_out_frequency);
675 return -EINVAL;
676 }
677
678 ret = ytphy_modify_ext(phydev, YTPHY_SYNCE_CFG_REG, mask,
679 val);
680 if (ret < 0)
681 return ret;
682
683 ret = ytphy_rgmii_clk_delay_config(phydev);
684 if (ret < 0)
685 return ret;
686
687 if (priv->flag & AUTO_SLEEP_DISABLED) {
688 /* disable auto sleep */
689 ret = ytphy_modify_ext(phydev,
690 YT8531_EXTREG_SLEEP_CONTROL1_REG,
691 YT8531_ESC1R_SLEEP_SW, 0);
692 if (ret < 0)
693 return ret;
694 }
695
696 if (priv->flag & KEEP_PLL_ENABLED) {
697 /* enable RXC clock when no wire plug */
698 ret = ytphy_modify_ext(phydev,
699 YT8531_CLOCK_GATING_REG,
700 YT8531_CGR_RX_CLK_EN, 0);
701 if (ret < 0)
702 return ret;
703 }
704
Lukasz Tekieli3282aee2024-01-28 20:22:47 +0100705 ret = yt8531_set_ds(phydev);
706 if (ret < 0)
707 return ret;
708
Yanhong Wang1d6c3412023-06-15 17:36:42 +0800709 return 0;
710}
711
712static int yt8531_probe(struct phy_device *phydev)
713{
714 struct ytphy_plat_priv *priv;
715
716 priv = calloc(1, sizeof(struct ytphy_plat_priv));
717 if (!priv)
718 return -ENOMEM;
719
720 phydev->priv = priv;
721
722 return 0;
723}
724
Frank Sae63f2cad2024-09-12 05:02:25 -0700725static int ytphy_save_page(struct phy_device *phydev)
726{
727 int old_page;
728
729 old_page = ytphy_read_ext(phydev, YTPHY_REG_SPACE_SELECT_REG);
730 if (old_page < 0)
731 return old_page;
732
733 if ((old_page & YTPHY_RSSR_SPACE_MASK) == YTPHY_RSSR_FIBER_SPACE)
734 return YTPHY_RSSR_FIBER_SPACE;
735
736 return YTPHY_RSSR_UTP_SPACE;
737};
738
739static int ytphy_restore_page(struct phy_device *phydev, int page,
740 int ret)
741{
742 int mask = YTPHY_RSSR_SPACE_MASK;
743 int set;
744 int r;
745
746 if ((page & YTPHY_RSSR_SPACE_MASK) == YTPHY_RSSR_FIBER_SPACE)
747 set = YTPHY_RSSR_FIBER_SPACE;
748 else
749 set = YTPHY_RSSR_UTP_SPACE;
750
751 r = ytphy_modify_ext(phydev, YTPHY_REG_SPACE_SELECT_REG, mask,
752 set);
753 if (ret >= 0 && r < 0)
754 ret = r;
755
756 return ret;
757};
758
759static int ytphy_write_ext(struct phy_device *phydev, u16 regnum,
760 u16 val)
761{
762 int ret;
763
764 ret = phy_write(phydev, MDIO_DEVAD_NONE,
765 YTPHY_PAGE_SELECT, regnum);
766 if (ret < 0)
767 return ret;
768
769 return phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, val);
770}
771
772static int yt8821_probe(struct phy_device *phydev)
773{
774 phydev->advertising = PHY_GBIT_FEATURES |
775 SUPPORTED_2500baseX_Full |
776 SUPPORTED_Pause |
777 SUPPORTED_Asym_Pause;
778 phydev->supported = phydev->advertising;
779
780 return 0;
781}
782
783static int yt8821_serdes_init(struct phy_device *phydev)
784{
785 int old_page;
786 u16 mask;
787 u16 set;
788 int ret;
789
790 old_page = ytphy_save_page(phydev);
791 if (old_page < 0)
792 return old_page;
793
794 ret = ytphy_modify_ext(phydev, YTPHY_REG_SPACE_SELECT_REG,
795 YTPHY_RSSR_SPACE_MASK,
796 YTPHY_RSSR_FIBER_SPACE);
797 if (ret < 0)
798 goto err_restore_page;
799
800 ret = phy_modify(phydev, MDIO_DEVAD_NONE, MII_BMCR,
801 BMCR_ANENABLE, 0);
802 if (ret < 0)
803 goto err_restore_page;
804
805 mask = YT8821_SDS_EXT_CSR_VCO_LDO_EN |
806 YT8821_SDS_EXT_CSR_VCO_BIAS_LPF_EN;
807 set = YT8821_SDS_EXT_CSR_VCO_LDO_EN;
808 ret = ytphy_modify_ext(phydev, YT8821_SDS_EXT_CSR_CTRL_REG, mask,
809 set);
810
811err_restore_page:
812 return ytphy_restore_page(phydev, old_page, ret);
813}
814
815static int yt8821_utp_init(struct phy_device *phydev)
816{
817 int old_page;
818 u16 mask;
819 u16 save;
820 u16 set;
821 int ret;
822
823 old_page = ytphy_save_page(phydev);
824 if (old_page < 0)
825 return old_page;
826
827 ret = ytphy_modify_ext(phydev, YTPHY_REG_SPACE_SELECT_REG,
828 YTPHY_RSSR_SPACE_MASK,
829 YTPHY_RSSR_UTP_SPACE);
830 if (ret < 0)
831 goto err_restore_page;
832
833 mask = YT8821_UTP_EXT_RPDN_BP_FFE_LNG_2500 |
834 YT8821_UTP_EXT_RPDN_BP_FFE_SHT_2500 |
835 YT8821_UTP_EXT_RPDN_IPR_SHT_2500;
836 set = YT8821_UTP_EXT_RPDN_BP_FFE_LNG_2500 |
837 YT8821_UTP_EXT_RPDN_BP_FFE_SHT_2500;
838 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_RPDN_CTRL_REG,
839 mask, set);
840 if (ret < 0)
841 goto err_restore_page;
842
843 mask = YT8821_UTP_EXT_VGA_LPF1_CAP_OTHER |
844 YT8821_UTP_EXT_VGA_LPF1_CAP_2500;
845 ret = ytphy_modify_ext(phydev,
846 YT8821_UTP_EXT_VGA_LPF1_CAP_CTRL_REG,
847 mask, 0);
848 if (ret < 0)
849 goto err_restore_page;
850
851 mask = YT8821_UTP_EXT_VGA_LPF2_CAP_OTHER |
852 YT8821_UTP_EXT_VGA_LPF2_CAP_2500;
853 ret = ytphy_modify_ext(phydev,
854 YT8821_UTP_EXT_VGA_LPF2_CAP_CTRL_REG,
855 mask, 0);
856 if (ret < 0)
857 goto err_restore_page;
858
859 mask = YT8821_UTP_EXT_TRACE_LNG_GAIN_THE_2500 |
860 YT8821_UTP_EXT_TRACE_MED_GAIN_THE_2500;
861 set = FIELD_PREP(YT8821_UTP_EXT_TRACE_LNG_GAIN_THE_2500, 0x5a) |
862 FIELD_PREP(YT8821_UTP_EXT_TRACE_MED_GAIN_THE_2500, 0x3c);
863 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_TRACE_CTRL_REG,
864 mask, set);
865 if (ret < 0)
866 goto err_restore_page;
867
868 mask = YT8821_UTP_EXT_IPR_LNG_2500;
869 set = FIELD_PREP(YT8821_UTP_EXT_IPR_LNG_2500, 0x6c);
870 ret = ytphy_modify_ext(phydev,
871 YT8821_UTP_EXT_ALPHA_IPR_CTRL_REG,
872 mask, set);
873 if (ret < 0)
874 goto err_restore_page;
875
876 mask = YT8821_UTP_EXT_TRACE_LNG_GAIN_THR_1000;
877 set = FIELD_PREP(YT8821_UTP_EXT_TRACE_LNG_GAIN_THR_1000, 0x2a);
878 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_ECHO_CTRL_REG,
879 mask, set);
880 if (ret < 0)
881 goto err_restore_page;
882
883 mask = YT8821_UTP_EXT_TRACE_MED_GAIN_THR_1000;
884 set = FIELD_PREP(YT8821_UTP_EXT_TRACE_MED_GAIN_THR_1000, 0x22);
885 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_GAIN_CTRL_REG,
886 mask, set);
887 if (ret < 0)
888 goto err_restore_page;
889
890 mask = YT8821_UTP_EXT_TH_20DB_2500;
891 set = FIELD_PREP(YT8821_UTP_EXT_TH_20DB_2500, 0x8000);
892 ret = ytphy_modify_ext(phydev,
893 YT8821_UTP_EXT_TH_20DB_2500_CTRL_REG,
894 mask, set);
895 if (ret < 0)
896 goto err_restore_page;
897
898 mask = YT8821_UTP_EXT_MU_COARSE_FR_F_FFE |
899 YT8821_UTP_EXT_MU_COARSE_FR_F_FBE;
900 set = FIELD_PREP(YT8821_UTP_EXT_MU_COARSE_FR_F_FFE, 0x7) |
901 FIELD_PREP(YT8821_UTP_EXT_MU_COARSE_FR_F_FBE, 0x7);
902 ret = ytphy_modify_ext(phydev,
903 YT8821_UTP_EXT_MU_COARSE_FR_CTRL_REG,
904 mask, set);
905 if (ret < 0)
906 goto err_restore_page;
907
908 mask = YT8821_UTP_EXT_MU_FINE_FR_F_FFE |
909 YT8821_UTP_EXT_MU_FINE_FR_F_FBE;
910 set = FIELD_PREP(YT8821_UTP_EXT_MU_FINE_FR_F_FFE, 0x2) |
911 FIELD_PREP(YT8821_UTP_EXT_MU_FINE_FR_F_FBE, 0x2);
912 ret = ytphy_modify_ext(phydev,
913 YT8821_UTP_EXT_MU_FINE_FR_CTRL_REG,
914 mask, set);
915 if (ret < 0)
916 goto err_restore_page;
917
918 /* save YT8821_UTP_EXT_PI_CTRL_REG's val for use later */
919 ret = ytphy_read_ext(phydev, YT8821_UTP_EXT_PI_CTRL_REG);
920 if (ret < 0)
921 goto err_restore_page;
922
923 save = ret;
924
925 mask = YT8821_UTP_EXT_PI_TX_CLK_SEL_AFE |
926 YT8821_UTP_EXT_PI_RX_CLK_3_SEL_AFE |
927 YT8821_UTP_EXT_PI_RX_CLK_2_SEL_AFE |
928 YT8821_UTP_EXT_PI_RX_CLK_1_SEL_AFE |
929 YT8821_UTP_EXT_PI_RX_CLK_0_SEL_AFE;
930 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_PI_CTRL_REG,
931 mask, 0);
932 if (ret < 0)
933 goto err_restore_page;
934
935 /* restore YT8821_UTP_EXT_PI_CTRL_REG's val */
936 ret = ytphy_write_ext(phydev, YT8821_UTP_EXT_PI_CTRL_REG, save);
937 if (ret < 0)
938 goto err_restore_page;
939
940 mask = YT8821_UTP_EXT_FECHO_AMP_TH_HUGE;
941 set = FIELD_PREP(YT8821_UTP_EXT_FECHO_AMP_TH_HUGE, 0x38);
942 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_VCT_CFG6_CTRL_REG,
943 mask, set);
944 if (ret < 0)
945 goto err_restore_page;
946
947 mask = YT8821_UTP_EXT_NFR_TX_ABILITY;
948 set = YT8821_UTP_EXT_NFR_TX_ABILITY;
949 ret = ytphy_modify_ext(phydev,
950 YT8821_UTP_EXT_TXGE_NFR_FR_THP_CTRL_REG,
951 mask, set);
952 if (ret < 0)
953 goto err_restore_page;
954
955 mask = YT8821_UTP_EXT_PLL_SPARE_CFG;
956 set = FIELD_PREP(YT8821_UTP_EXT_PLL_SPARE_CFG, 0xe9);
957 ret = ytphy_modify_ext(phydev, YT8821_UTP_EXT_PLL_CTRL_REG,
958 mask, set);
959 if (ret < 0)
960 goto err_restore_page;
961
962 mask = YT8821_UTP_EXT_DAC_IMID_CH_3_10_ORG |
963 YT8821_UTP_EXT_DAC_IMID_CH_2_10_ORG;
964 set = FIELD_PREP(YT8821_UTP_EXT_DAC_IMID_CH_3_10_ORG, 0x64) |
965 FIELD_PREP(YT8821_UTP_EXT_DAC_IMID_CH_2_10_ORG, 0x64);
966 ret = ytphy_modify_ext(phydev,
967 YT8821_UTP_EXT_DAC_IMID_CH_2_3_CTRL_REG,
968 mask, set);
969 if (ret < 0)
970 goto err_restore_page;
971
972 mask = YT8821_UTP_EXT_DAC_IMID_CH_1_10_ORG |
973 YT8821_UTP_EXT_DAC_IMID_CH_0_10_ORG;
974 set = FIELD_PREP(YT8821_UTP_EXT_DAC_IMID_CH_1_10_ORG, 0x64) |
975 FIELD_PREP(YT8821_UTP_EXT_DAC_IMID_CH_0_10_ORG, 0x64);
976 ret = ytphy_modify_ext(phydev,
977 YT8821_UTP_EXT_DAC_IMID_CH_0_1_CTRL_REG,
978 mask, set);
979 if (ret < 0)
980 goto err_restore_page;
981
982 mask = YT8821_UTP_EXT_DAC_IMSB_CH_3_10_ORG |
983 YT8821_UTP_EXT_DAC_IMSB_CH_2_10_ORG;
984 set = FIELD_PREP(YT8821_UTP_EXT_DAC_IMSB_CH_3_10_ORG, 0x64) |
985 FIELD_PREP(YT8821_UTP_EXT_DAC_IMSB_CH_2_10_ORG, 0x64);
986 ret = ytphy_modify_ext(phydev,
987 YT8821_UTP_EXT_DAC_IMSB_CH_2_3_CTRL_REG,
988 mask, set);
989 if (ret < 0)
990 goto err_restore_page;
991
992 mask = YT8821_UTP_EXT_DAC_IMSB_CH_1_10_ORG |
993 YT8821_UTP_EXT_DAC_IMSB_CH_0_10_ORG;
994 set = FIELD_PREP(YT8821_UTP_EXT_DAC_IMSB_CH_1_10_ORG, 0x64) |
995 FIELD_PREP(YT8821_UTP_EXT_DAC_IMSB_CH_0_10_ORG, 0x64);
996 ret = ytphy_modify_ext(phydev,
997 YT8821_UTP_EXT_DAC_IMSB_CH_0_1_CTRL_REG,
998 mask, set);
999
1000err_restore_page:
1001 return ytphy_restore_page(phydev, old_page, ret);
1002}
1003
1004static int yt8821_auto_sleep_config(struct phy_device *phydev,
1005 bool enable)
1006{
1007 int old_page;
1008 int ret;
1009
1010 old_page = ytphy_save_page(phydev);
1011 if (old_page < 0)
1012 return old_page;
1013
1014 ret = ytphy_modify_ext(phydev, YTPHY_REG_SPACE_SELECT_REG,
1015 YTPHY_RSSR_SPACE_MASK,
1016 YTPHY_RSSR_UTP_SPACE);
1017 if (ret < 0)
1018 goto err_restore_page;
1019
1020 ret = ytphy_modify_ext(phydev,
1021 YT8531_EXTREG_SLEEP_CONTROL1_REG,
1022 YT8531_ESC1R_SLEEP_SW,
1023 enable ? 1 : 0);
1024
1025err_restore_page:
1026 return ytphy_restore_page(phydev, old_page, ret);
1027}
1028
1029static int yt8821_soft_reset(struct phy_device *phydev)
1030{
1031 return ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG,
1032 YT8531_CCR_SW_RST, 0);
1033}
1034
1035static int yt8821_config(struct phy_device *phydev)
1036{
1037 u8 mode = YT8821_CHIP_MODE_FORCE_BX2500;
1038 int ret;
1039 u16 set;
1040
1041 set = FIELD_PREP(YTPHY_CCR_MODE_SEL_MASK, mode);
1042 ret = ytphy_modify_ext(phydev,
1043 YT8531_CHIP_CONFIG_REG,
1044 YTPHY_CCR_MODE_SEL_MASK,
1045 set);
1046 if (ret < 0)
1047 return ret;
1048
1049 ret = yt8821_serdes_init(phydev);
1050 if (ret < 0)
1051 return ret;
1052
1053 ret = yt8821_utp_init(phydev);
1054 if (ret < 0)
1055 return ret;
1056
1057 ret = yt8821_auto_sleep_config(phydev, false);
1058 if (ret < 0)
1059 return ret;
1060
1061 return yt8821_soft_reset(phydev);
1062}
1063
1064static void yt8821_parse_status(struct phy_device *phydev, int val)
1065{
1066 int speed_mode;
1067 int speed;
1068
1069 speed_mode = val & YTPHY_SPEED_MASK;
1070 switch (speed_mode) {
1071 case YTPHY_SPEED_2500M:
1072 speed = SPEED_2500;
1073 break;
1074 case YTPHY_SPEED_1000M:
1075 speed = SPEED_1000;
1076 break;
1077 case YTPHY_SPEED_100M:
1078 speed = SPEED_100;
1079 break;
1080 case YTPHY_SPEED_10M:
1081 speed = SPEED_10;
1082 break;
1083 }
1084
1085 phydev->speed = speed;
1086 phydev->duplex = FIELD_GET(YTPHY_DUPLEX_MASK, val);
1087}
1088
1089static int yt8821_startup(struct phy_device *phydev)
1090{
1091 u16 val;
1092 int ret;
1093
1094 ret = ytphy_modify_ext(phydev, YTPHY_REG_SPACE_SELECT_REG,
1095 YTPHY_RSSR_SPACE_MASK,
1096 YTPHY_RSSR_UTP_SPACE);
1097 if (ret)
1098 return ret;
1099
1100 ret = genphy_update_link(phydev);
1101 if (ret)
1102 return ret;
1103
1104 ret = phy_read(phydev, MDIO_DEVAD_NONE,
1105 YTPHY_SPECIFIC_STATUS_REG);
1106 if (ret < 0)
1107 return ret;
1108
1109 val = ret;
1110
1111 if (phydev->link)
1112 yt8821_parse_status(phydev, val);
1113
1114 return 0;
1115}
1116
Nicolas Frattarolif08686a2023-08-05 12:35:01 +02001117U_BOOT_PHY_DRIVER(motorcomm8511) = {
1118 .name = "YT8511 Gigabit Ethernet",
1119 .uid = PHY_ID_YT8511,
1120 .mask = PHY_ID_MASK,
1121 .features = PHY_GBIT_FEATURES,
1122 .config = &yt8511_config,
1123 .startup = &genphy_startup,
1124 .shutdown = &genphy_shutdown,
1125};
1126
Yanhong Wang1d6c3412023-06-15 17:36:42 +08001127U_BOOT_PHY_DRIVER(motorcomm8531) = {
1128 .name = "YT8531 Gigabit Ethernet",
1129 .uid = PHY_ID_YT8531,
1130 .mask = PHY_ID_MASK,
1131 .features = PHY_GBIT_FEATURES,
1132 .probe = &yt8531_probe,
1133 .config = &yt8531_config,
1134 .startup = &yt8531_startup,
1135 .shutdown = &genphy_shutdown,
1136};
Frank Sae63f2cad2024-09-12 05:02:25 -07001137
1138U_BOOT_PHY_DRIVER(motorcomm8821) = {
1139 .name = "YT8821 2.5G Ethernet",
1140 .uid = PHY_ID_YT8821,
1141 .mask = PHY_ID_MASK,
1142 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS | MDIO_MMD_AN),
1143 .probe = &yt8821_probe,
1144 .config = &yt8821_config,
1145 .startup = &yt8821_startup,
1146 .shutdown = &genphy_shutdown,
1147};