2ed497c487ffae7d19ae5ed7adad33fb24cdd02b
[dpdk.git] / drivers / net / txgbe / base / txgbe_phy.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2020
3  */
4
5 #include "txgbe_hw.h"
6 #include "txgbe_eeprom.h"
7 #include "txgbe_mng.h"
8 #include "txgbe_phy.h"
9
10 /**
11  * txgbe_identify_extphy - Identify a single address for a PHY
12  * @hw: pointer to hardware structure
13  * @phy_addr: PHY address to probe
14  *
15  * Returns true if PHY found
16  */
17 static bool txgbe_identify_extphy(struct txgbe_hw *hw)
18 {
19         u16 phy_addr = 0;
20
21         if (!txgbe_validate_phy_addr(hw, phy_addr)) {
22                 DEBUGOUT("Unable to validate PHY address 0x%04X\n",
23                         phy_addr);
24                 return false;
25         }
26
27         if (txgbe_get_phy_id(hw))
28                 return false;
29
30         hw->phy.type = txgbe_get_phy_type_from_id(hw->phy.id);
31         if (hw->phy.type == txgbe_phy_unknown) {
32                 u16 ext_ability = 0;
33                 hw->phy.read_reg(hw, TXGBE_MD_PHY_EXT_ABILITY,
34                                  TXGBE_MD_DEV_PMA_PMD,
35                                  &ext_ability);
36
37                 if (ext_ability & (TXGBE_MD_PHY_10GBASET_ABILITY |
38                         TXGBE_MD_PHY_1000BASET_ABILITY))
39                         hw->phy.type = txgbe_phy_cu_unknown;
40                 else
41                         hw->phy.type = txgbe_phy_generic;
42         }
43
44         return true;
45 }
46
47 /**
48  *  txgbe_read_phy_if - Read TXGBE_ETHPHYIF register
49  *  @hw: pointer to hardware structure
50  *
51  *  Read TXGBE_ETHPHYIF register and save field values,
52  *  and check for valid field values.
53  **/
54 static s32 txgbe_read_phy_if(struct txgbe_hw *hw)
55 {
56         hw->phy.media_type = hw->phy.get_media_type(hw);
57
58         /* Save NW management interface connected on board. This is used
59          * to determine internal PHY mode.
60          */
61         hw->phy.nw_mng_if_sel = rd32(hw, TXGBE_ETHPHYIF);
62
63         /* If MDIO is connected to external PHY, then set PHY address. */
64         if (hw->phy.nw_mng_if_sel & TXGBE_ETHPHYIF_MDIO_ACT)
65                 hw->phy.addr = TXGBE_ETHPHYIF_MDIO_BASE(hw->phy.nw_mng_if_sel);
66
67         if (!hw->phy.phy_semaphore_mask) {
68                 if (hw->bus.lan_id)
69                         hw->phy.phy_semaphore_mask = TXGBE_MNGSEM_SWPHY;
70                 else
71                         hw->phy.phy_semaphore_mask = TXGBE_MNGSEM_SWPHY;
72         }
73
74         return 0;
75 }
76
77 /**
78  *  txgbe_identify_phy - Get physical layer module
79  *  @hw: pointer to hardware structure
80  *
81  *  Determines the physical layer module found on the current adapter.
82  **/
83 s32 txgbe_identify_phy(struct txgbe_hw *hw)
84 {
85         s32 err = TXGBE_ERR_PHY_ADDR_INVALID;
86
87         DEBUGFUNC("txgbe_identify_phy");
88
89         txgbe_read_phy_if(hw);
90
91         if (hw->phy.type != txgbe_phy_unknown)
92                 return 0;
93
94         /* Raptor 10GBASE-T requires an external PHY */
95         if (hw->phy.media_type == txgbe_media_type_copper) {
96                 err = txgbe_identify_extphy(hw);
97         } else if (hw->phy.media_type == txgbe_media_type_fiber) {
98                 err = txgbe_identify_module(hw);
99         } else {
100                 hw->phy.type = txgbe_phy_none;
101                 return 0;
102         }
103
104         /* Return error if SFP module has been detected but is not supported */
105         if (hw->phy.type == txgbe_phy_sfp_unsupported)
106                 return TXGBE_ERR_SFP_NOT_SUPPORTED;
107
108         return err;
109 }
110
111 /**
112  *  txgbe_validate_phy_addr - Determines phy address is valid
113  *  @hw: pointer to hardware structure
114  *  @phy_addr: PHY address
115  *
116  **/
117 bool txgbe_validate_phy_addr(struct txgbe_hw *hw, u32 phy_addr)
118 {
119         u16 phy_id = 0;
120         bool valid = false;
121
122         DEBUGFUNC("txgbe_validate_phy_addr");
123
124         hw->phy.addr = phy_addr;
125         hw->phy.read_reg(hw, TXGBE_MD_PHY_ID_HIGH,
126                              TXGBE_MD_DEV_PMA_PMD, &phy_id);
127
128         if (phy_id != 0xFFFF && phy_id != 0x0)
129                 valid = true;
130
131         DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id);
132
133         return valid;
134 }
135
136 /**
137  *  txgbe_get_phy_id - Get the phy type
138  *  @hw: pointer to hardware structure
139  *
140  **/
141 s32 txgbe_get_phy_id(struct txgbe_hw *hw)
142 {
143         u32 err;
144         u16 phy_id_high = 0;
145         u16 phy_id_low = 0;
146
147         DEBUGFUNC("txgbe_get_phy_id");
148
149         err = hw->phy.read_reg(hw, TXGBE_MD_PHY_ID_HIGH,
150                                       TXGBE_MD_DEV_PMA_PMD,
151                                       &phy_id_high);
152
153         if (err == 0) {
154                 hw->phy.id = (u32)(phy_id_high << 16);
155                 err = hw->phy.read_reg(hw, TXGBE_MD_PHY_ID_LOW,
156                                               TXGBE_MD_DEV_PMA_PMD,
157                                               &phy_id_low);
158                 hw->phy.id |= (u32)(phy_id_low & TXGBE_PHY_REVISION_MASK);
159                 hw->phy.revision = (u32)(phy_id_low & ~TXGBE_PHY_REVISION_MASK);
160         }
161         DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n",
162                   phy_id_high, phy_id_low);
163
164         return err;
165 }
166
167 /**
168  *  txgbe_get_phy_type_from_id - Get the phy type
169  *  @phy_id: PHY ID information
170  *
171  **/
172 enum txgbe_phy_type txgbe_get_phy_type_from_id(u32 phy_id)
173 {
174         enum txgbe_phy_type phy_type;
175
176         DEBUGFUNC("txgbe_get_phy_type_from_id");
177
178         switch (phy_id) {
179         case TXGBE_PHYID_TN1010:
180                 phy_type = txgbe_phy_tn;
181                 break;
182         case TXGBE_PHYID_QT2022:
183                 phy_type = txgbe_phy_qt;
184                 break;
185         case TXGBE_PHYID_ATH:
186                 phy_type = txgbe_phy_nl;
187                 break;
188         case TXGBE_PHYID_MTD3310:
189                 phy_type = txgbe_phy_cu_mtd;
190                 break;
191         default:
192                 phy_type = txgbe_phy_unknown;
193                 break;
194         }
195
196         return phy_type;
197 }
198
199 /**
200  *  txgbe_identify_module - Identifies module type
201  *  @hw: pointer to hardware structure
202  *
203  *  Determines HW type and calls appropriate function.
204  **/
205 s32 txgbe_identify_module(struct txgbe_hw *hw)
206 {
207         s32 err = TXGBE_ERR_SFP_NOT_PRESENT;
208
209         DEBUGFUNC("txgbe_identify_module");
210
211         switch (hw->phy.media_type) {
212         case txgbe_media_type_fiber:
213                 err = txgbe_identify_sfp_module(hw);
214                 break;
215
216         case txgbe_media_type_fiber_qsfp:
217                 err = txgbe_identify_qsfp_module(hw);
218                 break;
219
220         default:
221                 hw->phy.sfp_type = txgbe_sfp_type_not_present;
222                 err = TXGBE_ERR_SFP_NOT_PRESENT;
223                 break;
224         }
225
226         return err;
227 }
228
229 /**
230  *  txgbe_identify_sfp_module - Identifies SFP modules
231  *  @hw: pointer to hardware structure
232  *
233  *  Searches for and identifies the SFP module and assigns appropriate PHY type.
234  **/
235 s32 txgbe_identify_sfp_module(struct txgbe_hw *hw)
236 {
237         RTE_SET_USED(hw);
238         return 0;
239 }
240
241 /**
242  *  txgbe_identify_qsfp_module - Identifies QSFP modules
243  *  @hw: pointer to hardware structure
244  *
245  *  Searches for and identifies the QSFP module and assigns appropriate PHY type
246  **/
247 s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw)
248 {
249         RTE_SET_USED(hw);
250         return 0;
251 }
252