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)
103 /* close sds area register */
104 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
105 /* enable interrupts */
106 ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
107 YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
109 hw->phy.set_phy_power(hw, false);
114 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
115 bool autoneg_wait_to_complete)
121 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
123 hw->phy.autoneg_advertised = 0;
125 /* check chip_mode first */
126 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
127 if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
129 if (!hw->mac.autoneg) {
131 case NGBE_LINK_SPEED_1GB_FULL:
132 value = YT_BCR_SPEED_SELECT1;
134 case NGBE_LINK_SPEED_100M_FULL:
135 value = YT_BCR_SPEED_SELECT0;
137 case NGBE_LINK_SPEED_10M_FULL:
141 value = YT_BCR_SPEED_SELECT0 |
142 YT_BCR_SPEED_SELECT1;
143 DEBUGOUT("unknown speed = 0x%x.",
148 value |= YT_BCR_DUPLEX | YT_BCR_RESET;
149 hw->phy.write_reg(hw, YT_BCR, 0, value);
154 /*disable 100/10base-T Self-negotiation ability*/
155 hw->phy.read_reg(hw, YT_ANA, 0, &value);
156 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
157 YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
158 hw->phy.write_reg(hw, YT_ANA, 0, value);
160 /*disable 1000base-T Self-negotiation ability*/
161 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
162 value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
163 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
165 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
166 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
167 value_r9 |= YT_MS_1000BASET_FULL;
169 if (speed & NGBE_LINK_SPEED_100M_FULL) {
170 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
171 value_r4 |= YT_ANA_100BASET_FULL;
173 if (speed & NGBE_LINK_SPEED_10M_FULL) {
174 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
175 value_r4 |= YT_ANA_10BASET_FULL;
178 /* enable 1000base-T Self-negotiation ability */
179 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
181 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
183 /* enable 100/10base-T Self-negotiation ability */
184 hw->phy.read_reg(hw, YT_ANA, 0, &value);
186 hw->phy.write_reg(hw, YT_ANA, 0, value);
188 /* software reset to make the above configuration take effect*/
189 hw->phy.read_reg(hw, YT_BCR, 0, &value);
190 value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
191 hw->phy.write_reg(hw, YT_BCR, 0, value);
193 hw->phy.set_phy_power(hw, true);
194 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
196 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
198 /* RGMII_Config1 : Config rx and tx training delay */
199 value = YT_RGMII_CONF1_RXDELAY |
200 YT_RGMII_CONF1_TXDELAY_FE |
201 YT_RGMII_CONF1_TXDELAY;
202 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
203 value = YT_CHIP_MODE_SEL(1) |
206 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
209 ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
211 hw->phy.set_phy_power(hw, true);
212 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
213 hw->phy.set_phy_power(hw, true);
215 hw->phy.read_reg(hw, YT_SPST, 0, &value);
216 if (value & YT_SPST_LINK) {
218 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
221 /*disable 100/10base-T Self-negotiation ability*/
222 hw->phy.read_reg(hw, YT_ANA, 0, &value);
223 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
224 YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
225 hw->phy.write_reg(hw, YT_ANA, 0, value);
227 /*disable 1000base-T Self-negotiation ability*/
228 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
229 value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
230 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
232 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
233 hw->phy.autoneg_advertised |=
234 NGBE_LINK_SPEED_1GB_FULL;
235 value_r9 |= YT_MS_1000BASET_FULL;
237 if (speed & NGBE_LINK_SPEED_100M_FULL) {
238 hw->phy.autoneg_advertised |=
239 NGBE_LINK_SPEED_100M_FULL;
240 value_r4 |= YT_ANA_100BASET_FULL;
242 if (speed & NGBE_LINK_SPEED_10M_FULL) {
243 hw->phy.autoneg_advertised |=
244 NGBE_LINK_SPEED_10M_FULL;
245 value_r4 |= YT_ANA_10BASET_FULL;
248 /* enable 1000base-T Self-negotiation ability */
249 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
251 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
253 /* enable 100/10base-T Self-negotiation ability */
254 hw->phy.read_reg(hw, YT_ANA, 0, &value);
256 hw->phy.write_reg(hw, YT_ANA, 0, value);
258 /* software reset to make the above configuration
261 hw->phy.read_reg(hw, YT_BCR, 0, &value);
262 value |= YT_BCR_RESET;
263 hw->phy.write_reg(hw, YT_BCR, 0, value);
265 } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
266 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
268 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
269 value |= YT_RGMII_CONF1_MODE;
270 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
272 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
273 value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
274 YT_RGMII_CONF2_LINKUP);
275 value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
276 YT_RGMII_CONF2_LINKUP;
277 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
279 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
280 value &= ~YT_SMI_PHY_SW_RST;
281 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
283 hw->phy.set_phy_power(hw, true);
286 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
287 ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
292 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
298 if (hw->phy.type != ngbe_phy_yt8521s &&
299 hw->phy.type != ngbe_phy_yt8521s_sfi)
300 return NGBE_ERR_PHY_TYPE;
302 /* check chip_mode first */
303 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
304 if (ctrl & YT_CHIP_MODE_MASK) {
306 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
307 /* sds software reset */
308 ctrl |= YT_BCR_RESET;
309 status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
311 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
312 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
313 if (!(ctrl & YT_BCR_RESET))
319 status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
320 /* sds software reset */
321 ctrl |= YT_BCR_RESET;
322 status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
324 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
325 status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
326 if (!(ctrl & YT_BCR_RESET))
332 if (i == YT_PHY_RST_WAIT_PERIOD) {
333 DEBUGOUT("PHY reset polling failed to complete.");
334 return NGBE_ERR_RESET_FAILED;
340 s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
345 status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
346 value &= YT_FANA_PAUSE_MASK;
347 *pause_bit = (u8)(value >> 7);
352 s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
357 status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
358 value &= YT_FLPAR_PAUSE_MASK;
359 *pause_bit = (u8)(value >> 7);
364 s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
369 status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
370 value &= ~YT_FANA_PAUSE_MASK;
372 status = hw->phy.write_reg(hw, YT_ANA, 0, value);
377 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
378 u32 *speed, bool *link_up)
386 /* Initialize speed and link to default case */
388 *speed = NGBE_LINK_SPEED_UNKNOWN;
390 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
391 ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
393 status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
394 phy_link = phy_data & YT_SPST_LINK;
395 phy_speed = phy_data & YT_SPST_SPEED_MASK;
400 if (phy_speed == YT_SPST_SPEED_1000M)
401 *speed = NGBE_LINK_SPEED_1GB_FULL;
402 else if (phy_speed == YT_SPST_SPEED_100M)
403 *speed = NGBE_LINK_SPEED_100M_FULL;
404 else if (phy_speed == YT_SPST_SPEED_10M)
405 *speed = NGBE_LINK_SPEED_10M_FULL;
411 s32 ngbe_set_phy_power_yt(struct ngbe_hw *hw, bool on)
415 /* power down/up in fiber mode */
416 hw->phy.read_reg(hw, YT_BCR, 0, &value);
418 value &= ~YT_BCR_PWDN;
420 value |= YT_BCR_PWDN;
421 hw->phy.write_reg(hw, YT_BCR, 0, value);
424 /* power down/up in UTP mode */
425 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
427 value &= ~YT_BCR_PWDN;
429 value |= YT_BCR_PWDN;
430 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);