1 /*******************************************************************************
3 Copyright (c) 2001-2007, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 *******************************************************************************/
36 #include "ixgbe_api.h"
37 #include "ixgbe_common.h"
38 #include "ixgbe_phy.h"
41 * ixgbe_init_shared_code_phy - Initialize PHY shared code
42 * @hw: pointer to hardware structure
44 s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw)
46 /* Assign function pointers */
47 ixgbe_assign_func_pointers_phy(hw);
53 * ixgbe_assign_func_pointers_phy - Assigns PHY-specific function pointers
54 * @hw: pointer to hardware structure
56 * Note, generic function pointers have already been assigned, so the
57 * function pointers set here are only for PHY-specific functions.
59 s32 ixgbe_assign_func_pointers_phy(struct ixgbe_hw *hw)
61 hw->func.ixgbe_func_reset_phy =
62 &ixgbe_reset_phy_generic;
63 hw->func.ixgbe_func_read_phy_reg =
64 &ixgbe_read_phy_reg_generic;
65 hw->func.ixgbe_func_write_phy_reg =
66 &ixgbe_write_phy_reg_generic;
67 hw->func.ixgbe_func_identify_phy =
68 &ixgbe_identify_phy_generic;
74 * ixgbe_identify_phy_generic - Get physical layer module
75 * @hw: pointer to hardware structure
77 * Determines the physical layer module found on the current adapter.
79 s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
81 s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
84 for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
85 if (ixgbe_validate_phy_addr(hw, phy_addr)) {
86 hw->phy.addr = phy_addr;
88 hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
89 status = IXGBE_SUCCESS;
97 * ixgbe_validate_phy_addr - Determines phy address is valid
98 * @hw: pointer to hardware structure
101 bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr)
106 hw->phy.addr = phy_addr;
107 ixgbe_read_phy_reg_generic(hw,
108 IXGBE_MDIO_PHY_ID_HIGH,
109 IXGBE_MDIO_PMA_PMD_DEV_TYPE,
112 if (phy_id != 0xFFFF && phy_id != 0x0)
119 * ixgbe_get_phy_id - Get the phy type
120 * @hw: pointer to hardware structure
123 s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
129 status = ixgbe_read_phy_reg_generic(hw,
130 IXGBE_MDIO_PHY_ID_HIGH,
131 IXGBE_MDIO_PMA_PMD_DEV_TYPE,
134 if (status == IXGBE_SUCCESS) {
135 hw->phy.id = (u32)(phy_id_high << 16);
136 status = ixgbe_read_phy_reg_generic(hw,
137 IXGBE_MDIO_PHY_ID_LOW,
138 IXGBE_MDIO_PMA_PMD_DEV_TYPE,
140 hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
141 hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
148 * ixgbe_get_phy_type_from_id - Get the phy type
149 * @hw: pointer to hardware structure
152 enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
154 enum ixgbe_phy_type phy_type;
158 phy_type = ixgbe_phy_qt;
161 phy_type = ixgbe_phy_unknown;
169 * ixgbe_reset_phy_generic - Performs a PHY reset
170 * @hw: pointer to hardware structure
172 s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
175 * Perform soft PHY reset to the PHY_XS.
176 * This will cause a soft reset to the PHY
178 return ixgbe_write_phy_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
179 IXGBE_MDIO_PHY_XS_DEV_TYPE,
180 IXGBE_MDIO_PHY_XS_RESET);
184 * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register
185 * @hw: pointer to hardware structure
186 * @reg_addr: 32 bit address of PHY register to read
187 * @phy_data: Pointer to read data from PHY register
189 s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
190 u32 device_type, u16 *phy_data)
195 s32 status = IXGBE_SUCCESS;
198 if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
199 gssr = IXGBE_GSSR_PHY1_SM;
201 gssr = IXGBE_GSSR_PHY0_SM;
203 if (ixgbe_acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
204 status = IXGBE_ERR_SWFW_SYNC;
206 if (status == IXGBE_SUCCESS) {
207 /* Setup and write the address cycle command */
208 command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
209 (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
210 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
211 (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
213 IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
216 * Check every 10 usec to see if the address cycle completed.
217 * The MDI Command bit will clear when the operation is
220 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
223 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
225 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
230 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
231 DEBUGOUT("PHY address command did not complete.\n");
232 status = IXGBE_ERR_PHY;
235 if (status == IXGBE_SUCCESS) {
237 * Address cycle complete, setup and write the read
240 command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
241 (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
242 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
243 (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
245 IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
248 * Check every 10 usec to see if the address cycle
249 * completed. The MDI Command bit will clear when the
250 * operation is complete
252 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
255 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
257 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
261 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
262 DEBUGOUT("PHY read command didn't complete\n");
263 status = IXGBE_ERR_PHY;
266 * Read operation is complete. Get the data
269 data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
270 data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
271 *phy_data = (u16)(data);
275 ixgbe_release_swfw_sync(hw, gssr);
281 * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register
282 * @hw: pointer to hardware structure
283 * @reg_addr: 32 bit PHY register to write
284 * @device_type: 5 bit device type
285 * @phy_data: Data to write to the PHY register
287 s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
288 u32 device_type, u16 phy_data)
292 s32 status = IXGBE_SUCCESS;
295 if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
296 gssr = IXGBE_GSSR_PHY1_SM;
298 gssr = IXGBE_GSSR_PHY0_SM;
300 if (ixgbe_acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
301 status = IXGBE_ERR_SWFW_SYNC;
303 if (status == IXGBE_SUCCESS) {
304 /* Put the data in the MDI single read and write data register*/
305 IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
307 /* Setup and write the address cycle command */
308 command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
309 (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
310 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
311 (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
313 IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
316 * Check every 10 usec to see if the address cycle completed.
317 * The MDI Command bit will clear when the operation is
320 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
323 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
325 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
326 DEBUGFUNC("PHY address cmd didn't complete\n");
331 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
332 status = IXGBE_ERR_PHY;
334 if (status == IXGBE_SUCCESS) {
336 * Address cycle complete, setup and write the write
339 command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
340 (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
341 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
342 (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
344 IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
347 * Check every 10 usec to see if the address cycle
348 * completed. The MDI Command bit will clear when the
349 * operation is complete
351 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
354 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
356 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
357 DEBUGFUNC("PHY write command did not "
363 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
364 status = IXGBE_ERR_PHY;
367 ixgbe_release_swfw_sync(hw, gssr);
374 * ixgbe_setup_phy_link - Restart PHY autoneg
375 * @hw: pointer to hardware structure
377 * Restart autonegotiation and PHY and waits for completion.
379 s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw)
381 return ixgbe_call_func(hw, ixgbe_func_setup_phy_link, (hw),
382 IXGBE_NOT_IMPLEMENTED);
386 * ixgbe_check_phy_link - Determine link and speed status
387 * @hw: pointer to hardware structure
389 * Reads a PHY register to determine if link is up and the current speed for
392 s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
395 return ixgbe_call_func(hw, ixgbe_func_check_phy_link, (hw, speed,
396 link_up), IXGBE_NOT_IMPLEMENTED);
400 * ixgbe_setup_phy_link_speed - Set auto advertise
401 * @hw: pointer to hardware structure
402 * @speed: new link speed
403 * @autoneg: TRUE if autonegotiation enabled
405 * Sets the auto advertised capabilities
407 s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
409 bool autoneg_wait_to_complete)
411 return ixgbe_call_func(hw, ixgbe_func_setup_phy_link_speed, (hw, speed,
412 autoneg, autoneg_wait_to_complete),
413 IXGBE_NOT_IMPLEMENTED);