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);
41 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
46 /* enable interrupts, only link status change and an done is allowed */
47 value = RTL_INER_LSC | RTL_INER_ANC;
48 hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
50 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
52 for (i = 0; i < 15; i++) {
53 if (!rd32m(hw, NGBE_STAT,
54 NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id)))
60 DEBUGOUT("GPhy reset exceeds maximum times.\n");
61 return NGBE_ERR_PHY_TIMEOUT;
64 for (i = 0; i < 1000; i++) {
65 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
66 if (value & RTL_INSR_ACCESS)
70 hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
71 for (i = 0; i < 1000; i++) {
72 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
73 if (value & RTL_INSR_ACCESS)
77 return NGBE_ERR_PHY_TIMEOUT;
79 hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
80 for (i = 0; i < 1000; i++) {
81 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
82 if (value & RTL_INSR_ACCESS)
86 return NGBE_ERR_PHY_TIMEOUT;
88 for (i = 0; i < 1000; i++) {
89 hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
90 if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
94 return NGBE_ERR_PHY_TIMEOUT;
100 * ngbe_setup_phy_link_rtl - Set and restart auto-neg
101 * @hw: pointer to hardware structure
103 * Restart auto-negotiation and PHY and waits for completion.
105 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
106 u32 speed, bool autoneg_wait_to_complete)
108 u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
111 DEBUGFUNC("ngbe_setup_phy_link_rtl");
113 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
115 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
117 if (!hw->mac.autoneg) {
118 hw->phy.reset_hw(hw);
121 case NGBE_LINK_SPEED_1GB_FULL:
122 value = RTL_BMCR_SPEED_SELECT1;
124 case NGBE_LINK_SPEED_100M_FULL:
125 value = RTL_BMCR_SPEED_SELECT0;
127 case NGBE_LINK_SPEED_10M_FULL:
131 value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
132 DEBUGOUT("unknown speed = 0x%x.\n", speed);
136 value |= RTL_BMCR_DUPLEX;
137 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
143 * Clear autoneg_advertised and set new values based on input link
147 hw->phy.autoneg_advertised = 0;
149 if (speed & NGBE_LINK_SPEED_1GB_FULL)
150 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
152 if (speed & NGBE_LINK_SPEED_100M_FULL)
153 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
155 if (speed & NGBE_LINK_SPEED_10M_FULL)
156 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
159 /* disable 10/100M Half Duplex */
160 hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
161 autoneg_reg &= 0xFF5F;
162 hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
164 /* set advertise enable according to input speed */
165 if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
166 hw->phy.read_reg(hw, RTL_GBCR,
167 RTL_DEV_ZERO, &autoneg_reg);
168 autoneg_reg &= ~RTL_GBCR_1000F;
169 hw->phy.write_reg(hw, RTL_GBCR,
170 RTL_DEV_ZERO, autoneg_reg);
172 hw->phy.read_reg(hw, RTL_GBCR,
173 RTL_DEV_ZERO, &autoneg_reg);
174 autoneg_reg |= RTL_GBCR_1000F;
175 hw->phy.write_reg(hw, RTL_GBCR,
176 RTL_DEV_ZERO, autoneg_reg);
179 if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
180 hw->phy.read_reg(hw, RTL_ANAR,
181 RTL_DEV_ZERO, &autoneg_reg);
182 autoneg_reg &= ~RTL_ANAR_100F;
183 autoneg_reg &= ~RTL_ANAR_100H;
184 hw->phy.write_reg(hw, RTL_ANAR,
185 RTL_DEV_ZERO, autoneg_reg);
187 hw->phy.read_reg(hw, RTL_ANAR,
188 RTL_DEV_ZERO, &autoneg_reg);
189 autoneg_reg |= RTL_ANAR_100F;
190 hw->phy.write_reg(hw, RTL_ANAR,
191 RTL_DEV_ZERO, autoneg_reg);
194 if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
195 hw->phy.read_reg(hw, RTL_ANAR,
196 RTL_DEV_ZERO, &autoneg_reg);
197 autoneg_reg &= ~RTL_ANAR_10F;
198 autoneg_reg &= ~RTL_ANAR_10H;
199 hw->phy.write_reg(hw, RTL_ANAR,
200 RTL_DEV_ZERO, autoneg_reg);
202 hw->phy.read_reg(hw, RTL_ANAR,
203 RTL_DEV_ZERO, &autoneg_reg);
204 autoneg_reg |= RTL_ANAR_10F;
205 hw->phy.write_reg(hw, RTL_ANAR,
206 RTL_DEV_ZERO, autoneg_reg);
209 /* restart AN and wait AN done interrupt */
210 autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
211 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
214 autoneg_reg = 0x205B;
215 hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
216 hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
218 hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
219 autoneg_reg = autoneg_reg & 0xFFFC;
220 /* act led blinking mode set to 60ms */
222 hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
227 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
232 DEBUGFUNC("ngbe_reset_phy_rtl");
234 value |= RTL_BMCR_RESET;
235 status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
237 for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) {
238 status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value);
239 if (!(value & RTL_BMCR_RESET))
244 if (i == RTL_PHY_RST_WAIT_PERIOD) {
245 DEBUGOUT("PHY reset polling failed to complete.\n");
246 return NGBE_ERR_RESET_FAILED;
252 s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
257 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
258 value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE;
259 *pause_bit = (u8)(value >> 10);
263 s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
268 status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
270 status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value);
271 value = value & RTL_BMSR_ANC;
273 /* if AN complete then check lp adv pause */
274 status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value);
275 value &= RTL_ANLPAR_LP;
276 *pause_bit = (u8)(value >> 10);
280 s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit)
285 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
286 value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE);
289 status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value);
294 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
302 DEBUGFUNC("ngbe_check_phy_link_rtl");
304 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
306 /* Initialize speed and link to default case */
308 *speed = NGBE_LINK_SPEED_UNKNOWN;
311 * Check current speed and link status of the PHY register.
312 * This is a vendor specific register and may have to
313 * be changed for other copper PHYs.
315 status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
316 phy_link = phy_data & RTL_PHYSR_RTLS;
317 phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
318 if (phy_link == RTL_PHYSR_RTLS) {
321 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
322 *speed = NGBE_LINK_SPEED_1GB_FULL;
323 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
324 *speed = NGBE_LINK_SPEED_100M_FULL;
325 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
326 *speed = NGBE_LINK_SPEED_10M_FULL;