net/bnxt: fix RSS action
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_rtl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4
5 #include "ngbe_phy_rtl.h"
6
7 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
8                 u32 reg_addr, u32 device_type, u16 *phy_data)
9 {
10         mdi_reg_t reg;
11         mdi_reg_22_t reg22;
12
13         reg.device_type = device_type;
14         reg.addr = reg_addr;
15         ngbe_mdi_map_register(&reg, &reg22);
16
17         wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
18         *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
19
20         return 0;
21 }
22
23 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
24                 u32 reg_addr, u32 device_type, u16 phy_data)
25 {
26         mdi_reg_t reg;
27         mdi_reg_22_t reg22;
28
29         reg.device_type = device_type;
30         reg.addr = reg_addr;
31         ngbe_mdi_map_register(&reg, &reg22);
32
33         wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
34         wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
35
36         return 0;
37 }
38
39 static void ngbe_phy_led_ctrl_rtl(struct ngbe_hw *hw)
40 {
41         u16 value = 0;
42
43         if (hw->led_conf != 0xFFFF)
44                 value = hw->led_conf & 0xFFFF;
45         else
46                 value = 0x205B;
47
48         hw->phy.write_reg(hw, RTL_LCR, 0xd04, value);
49         hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
50
51         hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &value);
52         if (hw->led_conf != 0xFFFF) {
53                 value &= ~0x73;
54                 value |= hw->led_conf >> 16;
55         } else {
56                 value &= 0xFFFC;
57                 /*act led blinking mode set to 60ms*/
58                 value |= 0x2;
59         }
60         hw->phy.write_reg(hw, RTL_LPCR, 0xd04, value);
61 }
62
63 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
64 {
65         int i;
66         u16 value = 0;
67
68         /* enable interrupts, only link status change and an done is allowed */
69         value = RTL_INER_LSC | RTL_INER_ANC;
70         hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
71
72         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
73
74         for (i = 0; i < 15; i++) {
75                 if (!rd32m(hw, NGBE_STAT,
76                         NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id)))
77                         break;
78
79                 msec_delay(10);
80         }
81         if (i == 15) {
82                 DEBUGOUT("GPhy reset exceeds maximum times.");
83                 return NGBE_ERR_PHY_TIMEOUT;
84         }
85
86         hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
87         hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
88         if (!(value & RTL_SCR_EFUSE)) {
89                 DEBUGOUT("Write EFUSE failed.");
90                 return NGBE_ERR_PHY_TIMEOUT;
91         }
92
93         for (i = 0; i < 1000; i++) {
94                 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
95                 if (value & RTL_INSR_ACCESS)
96                         break;
97                 msec_delay(1);
98         }
99         if (i == 1000)
100                 DEBUGOUT("PHY wait mdio 1 access timeout.");
101
102
103         hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
104         hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value);
105         if (!(value & RTL_SCR_EXTINI)) {
106                 DEBUGOUT("Write EXIINI failed.");
107                 return NGBE_ERR_PHY_TIMEOUT;
108         }
109
110         for (i = 0; i < 1000; i++) {
111                 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
112                 if (value & RTL_INSR_ACCESS)
113                         break;
114                 msec_delay(1);
115         }
116         if (i == 1000)
117                 DEBUGOUT("PHY wait mdio 2 access timeout.");
118
119         for (i = 0; i < 1000; i++) {
120                 hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
121                 if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
122                         break;
123                 msec_delay(1);
124         }
125         if (i == 1000)
126                 return NGBE_ERR_PHY_TIMEOUT;
127
128         return 0;
129 }
130
131 /**
132  *  ngbe_setup_phy_link_rtl - Set and restart auto-neg
133  *  @hw: pointer to hardware structure
134  *
135  *  Restart auto-negotiation and PHY and waits for completion.
136  **/
137 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
138                 u32 speed, bool autoneg_wait_to_complete)
139 {
140         u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
141         u16 value = 0;
142
143         UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
144
145         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
146
147         if (!hw->mac.autoneg) {
148                 hw->phy.reset_hw(hw);
149
150                 switch (speed) {
151                 case NGBE_LINK_SPEED_1GB_FULL:
152                         value = RTL_BMCR_SPEED_SELECT1;
153                         break;
154                 case NGBE_LINK_SPEED_100M_FULL:
155                         value = RTL_BMCR_SPEED_SELECT0;
156                         break;
157                 case NGBE_LINK_SPEED_10M_FULL:
158                         value = 0;
159                         break;
160                 default:
161                         value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
162                         DEBUGOUT("unknown speed = 0x%x.", speed);
163                         break;
164                 }
165                 /* duplex full */
166                 value |= RTL_BMCR_DUPLEX;
167                 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
168
169                 goto skip_an;
170         }
171
172         /*
173          * Clear autoneg_advertised and set new values based on input link
174          * speed.
175          */
176         if (speed) {
177                 hw->phy.autoneg_advertised = 0;
178
179                 if (speed & NGBE_LINK_SPEED_1GB_FULL)
180                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
181
182                 if (speed & NGBE_LINK_SPEED_100M_FULL)
183                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
184
185                 if (speed & NGBE_LINK_SPEED_10M_FULL)
186                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
187         }
188
189         /* disable 10/100M Half Duplex */
190         hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
191         autoneg_reg &= 0xFF5F;
192         hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
193
194         /* set advertise enable according to input speed */
195         if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
196                 hw->phy.read_reg(hw, RTL_GBCR,
197                         RTL_DEV_ZERO, &autoneg_reg);
198                 autoneg_reg &= ~RTL_GBCR_1000F;
199                 hw->phy.write_reg(hw, RTL_GBCR,
200                         RTL_DEV_ZERO, autoneg_reg);
201         } else {
202                 hw->phy.read_reg(hw, RTL_GBCR,
203                         RTL_DEV_ZERO, &autoneg_reg);
204                 autoneg_reg |= RTL_GBCR_1000F;
205                 hw->phy.write_reg(hw, RTL_GBCR,
206                         RTL_DEV_ZERO, autoneg_reg);
207         }
208
209         if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
210                 hw->phy.read_reg(hw, RTL_ANAR,
211                         RTL_DEV_ZERO, &autoneg_reg);
212                 autoneg_reg &= ~RTL_ANAR_100F;
213                 autoneg_reg &= ~RTL_ANAR_100H;
214                 hw->phy.write_reg(hw, RTL_ANAR,
215                         RTL_DEV_ZERO, autoneg_reg);
216         } else {
217                 hw->phy.read_reg(hw, RTL_ANAR,
218                         RTL_DEV_ZERO, &autoneg_reg);
219                 autoneg_reg |= RTL_ANAR_100F;
220                 hw->phy.write_reg(hw, RTL_ANAR,
221                         RTL_DEV_ZERO, autoneg_reg);
222         }
223
224         if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
225                 hw->phy.read_reg(hw, RTL_ANAR,
226                         RTL_DEV_ZERO, &autoneg_reg);
227                 autoneg_reg &= ~RTL_ANAR_10F;
228                 autoneg_reg &= ~RTL_ANAR_10H;
229                 hw->phy.write_reg(hw, RTL_ANAR,
230                         RTL_DEV_ZERO, autoneg_reg);
231         } else {
232                 hw->phy.read_reg(hw, RTL_ANAR,
233                         RTL_DEV_ZERO, &autoneg_reg);
234                 autoneg_reg |= RTL_ANAR_10F;
235                 hw->phy.write_reg(hw, RTL_ANAR,
236                         RTL_DEV_ZERO, autoneg_reg);
237         }
238
239         /* restart AN and wait AN done interrupt */
240         autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
241         hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
242
243 skip_an:
244         ngbe_phy_led_ctrl_rtl(hw);
245
246         return 0;
247 }
248
249 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
250 {
251         u16 value = 0;
252         s32 status = 0;
253
254         value |= RTL_BMCR_RESET;
255         status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
256
257         msec_delay(5);
258
259         return status;
260 }
261
262 s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
263 {
264         u16 value;
265         s32 status = 0;
266
267         status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
268         value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE;
269         *pause_bit = (u8)(value >> 10);
270         return status;
271 }
272
273 s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit)
274 {
275         u16 value;
276         s32 status = 0;
277
278         status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
279
280         status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value);
281         value = value & RTL_BMSR_ANC;
282
283         /* if AN complete then check lp adv pause */
284         status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value);
285         value &= RTL_ANLPAR_LP;
286         *pause_bit = (u8)(value >> 10);
287         return status;
288 }
289
290 s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit)
291 {
292         u16 value;
293         s32 status = 0;
294
295         status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value);
296         value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE);
297         value |= pause_bit;
298
299         status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value);
300
301         return status;
302 }
303
304 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
305 {
306         s32 status = 0;
307         u16 phy_link = 0;
308         u16 phy_speed = 0;
309         u16 phy_data = 0;
310         u16 insr = 0;
311
312         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
313
314         /* Initialize speed and link to default case */
315         *link_up = false;
316         *speed = NGBE_LINK_SPEED_UNKNOWN;
317
318         /*
319          * Check current speed and link status of the PHY register.
320          * This is a vendor specific register and may have to
321          * be changed for other copper PHYs.
322          */
323         status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
324         phy_link = phy_data & RTL_PHYSR_RTLS;
325         phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
326         if (phy_link == RTL_PHYSR_RTLS) {
327                 *link_up = true;
328
329                 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
330                         *speed = NGBE_LINK_SPEED_1GB_FULL;
331                 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
332                         *speed = NGBE_LINK_SPEED_100M_FULL;
333                 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
334                         *speed = NGBE_LINK_SPEED_10M_FULL;
335         }
336
337         return status;
338 }
339