1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
5 #include "ngbe_phy_rtl.h"
7 #define RTL_PHY_RST_WAIT_PERIOD 5
9 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
10 u32 reg_addr, u32 device_type, u16 *phy_data)
15 reg.device_type = device_type;
17 ngbe_mdi_map_register(®, ®22);
19 wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
20 *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
25 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
26 u32 reg_addr, u32 device_type, u16 phy_data)
31 reg.device_type = device_type;
33 ngbe_mdi_map_register(®, ®22);
35 wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
36 wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
42 * ngbe_setup_phy_link_rtl - Set and restart auto-neg
43 * @hw: pointer to hardware structure
45 * Restart auto-negotiation and PHY and waits for completion.
47 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
48 u32 speed, bool autoneg_wait_to_complete)
50 u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
53 DEBUGFUNC("ngbe_setup_phy_link_rtl");
55 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
57 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
59 if (!hw->mac.autoneg) {
63 case NGBE_LINK_SPEED_1GB_FULL:
64 value = RTL_BMCR_SPEED_SELECT1;
66 case NGBE_LINK_SPEED_100M_FULL:
67 value = RTL_BMCR_SPEED_SELECT0;
69 case NGBE_LINK_SPEED_10M_FULL:
73 value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
74 DEBUGOUT("unknown speed = 0x%x.\n", speed);
78 value |= RTL_BMCR_DUPLEX;
79 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
85 * Clear autoneg_advertised and set new values based on input link
89 hw->phy.autoneg_advertised = 0;
91 if (speed & NGBE_LINK_SPEED_1GB_FULL)
92 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
94 if (speed & NGBE_LINK_SPEED_100M_FULL)
95 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
97 if (speed & NGBE_LINK_SPEED_10M_FULL)
98 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
101 /* disable 10/100M Half Duplex */
102 hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
103 autoneg_reg &= 0xFF5F;
104 hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
106 /* set advertise enable according to input speed */
107 if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
108 hw->phy.read_reg(hw, RTL_GBCR,
109 RTL_DEV_ZERO, &autoneg_reg);
110 autoneg_reg &= ~RTL_GBCR_1000F;
111 hw->phy.write_reg(hw, RTL_GBCR,
112 RTL_DEV_ZERO, autoneg_reg);
114 hw->phy.read_reg(hw, RTL_GBCR,
115 RTL_DEV_ZERO, &autoneg_reg);
116 autoneg_reg |= RTL_GBCR_1000F;
117 hw->phy.write_reg(hw, RTL_GBCR,
118 RTL_DEV_ZERO, autoneg_reg);
121 if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
122 hw->phy.read_reg(hw, RTL_ANAR,
123 RTL_DEV_ZERO, &autoneg_reg);
124 autoneg_reg &= ~RTL_ANAR_100F;
125 autoneg_reg &= ~RTL_ANAR_100H;
126 hw->phy.write_reg(hw, RTL_ANAR,
127 RTL_DEV_ZERO, autoneg_reg);
129 hw->phy.read_reg(hw, RTL_ANAR,
130 RTL_DEV_ZERO, &autoneg_reg);
131 autoneg_reg |= RTL_ANAR_100F;
132 hw->phy.write_reg(hw, RTL_ANAR,
133 RTL_DEV_ZERO, autoneg_reg);
136 if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
137 hw->phy.read_reg(hw, RTL_ANAR,
138 RTL_DEV_ZERO, &autoneg_reg);
139 autoneg_reg &= ~RTL_ANAR_10F;
140 autoneg_reg &= ~RTL_ANAR_10H;
141 hw->phy.write_reg(hw, RTL_ANAR,
142 RTL_DEV_ZERO, autoneg_reg);
144 hw->phy.read_reg(hw, RTL_ANAR,
145 RTL_DEV_ZERO, &autoneg_reg);
146 autoneg_reg |= RTL_ANAR_10F;
147 hw->phy.write_reg(hw, RTL_ANAR,
148 RTL_DEV_ZERO, autoneg_reg);
151 /* restart AN and wait AN done interrupt */
152 autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
153 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
156 autoneg_reg = 0x205B;
157 hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
158 hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
160 hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
161 autoneg_reg = autoneg_reg & 0xFFFC;
162 /* act led blinking mode set to 60ms */
164 hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
169 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
174 DEBUGFUNC("ngbe_reset_phy_rtl");
176 value |= RTL_BMCR_RESET;
177 status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
179 for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) {
180 status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value);
181 if (!(value & RTL_BMCR_RESET))
186 if (i == RTL_PHY_RST_WAIT_PERIOD) {
187 DEBUGOUT("PHY reset polling failed to complete.\n");
188 return NGBE_ERR_RESET_FAILED;
194 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
202 DEBUGFUNC("ngbe_check_phy_link_rtl");
204 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
206 /* Initialize speed and link to default case */
208 *speed = NGBE_LINK_SPEED_UNKNOWN;
211 * Check current speed and link status of the PHY register.
212 * This is a vendor specific register and may have to
213 * be changed for other copper PHYs.
215 status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
216 phy_link = phy_data & RTL_PHYSR_RTLS;
217 phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
218 if (phy_link == RTL_PHYSR_RTLS) {
221 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
222 *speed = NGBE_LINK_SPEED_1GB_FULL;
223 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
224 *speed = NGBE_LINK_SPEED_100M_FULL;
225 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
226 *speed = NGBE_LINK_SPEED_10M_FULL;