1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
5 #include "ngbe_phy_yt.h"
7 #define YT_PHY_RST_WAIT_PERIOD 5
9 s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw,
10 u32 reg_addr, u32 device_type, u16 *phy_data)
15 reg.device_type = device_type;
18 ngbe_mdi_map_register(®, ®22);
20 /* Read MII reg according to media type */
21 if (hw->phy.media_type == ngbe_media_type_fiber) {
22 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
23 reg22.device_type, YT_SMI_PHY_SDS);
24 ngbe_read_phy_reg_mdi(hw, reg22.addr,
25 reg22.device_type, phy_data);
26 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
27 reg22.device_type, 0);
29 ngbe_read_phy_reg_mdi(hw, reg22.addr,
30 reg22.device_type, phy_data);
36 s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw,
37 u32 reg_addr, u32 device_type, u16 phy_data)
42 reg.device_type = device_type;
45 ngbe_mdi_map_register(®, ®22);
47 /* Write MII reg according to media type */
48 if (hw->phy.media_type == ngbe_media_type_fiber) {
49 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
50 reg22.device_type, YT_SMI_PHY_SDS);
51 ngbe_write_phy_reg_mdi(hw, reg22.addr,
52 reg22.device_type, phy_data);
53 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
54 reg22.device_type, 0);
56 ngbe_write_phy_reg_mdi(hw, reg22.addr,
57 reg22.device_type, phy_data);
63 s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
64 u32 reg_addr, u32 device_type, u16 *phy_data)
66 ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
67 ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
72 s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
73 u32 reg_addr, u32 device_type, u16 phy_data)
75 ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
76 ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
81 s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
82 u32 reg_addr, u32 device_type, u16 *phy_data)
84 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
85 ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
86 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
91 s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
92 u32 reg_addr, u32 device_type, u16 phy_data)
94 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
95 ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
96 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
101 s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
105 DEBUGFUNC("ngbe_init_phy_yt");
107 /* close sds area register */
108 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
109 /* enable interrupts */
110 ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
111 YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
113 /* power down in fiber mode */
114 hw->phy.read_reg(hw, YT_BCR, 0, &value);
115 value |= YT_BCR_PWDN;
116 hw->phy.write_reg(hw, YT_BCR, 0, value);
118 /* power down in UTP mode */
119 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
120 value |= YT_BCR_PWDN;
121 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
126 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
127 bool autoneg_wait_to_complete)
133 DEBUGFUNC("ngbe_setup_phy_link_yt");
134 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
136 hw->phy.autoneg_advertised = 0;
138 /* check chip_mode first */
139 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
140 if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
142 if (!hw->mac.autoneg) {
144 case NGBE_LINK_SPEED_1GB_FULL:
145 value = YT_BCR_SPEED_SELECT1;
147 case NGBE_LINK_SPEED_100M_FULL:
148 value = YT_BCR_SPEED_SELECT0;
150 case NGBE_LINK_SPEED_10M_FULL:
154 value = YT_BCR_SPEED_SELECT0 |
155 YT_BCR_SPEED_SELECT1;
156 DEBUGOUT("unknown speed = 0x%x.\n",
161 value |= YT_BCR_DUPLEX | YT_BCR_RESET;
162 hw->phy.write_reg(hw, YT_BCR, 0, value);
167 /*disable 100/10base-T Self-negotiation ability*/
168 hw->phy.read_reg(hw, YT_ANA, 0, &value);
169 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
170 YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
171 hw->phy.write_reg(hw, YT_ANA, 0, value);
173 /*disable 1000base-T Self-negotiation ability*/
174 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
175 value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
176 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
178 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
179 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
180 value_r9 |= YT_MS_1000BASET_FULL;
182 if (speed & NGBE_LINK_SPEED_100M_FULL) {
183 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
184 value_r4 |= YT_ANA_100BASET_FULL;
186 if (speed & NGBE_LINK_SPEED_10M_FULL) {
187 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
188 value_r4 |= YT_ANA_10BASET_FULL;
191 /* enable 1000base-T Self-negotiation ability */
192 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
194 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
196 /* enable 100/10base-T Self-negotiation ability */
197 hw->phy.read_reg(hw, YT_ANA, 0, &value);
199 hw->phy.write_reg(hw, YT_ANA, 0, value);
201 /* software reset to make the above configuration take effect*/
202 hw->phy.read_reg(hw, YT_BCR, 0, &value);
203 value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
204 hw->phy.write_reg(hw, YT_BCR, 0, value);
206 /* power on in UTP mode */
207 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
208 value &= ~YT_BCR_PWDN;
209 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
210 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
212 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
214 /* RGMII_Config1 : Config rx and tx training delay */
215 value = YT_RGMII_CONF1_RXDELAY |
216 YT_RGMII_CONF1_TXDELAY_FE |
217 YT_RGMII_CONF1_TXDELAY;
218 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
219 value = YT_CHIP_MODE_SEL(1) |
222 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
225 ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
228 hw->phy.read_reg(hw, YT_BCR, 0, &value);
229 value &= ~YT_BCR_PWDN;
230 hw->phy.write_reg(hw, YT_BCR, 0, value);
231 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
232 /* power on in UTP mode */
233 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
234 value &= ~YT_BCR_PWDN;
235 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
236 /* power down in fiber mode */
237 hw->phy.read_reg(hw, YT_BCR, 0, &value);
238 value &= ~YT_BCR_PWDN;
239 hw->phy.write_reg(hw, YT_BCR, 0, value);
241 hw->phy.read_reg(hw, YT_SPST, 0, &value);
242 if (value & YT_SPST_LINK) {
244 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
247 /*disable 100/10base-T Self-negotiation ability*/
248 hw->phy.read_reg(hw, YT_ANA, 0, &value);
249 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
250 YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
251 hw->phy.write_reg(hw, YT_ANA, 0, value);
253 /*disable 1000base-T Self-negotiation ability*/
254 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
255 value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
256 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
258 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
259 hw->phy.autoneg_advertised |=
260 NGBE_LINK_SPEED_1GB_FULL;
261 value_r9 |= YT_MS_1000BASET_FULL;
263 if (speed & NGBE_LINK_SPEED_100M_FULL) {
264 hw->phy.autoneg_advertised |=
265 NGBE_LINK_SPEED_100M_FULL;
266 value_r4 |= YT_ANA_100BASET_FULL;
268 if (speed & NGBE_LINK_SPEED_10M_FULL) {
269 hw->phy.autoneg_advertised |=
270 NGBE_LINK_SPEED_10M_FULL;
271 value_r4 |= YT_ANA_10BASET_FULL;
274 /* enable 1000base-T Self-negotiation ability */
275 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
277 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
279 /* enable 100/10base-T Self-negotiation ability */
280 hw->phy.read_reg(hw, YT_ANA, 0, &value);
282 hw->phy.write_reg(hw, YT_ANA, 0, value);
284 /* software reset to make the above configuration
287 hw->phy.read_reg(hw, YT_BCR, 0, &value);
288 value |= YT_BCR_RESET;
289 hw->phy.write_reg(hw, YT_BCR, 0, value);
291 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
292 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
294 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
295 value |= YT_RGMII_CONF1_MODE;
296 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
298 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
299 value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
300 YT_RGMII_CONF2_LINKUP);
301 value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
302 YT_RGMII_CONF2_LINKUP;
303 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
305 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
306 value &= ~YT_SMI_PHY_SW_RST;
307 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
310 hw->phy.read_reg(hw, YT_BCR, 0, &value);
311 value &= ~YT_BCR_PWDN;
312 hw->phy.write_reg(hw, YT_BCR, 0, value);
315 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
316 ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
321 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
327 DEBUGFUNC("ngbe_reset_phy_yt");
329 if (hw->phy.type != ngbe_phy_yt8521s &&
330 hw->phy.type != ngbe_phy_yt8521s_sfi)
331 return NGBE_ERR_PHY_TYPE;
333 /* check chip_mode first */
334 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
335 if (ctrl & YT_CHIP_MODE_MASK) {
337 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
338 /* sds software reset */
339 ctrl |= YT_BCR_RESET;
340 status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
342 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
343 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
344 if (!(ctrl & YT_BCR_RESET))
350 status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
351 /* sds software reset */
352 ctrl |= YT_BCR_RESET;
353 status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
355 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
356 status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
357 if (!(ctrl & YT_BCR_RESET))
363 if (i == YT_PHY_RST_WAIT_PERIOD) {
364 DEBUGOUT("PHY reset polling failed to complete.\n");
365 return NGBE_ERR_RESET_FAILED;
371 s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
376 DEBUGFUNC("ngbe_get_phy_advertised_pause_yt");
378 status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
379 value &= YT_FANA_PAUSE_MASK;
380 *pause_bit = (u8)(value >> 7);
385 s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
390 DEBUGFUNC("ngbe_get_phy_lp_advertised_pause_yt");
392 status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
393 value &= YT_FLPAR_PAUSE_MASK;
394 *pause_bit = (u8)(value >> 7);
399 s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
404 DEBUGFUNC("ngbe_set_phy_pause_adv_yt");
407 status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
408 value &= ~YT_FANA_PAUSE_MASK;
410 status = hw->phy.write_reg(hw, YT_ANA, 0, value);
415 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
416 u32 *speed, bool *link_up)
424 DEBUGFUNC("ngbe_check_phy_link_yt");
426 /* Initialize speed and link to default case */
428 *speed = NGBE_LINK_SPEED_UNKNOWN;
430 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
431 ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
433 status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
434 phy_link = phy_data & YT_SPST_LINK;
435 phy_speed = phy_data & YT_SPST_SPEED_MASK;
440 if (phy_speed == YT_SPST_SPEED_1000M)
441 *speed = NGBE_LINK_SPEED_1GB_FULL;
442 else if (phy_speed == YT_SPST_SPEED_100M)
443 *speed = NGBE_LINK_SPEED_100M_FULL;
444 else if (phy_speed == YT_SPST_SPEED_10M)
445 *speed = NGBE_LINK_SPEED_10M_FULL;