net/bnxt: fix RSS action
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include "ngbe_hw.h"
7 #include "ngbe_phy.h"
8
9 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22)
10 {
11         bool match = 1;
12         switch (reg->device_type) {
13         case NGBE_MD_DEV_PMA_PMD:
14                 switch (reg->addr) {
15                 case NGBE_MD_PHY_ID_HIGH:
16                 case NGBE_MD_PHY_ID_LOW:
17                         reg22->page = 0;
18                         reg22->addr = reg->addr;
19                         reg22->device_type = 0;
20                         break;
21                 default:
22                         match = 0;
23                 }
24                 break;
25         default:
26                 match = 0;
27                 break;
28         }
29
30         if (!match) {
31                 reg22->page = reg->device_type;
32                 reg22->device_type = reg->device_type;
33                 reg22->addr = reg->addr;
34         }
35
36         return 0;
37 }
38
39 /**
40  * ngbe_probe_phy - Identify a single address for a PHY
41  * @hw: pointer to hardware structure
42  * @phy_addr: PHY address to probe
43  *
44  * Returns true if PHY found
45  */
46 static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
47 {
48         if (!ngbe_validate_phy_addr(hw, phy_addr)) {
49                 DEBUGOUT("Unable to validate PHY address 0x%04X",
50                         phy_addr);
51                 return false;
52         }
53
54         if (ngbe_get_phy_id(hw))
55                 return false;
56
57         if (ngbe_get_phy_type_from_id(hw))
58                 return false;
59
60         return true;
61 }
62
63 /**
64  *  ngbe_identify_phy - Get physical layer module
65  *  @hw: pointer to hardware structure
66  *
67  *  Determines the physical layer module found on the current adapter.
68  **/
69 s32 ngbe_identify_phy(struct ngbe_hw *hw)
70 {
71         s32 err = NGBE_ERR_PHY_ADDR_INVALID;
72         u16 phy_addr;
73
74         if (hw->phy.type != ngbe_phy_unknown)
75                 return 0;
76
77         /* select clause22 */
78         wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK);
79
80         for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) {
81                 if (ngbe_probe_phy(hw, phy_addr)) {
82                         err = 0;
83                         break;
84                 }
85         }
86
87         return err;
88 }
89
90 /**
91  * ngbe_check_reset_blocked - check status of MNG FW veto bit
92  * @hw: pointer to the hardware structure
93  *
94  * This function checks the STAT.MNGVETO bit to see if there are
95  * any constraints on link from manageability.  For MAC's that don't
96  * have this bit just return faluse since the link can not be blocked
97  * via this method.
98  **/
99 s32 ngbe_check_reset_blocked(struct ngbe_hw *hw)
100 {
101         u32 mmngc;
102
103         mmngc = rd32(hw, NGBE_STAT);
104         if (mmngc & NGBE_STAT_MNGVETO) {
105                 DEBUGOUT("MNG_VETO bit detected.");
106                 return true;
107         }
108
109         return false;
110 }
111
112 /**
113  *  ngbe_validate_phy_addr - Determines phy address is valid
114  *  @hw: pointer to hardware structure
115  *  @phy_addr: PHY address
116  *
117  **/
118 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr)
119 {
120         u16 phy_id = 0;
121         bool valid = false;
122
123         if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP)
124                 return true;
125
126         hw->phy.addr = phy_addr;
127         hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
128                              NGBE_MD_DEV_PMA_PMD, &phy_id);
129
130         if (phy_id != 0xFFFF && phy_id != 0x0)
131                 valid = true;
132
133         DEBUGOUT("PHY ID HIGH is 0x%04X", phy_id);
134
135         return valid;
136 }
137
138 /**
139  *  ngbe_get_phy_id - Get the phy ID
140  *  @hw: pointer to hardware structure
141  *
142  **/
143 s32 ngbe_get_phy_id(struct ngbe_hw *hw)
144 {
145         u32 err;
146         u16 phy_id_high = 0;
147         u16 phy_id_low = 0;
148
149         err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
150                                       NGBE_MD_DEV_PMA_PMD,
151                                       &phy_id_high);
152         hw->phy.id = (u32)(phy_id_high << 16);
153
154         err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW,
155                                 NGBE_MD_DEV_PMA_PMD,
156                                 &phy_id_low);
157         hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK);
158         hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK);
159
160         DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X",
161                   phy_id_high, phy_id_low);
162
163         return err;
164 }
165
166 /**
167  *  ngbe_get_phy_type_from_id - Get the phy type
168  *
169  **/
170 s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
171 {
172         s32 status = 0;
173
174         switch (hw->phy.id) {
175         case NGBE_PHYID_RTL:
176                 hw->phy.type = ngbe_phy_rtl;
177                 break;
178         case NGBE_PHYID_MVL:
179                 if (hw->phy.media_type == ngbe_media_type_fiber)
180                         hw->phy.type = ngbe_phy_mvl_sfi;
181                 else if (hw->phy.media_type == ngbe_media_type_copper)
182                         hw->phy.type = ngbe_phy_mvl;
183                 else
184                         status = ngbe_check_phy_mode_mvl(hw);
185                 break;
186         case NGBE_PHYID_YT:
187                 if (hw->phy.media_type == ngbe_media_type_fiber)
188                         hw->phy.type = ngbe_phy_yt8521s_sfi;
189                 else
190                         hw->phy.type = ngbe_phy_yt8521s;
191                 break;
192         default:
193                 hw->phy.type = ngbe_phy_unknown;
194                 status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
195                 break;
196         }
197
198         return status;
199 }
200
201 /**
202  *  ngbe_reset_phy - Performs a PHY reset
203  *  @hw: pointer to hardware structure
204  **/
205 s32 ngbe_reset_phy(struct ngbe_hw *hw)
206 {
207         s32 err = 0;
208
209         if (hw->phy.type == ngbe_phy_unknown)
210                 err = ngbe_identify_phy(hw);
211
212         if (err != 0 || hw->phy.type == ngbe_phy_none)
213                 return err;
214
215         /* Don't reset PHY if it's shut down due to overtemp. */
216         if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP)
217                 return err;
218
219         /* Blocked by MNG FW so bail */
220         if (ngbe_check_reset_blocked(hw))
221                 return err;
222
223         switch (hw->phy.type) {
224         case ngbe_phy_rtl:
225                 err = ngbe_reset_phy_rtl(hw);
226                 break;
227         case ngbe_phy_mvl:
228         case ngbe_phy_mvl_sfi:
229                 err = ngbe_reset_phy_mvl(hw);
230                 break;
231         case ngbe_phy_yt8521s:
232         case ngbe_phy_yt8521s_sfi:
233                 err = ngbe_reset_phy_yt(hw);
234                 break;
235         default:
236                 break;
237         }
238
239         return err;
240 }
241
242 /**
243  *  ngbe_read_phy_mdi - Reads a value from a specified PHY register without
244  *  the SWFW lock
245  *  @hw: pointer to hardware structure
246  *  @reg_addr: 32 bit address of PHY register to read
247  *  @device_type: 5 bit device type
248  *  @phy_data: Pointer to read data from PHY register
249  **/
250 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
251                            u16 *phy_data)
252 {
253         u32 command, data;
254
255         /* Setup and write the address cycle command */
256         command = NGBE_MDIOSCA_REG(reg_addr) |
257                   NGBE_MDIOSCA_DEV(device_type) |
258                   NGBE_MDIOSCA_PORT(hw->phy.addr);
259         wr32(hw, NGBE_MDIOSCA, command);
260
261         command = NGBE_MDIOSCD_CMD_READ |
262                   NGBE_MDIOSCD_BUSY |
263                   NGBE_MDIOSCD_CLOCK(6);
264         wr32(hw, NGBE_MDIOSCD, command);
265
266         /*
267          * Check every 10 usec to see if the address cycle completed.
268          * The MDI Command bit will clear when the operation is
269          * complete
270          */
271         if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
272                 0, NULL, 100, 100)) {
273                 DEBUGOUT("PHY address command did not complete");
274                 return NGBE_ERR_PHY;
275         }
276
277         data = rd32(hw, NGBE_MDIOSCD);
278         *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data);
279
280         return 0;
281 }
282
283 /**
284  *  ngbe_read_phy_reg - Reads a value from a specified PHY register
285  *  using the SWFW lock - this function is needed in most cases
286  *  @hw: pointer to hardware structure
287  *  @reg_addr: 32 bit address of PHY register to read
288  *  @device_type: 5 bit device type
289  *  @phy_data: Pointer to read data from PHY register
290  **/
291 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
292                                u32 device_type, u16 *phy_data)
293 {
294         s32 err;
295         u32 gssr = hw->phy.phy_semaphore_mask;
296
297         if (hw->mac.acquire_swfw_sync(hw, gssr))
298                 return NGBE_ERR_SWFW_SYNC;
299
300         err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type,
301                                         phy_data);
302
303         hw->mac.release_swfw_sync(hw, gssr);
304
305         return err;
306 }
307
308 /**
309  *  ngbe_write_phy_reg_mdi - Writes a value to specified PHY register
310  *  without SWFW lock
311  *  @hw: pointer to hardware structure
312  *  @reg_addr: 32 bit PHY register to write
313  *  @device_type: 5 bit device type
314  *  @phy_data: Data to write to the PHY register
315  **/
316 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr,
317                                 u32 device_type, u16 phy_data)
318 {
319         u32 command;
320
321         /* write command */
322         command = NGBE_MDIOSCA_REG(reg_addr) |
323                   NGBE_MDIOSCA_DEV(device_type) |
324                   NGBE_MDIOSCA_PORT(hw->phy.addr);
325         wr32(hw, NGBE_MDIOSCA, command);
326
327         command = NGBE_MDIOSCD_CMD_WRITE |
328                   NGBE_MDIOSCD_DAT(phy_data) |
329                   NGBE_MDIOSCD_BUSY |
330                   NGBE_MDIOSCD_CLOCK(6);
331         wr32(hw, NGBE_MDIOSCD, command);
332
333         /* wait for completion */
334         if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
335                 0, NULL, 100, 100)) {
336                 DEBUGOUT("PHY write cmd didn't complete");
337                 return NGBE_ERR_PHY;
338         }
339
340         return 0;
341 }
342
343 /**
344  *  ngbe_write_phy_reg - Writes a value to specified PHY register
345  *  using SWFW lock- this function is needed in most cases
346  *  @hw: pointer to hardware structure
347  *  @reg_addr: 32 bit PHY register to write
348  *  @device_type: 5 bit device type
349  *  @phy_data: Data to write to the PHY register
350  **/
351 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
352                                 u32 device_type, u16 phy_data)
353 {
354         s32 err;
355         u32 gssr = hw->phy.phy_semaphore_mask;
356
357         if (hw->mac.acquire_swfw_sync(hw, gssr))
358                 err = NGBE_ERR_SWFW_SYNC;
359
360         err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type,
361                                          phy_data);
362
363         hw->mac.release_swfw_sync(hw, gssr);
364
365         return err;
366 }
367
368 /**
369  *  ngbe_init_phy - PHY specific init
370  *  @hw: pointer to hardware structure
371  *
372  *  Initialize any function pointers that were not able to be
373  *  set during init_shared_code because the PHY type was
374  *  not known.
375  *
376  **/
377 s32 ngbe_init_phy(struct ngbe_hw *hw)
378 {
379         struct ngbe_phy_info *phy = &hw->phy;
380         s32 err = 0;
381
382         hw->phy.addr = 0;
383
384         switch (hw->sub_device_id) {
385         case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
386         case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
387                 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
388                 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
389                 break;
390         case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
391         case NGBE_SUB_DEV_ID_EM_MVL_SFP:
392         case NGBE_SUB_DEV_ID_EM_MVL_MIX:
393                 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
394                 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
395                 break;
396         case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
397                 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt;
398                 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt;
399                 break;
400         default:
401                 break;
402         }
403
404         hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY;
405
406         /* Identify the PHY */
407         err = phy->identify(hw);
408         if (err == NGBE_ERR_PHY_ADDR_INVALID)
409                 goto init_phy_ops_out;
410
411         /* Set necessary function pointers based on PHY type */
412         switch (hw->phy.type) {
413         case ngbe_phy_rtl:
414                 hw->phy.init_hw = ngbe_init_phy_rtl;
415                 hw->phy.check_link = ngbe_check_phy_link_rtl;
416                 hw->phy.setup_link = ngbe_setup_phy_link_rtl;
417                 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl;
418                 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl;
419                 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl;
420                 break;
421         case ngbe_phy_mvl:
422         case ngbe_phy_mvl_sfi:
423                 hw->phy.init_hw = ngbe_init_phy_mvl;
424                 hw->phy.check_link = ngbe_check_phy_link_mvl;
425                 hw->phy.setup_link = ngbe_setup_phy_link_mvl;
426                 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl;
427                 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl;
428                 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl;
429                 break;
430         case ngbe_phy_yt8521s:
431         case ngbe_phy_yt8521s_sfi:
432                 hw->phy.init_hw = ngbe_init_phy_yt;
433                 hw->phy.check_link = ngbe_check_phy_link_yt;
434                 hw->phy.setup_link = ngbe_setup_phy_link_yt;
435                 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt;
436                 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt;
437                 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt;
438         default:
439                 break;
440         }
441
442 init_phy_ops_out:
443         return err;
444 }
445