1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
9 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22)
12 switch (reg->device_type) {
13 case NGBE_MD_DEV_PMA_PMD:
15 case NGBE_MD_PHY_ID_HIGH:
16 case NGBE_MD_PHY_ID_LOW:
18 reg22->addr = reg->addr;
19 reg22->device_type = 0;
31 reg22->page = reg->device_type;
32 reg22->device_type = reg->device_type;
33 reg22->addr = reg->addr;
40 * ngbe_probe_phy - Identify a single address for a PHY
41 * @hw: pointer to hardware structure
42 * @phy_addr: PHY address to probe
44 * Returns true if PHY found
46 static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
48 if (!ngbe_validate_phy_addr(hw, phy_addr)) {
49 DEBUGOUT("Unable to validate PHY address 0x%04X\n",
54 if (ngbe_get_phy_id(hw))
57 if (ngbe_get_phy_type_from_id(hw))
64 * ngbe_identify_phy - Get physical layer module
65 * @hw: pointer to hardware structure
67 * Determines the physical layer module found on the current adapter.
69 s32 ngbe_identify_phy(struct ngbe_hw *hw)
71 s32 err = NGBE_ERR_PHY_ADDR_INVALID;
74 DEBUGFUNC("ngbe_identify_phy");
76 if (hw->phy.type != ngbe_phy_unknown)
80 wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK);
82 for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) {
83 if (ngbe_probe_phy(hw, phy_addr)) {
93 * ngbe_check_reset_blocked - check status of MNG FW veto bit
94 * @hw: pointer to the hardware structure
96 * This function checks the STAT.MNGVETO bit to see if there are
97 * any constraints on link from manageability. For MAC's that don't
98 * have this bit just return faluse since the link can not be blocked
101 s32 ngbe_check_reset_blocked(struct ngbe_hw *hw)
105 DEBUGFUNC("ngbe_check_reset_blocked");
107 mmngc = rd32(hw, NGBE_STAT);
108 if (mmngc & NGBE_STAT_MNGVETO) {
109 DEBUGOUT("MNG_VETO bit detected.\n");
117 * ngbe_validate_phy_addr - Determines phy address is valid
118 * @hw: pointer to hardware structure
119 * @phy_addr: PHY address
122 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr)
127 DEBUGFUNC("ngbe_validate_phy_addr");
129 if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP)
132 hw->phy.addr = phy_addr;
133 hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
134 NGBE_MD_DEV_PMA_PMD, &phy_id);
136 if (phy_id != 0xFFFF && phy_id != 0x0)
139 DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id);
145 * ngbe_get_phy_id - Get the phy ID
146 * @hw: pointer to hardware structure
149 s32 ngbe_get_phy_id(struct ngbe_hw *hw)
155 DEBUGFUNC("ngbe_get_phy_id");
157 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
160 hw->phy.id = (u32)(phy_id_high << 16);
162 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW,
165 hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK);
166 hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK);
168 DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n",
169 phy_id_high, phy_id_low);
175 * ngbe_get_phy_type_from_id - Get the phy type
178 s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
182 DEBUGFUNC("ngbe_get_phy_type_from_id");
184 switch (hw->phy.id) {
186 hw->phy.type = ngbe_phy_rtl;
189 if (hw->phy.media_type == ngbe_media_type_fiber)
190 hw->phy.type = ngbe_phy_mvl_sfi;
191 else if (hw->phy.media_type == ngbe_media_type_copper)
192 hw->phy.type = ngbe_phy_mvl;
194 status = ngbe_check_phy_mode_mvl(hw);
197 if (hw->phy.media_type == ngbe_media_type_fiber)
198 hw->phy.type = ngbe_phy_yt8521s_sfi;
200 hw->phy.type = ngbe_phy_yt8521s;
203 hw->phy.type = ngbe_phy_unknown;
204 status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
212 * ngbe_reset_phy - Performs a PHY reset
213 * @hw: pointer to hardware structure
215 s32 ngbe_reset_phy(struct ngbe_hw *hw)
219 DEBUGFUNC("ngbe_reset_phy");
221 if (hw->phy.type == ngbe_phy_unknown)
222 err = ngbe_identify_phy(hw);
224 if (err != 0 || hw->phy.type == ngbe_phy_none)
227 /* Don't reset PHY if it's shut down due to overtemp. */
228 if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP)
231 /* Blocked by MNG FW so bail */
232 if (ngbe_check_reset_blocked(hw))
235 switch (hw->phy.type) {
237 err = ngbe_reset_phy_rtl(hw);
240 case ngbe_phy_mvl_sfi:
241 err = ngbe_reset_phy_mvl(hw);
243 case ngbe_phy_yt8521s:
244 case ngbe_phy_yt8521s_sfi:
245 err = ngbe_reset_phy_yt(hw);
255 * ngbe_read_phy_mdi - Reads a value from a specified PHY register without
257 * @hw: pointer to hardware structure
258 * @reg_addr: 32 bit address of PHY register to read
259 * @device_type: 5 bit device type
260 * @phy_data: Pointer to read data from PHY register
262 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
267 /* Setup and write the address cycle command */
268 command = NGBE_MDIOSCA_REG(reg_addr) |
269 NGBE_MDIOSCA_DEV(device_type) |
270 NGBE_MDIOSCA_PORT(hw->phy.addr);
271 wr32(hw, NGBE_MDIOSCA, command);
273 command = NGBE_MDIOSCD_CMD_READ |
275 NGBE_MDIOSCD_CLOCK(6);
276 wr32(hw, NGBE_MDIOSCD, command);
279 * Check every 10 usec to see if the address cycle completed.
280 * The MDI Command bit will clear when the operation is
283 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
284 0, NULL, 100, 100)) {
285 DEBUGOUT("PHY address command did not complete\n");
289 data = rd32(hw, NGBE_MDIOSCD);
290 *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data);
296 * ngbe_read_phy_reg - Reads a value from a specified PHY register
297 * using the SWFW lock - this function is needed in most cases
298 * @hw: pointer to hardware structure
299 * @reg_addr: 32 bit address of PHY register to read
300 * @device_type: 5 bit device type
301 * @phy_data: Pointer to read data from PHY register
303 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
304 u32 device_type, u16 *phy_data)
307 u32 gssr = hw->phy.phy_semaphore_mask;
309 DEBUGFUNC("ngbe_read_phy_reg");
311 if (hw->mac.acquire_swfw_sync(hw, gssr))
312 return NGBE_ERR_SWFW_SYNC;
314 err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type,
317 hw->mac.release_swfw_sync(hw, gssr);
323 * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register
325 * @hw: pointer to hardware structure
326 * @reg_addr: 32 bit PHY register to write
327 * @device_type: 5 bit device type
328 * @phy_data: Data to write to the PHY register
330 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr,
331 u32 device_type, u16 phy_data)
336 command = NGBE_MDIOSCA_REG(reg_addr) |
337 NGBE_MDIOSCA_DEV(device_type) |
338 NGBE_MDIOSCA_PORT(hw->phy.addr);
339 wr32(hw, NGBE_MDIOSCA, command);
341 command = NGBE_MDIOSCD_CMD_WRITE |
342 NGBE_MDIOSCD_DAT(phy_data) |
344 NGBE_MDIOSCD_CLOCK(6);
345 wr32(hw, NGBE_MDIOSCD, command);
347 /* wait for completion */
348 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
349 0, NULL, 100, 100)) {
350 TLOG_DEBUG("PHY write cmd didn't complete\n");
358 * ngbe_write_phy_reg - Writes a value to specified PHY register
359 * using SWFW lock- this function is needed in most cases
360 * @hw: pointer to hardware structure
361 * @reg_addr: 32 bit PHY register to write
362 * @device_type: 5 bit device type
363 * @phy_data: Data to write to the PHY register
365 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
366 u32 device_type, u16 phy_data)
369 u32 gssr = hw->phy.phy_semaphore_mask;
371 DEBUGFUNC("ngbe_write_phy_reg");
373 if (hw->mac.acquire_swfw_sync(hw, gssr))
374 err = NGBE_ERR_SWFW_SYNC;
376 err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type,
379 hw->mac.release_swfw_sync(hw, gssr);
385 * ngbe_init_phy - PHY specific init
386 * @hw: pointer to hardware structure
388 * Initialize any function pointers that were not able to be
389 * set during init_shared_code because the PHY type was
393 s32 ngbe_init_phy(struct ngbe_hw *hw)
395 struct ngbe_phy_info *phy = &hw->phy;
398 DEBUGFUNC("ngbe_init_phy");
402 switch (hw->sub_device_id) {
403 case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
404 case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
405 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
406 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
408 case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
409 case NGBE_SUB_DEV_ID_EM_MVL_SFP:
410 case NGBE_SUB_DEV_ID_EM_MVL_MIX:
411 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
412 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
414 case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
415 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt;
416 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt;
422 hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY;
424 /* Identify the PHY */
425 err = phy->identify(hw);
426 if (err == NGBE_ERR_PHY_ADDR_INVALID)
427 goto init_phy_ops_out;
429 /* Set necessary function pointers based on PHY type */
430 switch (hw->phy.type) {
432 hw->phy.init_hw = ngbe_init_phy_rtl;
433 hw->phy.check_link = ngbe_check_phy_link_rtl;
434 hw->phy.setup_link = ngbe_setup_phy_link_rtl;
435 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl;
436 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl;
437 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl;
440 case ngbe_phy_mvl_sfi:
441 hw->phy.init_hw = ngbe_init_phy_mvl;
442 hw->phy.check_link = ngbe_check_phy_link_mvl;
443 hw->phy.setup_link = ngbe_setup_phy_link_mvl;
444 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl;
445 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl;
446 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl;
448 case ngbe_phy_yt8521s:
449 case ngbe_phy_yt8521s_sfi:
450 hw->phy.init_hw = ngbe_init_phy_yt;
451 hw->phy.check_link = ngbe_check_phy_link_yt;
452 hw->phy.setup_link = ngbe_setup_phy_link_yt;
453 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt;
454 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt;
455 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt;