net/bnxt: fix RSS action
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_yt.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4
5 #include "ngbe_phy_yt.h"
6
7 #define YT_PHY_RST_WAIT_PERIOD          5
8
9 s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw,
10                 u32 reg_addr, u32 device_type, u16 *phy_data)
11 {
12         mdi_reg_t reg;
13         mdi_reg_22_t reg22;
14
15         reg.device_type = device_type;
16         reg.addr = reg_addr;
17
18         ngbe_mdi_map_register(&reg, &reg22);
19
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);
28         } else {
29                 ngbe_read_phy_reg_mdi(hw, reg22.addr,
30                                         reg22.device_type, phy_data);
31         }
32
33         return 0;
34 }
35
36 s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw,
37                 u32 reg_addr, u32 device_type, u16 phy_data)
38 {
39         mdi_reg_t reg;
40         mdi_reg_22_t reg22;
41
42         reg.device_type = device_type;
43         reg.addr = reg_addr;
44
45         ngbe_mdi_map_register(&reg, &reg22);
46
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);
55         } else {
56                 ngbe_write_phy_reg_mdi(hw, reg22.addr,
57                                         reg22.device_type, phy_data);
58         }
59
60         return 0;
61 }
62
63 s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
64                 u32 reg_addr, u32 device_type, u16 *phy_data)
65 {
66         ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
67         ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
68
69         return 0;
70 }
71
72 s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
73                 u32 reg_addr, u32 device_type, u16 phy_data)
74 {
75         ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
76         ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
77
78         return 0;
79 }
80
81 s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
82                 u32 reg_addr, u32 device_type, u16 *phy_data)
83 {
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);
87
88         return 0;
89 }
90
91 s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
92                 u32 reg_addr, u32 device_type, u16 phy_data)
93 {
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);
97
98         return 0;
99 }
100
101 s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
102 {
103         u16 value = 0;
104
105         /* close sds area register */
106         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
107         /* enable interrupts */
108         ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
109                                 YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
110
111         /* power down in fiber mode */
112         hw->phy.read_reg(hw, YT_BCR, 0, &value);
113         value |= YT_BCR_PWDN;
114         hw->phy.write_reg(hw, YT_BCR, 0, value);
115
116         /* power down in UTP mode */
117         ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
118         value |= YT_BCR_PWDN;
119         ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
120
121         return 0;
122 }
123
124 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
125                                 bool autoneg_wait_to_complete)
126 {
127         u16 value_r4 = 0;
128         u16 value_r9 = 0;
129         u16 value;
130
131         UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
132
133         hw->phy.autoneg_advertised = 0;
134
135         /* check chip_mode first */
136         ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
137         if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
138                 /* UTP to rgmii */
139                 if (!hw->mac.autoneg) {
140                         switch (speed) {
141                         case NGBE_LINK_SPEED_1GB_FULL:
142                                 value = YT_BCR_SPEED_SELECT1;
143                                 break;
144                         case NGBE_LINK_SPEED_100M_FULL:
145                                 value = YT_BCR_SPEED_SELECT0;
146                                 break;
147                         case NGBE_LINK_SPEED_10M_FULL:
148                                 value = 0;
149                                 break;
150                         default:
151                                 value = YT_BCR_SPEED_SELECT0 |
152                                         YT_BCR_SPEED_SELECT1;
153                                 DEBUGOUT("unknown speed = 0x%x.",
154                                         speed);
155                                 break;
156                         }
157                         /* duplex full */
158                         value |= YT_BCR_DUPLEX | YT_BCR_RESET;
159                         hw->phy.write_reg(hw, YT_BCR, 0, value);
160
161                         goto skip_an;
162                 }
163
164                 /*disable 100/10base-T Self-negotiation ability*/
165                 hw->phy.read_reg(hw, YT_ANA, 0, &value);
166                 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
167                         YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
168                 hw->phy.write_reg(hw, YT_ANA, 0, value);
169
170                 /*disable 1000base-T Self-negotiation ability*/
171                 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
172                 value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
173                 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
174
175                 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
176                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
177                         value_r9 |= YT_MS_1000BASET_FULL;
178                 }
179                 if (speed & NGBE_LINK_SPEED_100M_FULL) {
180                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
181                         value_r4 |= YT_ANA_100BASET_FULL;
182                 }
183                 if (speed & NGBE_LINK_SPEED_10M_FULL) {
184                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
185                         value_r4 |= YT_ANA_10BASET_FULL;
186                 }
187
188                 /* enable 1000base-T Self-negotiation ability */
189                 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
190                 value |= value_r9;
191                 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
192
193                 /* enable 100/10base-T Self-negotiation ability */
194                 hw->phy.read_reg(hw, YT_ANA, 0, &value);
195                 value |= value_r4;
196                 hw->phy.write_reg(hw, YT_ANA, 0, value);
197
198                 /* software reset to make the above configuration take effect*/
199                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
200                 value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
201                 hw->phy.write_reg(hw, YT_BCR, 0, value);
202 skip_an:
203                 /* power on in UTP mode */
204                 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
205                 value &= ~YT_BCR_PWDN;
206                 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
207         } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
208                 /* fiber to rgmii */
209                 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
210
211                 /* RGMII_Config1 : Config rx and tx training delay */
212                 value = YT_RGMII_CONF1_RXDELAY |
213                         YT_RGMII_CONF1_TXDELAY_FE |
214                         YT_RGMII_CONF1_TXDELAY;
215                 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
216                 value = YT_CHIP_MODE_SEL(1) |
217                         YT_CHIP_SW_LDO_EN |
218                         YT_CHIP_SW_RST;
219                 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
220
221                 /* software reset */
222                 ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
223
224                 /* power on phy */
225                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
226                 value &= ~YT_BCR_PWDN;
227                 hw->phy.write_reg(hw, YT_BCR, 0, value);
228         } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
229                 /* power on in UTP mode */
230                 ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
231                 value &= ~YT_BCR_PWDN;
232                 ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
233                 /* power down in fiber mode */
234                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
235                 value &= ~YT_BCR_PWDN;
236                 hw->phy.write_reg(hw, YT_BCR, 0, value);
237
238                 hw->phy.read_reg(hw, YT_SPST, 0, &value);
239                 if (value & YT_SPST_LINK) {
240                         /* fiber up */
241                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
242                 } else {
243                         /* utp up */
244                         /*disable 100/10base-T Self-negotiation ability*/
245                         hw->phy.read_reg(hw, YT_ANA, 0, &value);
246                         value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
247                                 YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
248                         hw->phy.write_reg(hw, YT_ANA, 0, value);
249
250                         /*disable 1000base-T Self-negotiation ability*/
251                         hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
252                         value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
253                         hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
254
255                         if (speed & NGBE_LINK_SPEED_1GB_FULL) {
256                                 hw->phy.autoneg_advertised |=
257                                                 NGBE_LINK_SPEED_1GB_FULL;
258                                 value_r9 |= YT_MS_1000BASET_FULL;
259                         }
260                         if (speed & NGBE_LINK_SPEED_100M_FULL) {
261                                 hw->phy.autoneg_advertised |=
262                                                 NGBE_LINK_SPEED_100M_FULL;
263                                 value_r4 |= YT_ANA_100BASET_FULL;
264                         }
265                         if (speed & NGBE_LINK_SPEED_10M_FULL) {
266                                 hw->phy.autoneg_advertised |=
267                                                 NGBE_LINK_SPEED_10M_FULL;
268                                 value_r4 |= YT_ANA_10BASET_FULL;
269                         }
270
271                         /* enable 1000base-T Self-negotiation ability */
272                         hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
273                         value |= value_r9;
274                         hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
275
276                         /* enable 100/10base-T Self-negotiation ability */
277                         hw->phy.read_reg(hw, YT_ANA, 0, &value);
278                         value |= value_r4;
279                         hw->phy.write_reg(hw, YT_ANA, 0, value);
280
281                         /* software reset to make the above configuration
282                          * take effect
283                          */
284                         hw->phy.read_reg(hw, YT_BCR, 0, &value);
285                         value |= YT_BCR_RESET;
286                         hw->phy.write_reg(hw, YT_BCR, 0, value);
287                 }
288         } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
289                 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
290
291                 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
292                 value |= YT_RGMII_CONF1_MODE;
293                 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
294
295                 ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
296                 value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
297                         YT_RGMII_CONF2_LINKUP);
298                 value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
299                         YT_RGMII_CONF2_LINKUP;
300                 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
301
302                 ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
303                 value &= ~YT_SMI_PHY_SW_RST;
304                 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
305
306                 /* power on phy */
307                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
308                 value &= ~YT_BCR_PWDN;
309                 hw->phy.write_reg(hw, YT_BCR, 0, value);
310         }
311
312         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
313         ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
314
315         return 0;
316 }
317
318 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
319 {
320         u32 i;
321         u16 ctrl = 0;
322         s32 status = 0;
323
324         if (hw->phy.type != ngbe_phy_yt8521s &&
325                 hw->phy.type != ngbe_phy_yt8521s_sfi)
326                 return NGBE_ERR_PHY_TYPE;
327
328         /* check chip_mode first */
329         ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
330         if (ctrl & YT_CHIP_MODE_MASK) {
331                 /* fiber to rgmii */
332                 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
333                 /* sds software reset */
334                 ctrl |= YT_BCR_RESET;
335                 status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
336
337                 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
338                         status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
339                         if (!(ctrl & YT_BCR_RESET))
340                                 break;
341                         msleep(1);
342                 }
343         } else {
344                 /* UTP to rgmii */
345                 status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
346                 /* sds software reset */
347                 ctrl |= YT_BCR_RESET;
348                 status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
349
350                 for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
351                         status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
352                         if (!(ctrl & YT_BCR_RESET))
353                                 break;
354                         msleep(1);
355                 }
356         }
357
358         if (i == YT_PHY_RST_WAIT_PERIOD) {
359                 DEBUGOUT("PHY reset polling failed to complete.");
360                 return NGBE_ERR_RESET_FAILED;
361         }
362
363         return status;
364 }
365
366 s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
367 {
368         u16 value;
369         s32 status = 0;
370
371         status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
372         value &= YT_FANA_PAUSE_MASK;
373         *pause_bit = (u8)(value >> 7);
374
375         return status;
376 }
377
378 s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
379 {
380         u16 value;
381         s32 status = 0;
382
383         status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
384         value &= YT_FLPAR_PAUSE_MASK;
385         *pause_bit = (u8)(value >> 7);
386
387         return status;
388 }
389
390 s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
391 {
392         u16 value;
393         s32 status = 0;
394
395         status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
396         value &= ~YT_FANA_PAUSE_MASK;
397         value |= pause_bit;
398         status = hw->phy.write_reg(hw, YT_ANA, 0, value);
399
400         return status;
401 }
402
403 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
404                 u32 *speed, bool *link_up)
405 {
406         s32 status = 0;
407         u16 phy_link = 0;
408         u16 phy_speed = 0;
409         u16 phy_data = 0;
410         u16 insr = 0;
411
412         /* Initialize speed and link to default case */
413         *link_up = false;
414         *speed = NGBE_LINK_SPEED_UNKNOWN;
415
416         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
417         ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
418
419         status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
420         phy_link = phy_data & YT_SPST_LINK;
421         phy_speed = phy_data & YT_SPST_SPEED_MASK;
422
423         if (phy_link) {
424                 *link_up = true;
425
426                 if (phy_speed == YT_SPST_SPEED_1000M)
427                         *speed = NGBE_LINK_SPEED_1GB_FULL;
428                 else if (phy_speed == YT_SPST_SPEED_100M)
429                         *speed = NGBE_LINK_SPEED_100M_FULL;
430                 else if (phy_speed == YT_SPST_SPEED_10M)
431                         *speed = NGBE_LINK_SPEED_10M_FULL;
432         }
433
434         return status;
435 }
436