1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 1999 - 2018 Intel Corporation. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/pci.h>
5*4882a593Smuzhiyun #include <linux/delay.h>
6*4882a593Smuzhiyun #include <linux/iopoll.h>
7*4882a593Smuzhiyun #include <linux/sched.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include "ixgbe.h"
10*4882a593Smuzhiyun #include "ixgbe_phy.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun static void ixgbe_i2c_start(struct ixgbe_hw *hw);
13*4882a593Smuzhiyun static void ixgbe_i2c_stop(struct ixgbe_hw *hw);
14*4882a593Smuzhiyun static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data);
15*4882a593Smuzhiyun static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data);
16*4882a593Smuzhiyun static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw);
17*4882a593Smuzhiyun static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data);
18*4882a593Smuzhiyun static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data);
19*4882a593Smuzhiyun static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
20*4882a593Smuzhiyun static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
21*4882a593Smuzhiyun static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data);
22*4882a593Smuzhiyun static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl);
23*4882a593Smuzhiyun static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
24*4882a593Smuzhiyun static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
25*4882a593Smuzhiyun static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
26*4882a593Smuzhiyun static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /**
29*4882a593Smuzhiyun * ixgbe_out_i2c_byte_ack - Send I2C byte with ack
30*4882a593Smuzhiyun * @hw: pointer to the hardware structure
31*4882a593Smuzhiyun * @byte: byte to send
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * Returns an error code on error.
34*4882a593Smuzhiyun **/
ixgbe_out_i2c_byte_ack(struct ixgbe_hw * hw,u8 byte)35*4882a593Smuzhiyun static s32 ixgbe_out_i2c_byte_ack(struct ixgbe_hw *hw, u8 byte)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun s32 status;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, byte);
40*4882a593Smuzhiyun if (status)
41*4882a593Smuzhiyun return status;
42*4882a593Smuzhiyun return ixgbe_get_i2c_ack(hw);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /**
46*4882a593Smuzhiyun * ixgbe_in_i2c_byte_ack - Receive an I2C byte and send ack
47*4882a593Smuzhiyun * @hw: pointer to the hardware structure
48*4882a593Smuzhiyun * @byte: pointer to a u8 to receive the byte
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * Returns an error code on error.
51*4882a593Smuzhiyun **/
ixgbe_in_i2c_byte_ack(struct ixgbe_hw * hw,u8 * byte)52*4882a593Smuzhiyun static s32 ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun s32 status;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun status = ixgbe_clock_in_i2c_byte(hw, byte);
57*4882a593Smuzhiyun if (status)
58*4882a593Smuzhiyun return status;
59*4882a593Smuzhiyun /* ACK */
60*4882a593Smuzhiyun return ixgbe_clock_out_i2c_bit(hw, false);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /**
64*4882a593Smuzhiyun * ixgbe_ones_comp_byte_add - Perform one's complement addition
65*4882a593Smuzhiyun * @add1: addend 1
66*4882a593Smuzhiyun * @add2: addend 2
67*4882a593Smuzhiyun *
68*4882a593Smuzhiyun * Returns one's complement 8-bit sum.
69*4882a593Smuzhiyun **/
ixgbe_ones_comp_byte_add(u8 add1,u8 add2)70*4882a593Smuzhiyun static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun u16 sum = add1 + add2;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun sum = (sum & 0xFF) + (sum >> 8);
75*4882a593Smuzhiyun return sum & 0xFF;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /**
79*4882a593Smuzhiyun * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation
80*4882a593Smuzhiyun * @hw: pointer to the hardware structure
81*4882a593Smuzhiyun * @addr: I2C bus address to read from
82*4882a593Smuzhiyun * @reg: I2C device register to read from
83*4882a593Smuzhiyun * @val: pointer to location to receive read value
84*4882a593Smuzhiyun * @lock: true if to take and release semaphore
85*4882a593Smuzhiyun *
86*4882a593Smuzhiyun * Returns an error code on error.
87*4882a593Smuzhiyun */
ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 * val,bool lock)88*4882a593Smuzhiyun s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
89*4882a593Smuzhiyun u16 reg, u16 *val, bool lock)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun u32 swfw_mask = hw->phy.phy_semaphore_mask;
92*4882a593Smuzhiyun int max_retry = 3;
93*4882a593Smuzhiyun int retry = 0;
94*4882a593Smuzhiyun u8 csum_byte;
95*4882a593Smuzhiyun u8 high_bits;
96*4882a593Smuzhiyun u8 low_bits;
97*4882a593Smuzhiyun u8 reg_high;
98*4882a593Smuzhiyun u8 csum;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun reg_high = ((reg >> 7) & 0xFE) | 1; /* Indicate read combined */
101*4882a593Smuzhiyun csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
102*4882a593Smuzhiyun csum = ~csum;
103*4882a593Smuzhiyun do {
104*4882a593Smuzhiyun if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
105*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
106*4882a593Smuzhiyun ixgbe_i2c_start(hw);
107*4882a593Smuzhiyun /* Device Address and write indication */
108*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, addr))
109*4882a593Smuzhiyun goto fail;
110*4882a593Smuzhiyun /* Write bits 14:8 */
111*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, reg_high))
112*4882a593Smuzhiyun goto fail;
113*4882a593Smuzhiyun /* Write bits 7:0 */
114*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF))
115*4882a593Smuzhiyun goto fail;
116*4882a593Smuzhiyun /* Write csum */
117*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, csum))
118*4882a593Smuzhiyun goto fail;
119*4882a593Smuzhiyun /* Re-start condition */
120*4882a593Smuzhiyun ixgbe_i2c_start(hw);
121*4882a593Smuzhiyun /* Device Address and read indication */
122*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, addr | 1))
123*4882a593Smuzhiyun goto fail;
124*4882a593Smuzhiyun /* Get upper bits */
125*4882a593Smuzhiyun if (ixgbe_in_i2c_byte_ack(hw, &high_bits))
126*4882a593Smuzhiyun goto fail;
127*4882a593Smuzhiyun /* Get low bits */
128*4882a593Smuzhiyun if (ixgbe_in_i2c_byte_ack(hw, &low_bits))
129*4882a593Smuzhiyun goto fail;
130*4882a593Smuzhiyun /* Get csum */
131*4882a593Smuzhiyun if (ixgbe_clock_in_i2c_byte(hw, &csum_byte))
132*4882a593Smuzhiyun goto fail;
133*4882a593Smuzhiyun /* NACK */
134*4882a593Smuzhiyun if (ixgbe_clock_out_i2c_bit(hw, false))
135*4882a593Smuzhiyun goto fail;
136*4882a593Smuzhiyun ixgbe_i2c_stop(hw);
137*4882a593Smuzhiyun if (lock)
138*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
139*4882a593Smuzhiyun *val = (high_bits << 8) | low_bits;
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun fail:
143*4882a593Smuzhiyun ixgbe_i2c_bus_clear(hw);
144*4882a593Smuzhiyun if (lock)
145*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
146*4882a593Smuzhiyun retry++;
147*4882a593Smuzhiyun if (retry < max_retry)
148*4882a593Smuzhiyun hw_dbg(hw, "I2C byte read combined error - Retry.\n");
149*4882a593Smuzhiyun else
150*4882a593Smuzhiyun hw_dbg(hw, "I2C byte read combined error.\n");
151*4882a593Smuzhiyun } while (retry < max_retry);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return IXGBE_ERR_I2C;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /**
157*4882a593Smuzhiyun * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
158*4882a593Smuzhiyun * @hw: pointer to the hardware structure
159*4882a593Smuzhiyun * @addr: I2C bus address to write to
160*4882a593Smuzhiyun * @reg: I2C device register to write to
161*4882a593Smuzhiyun * @val: value to write
162*4882a593Smuzhiyun * @lock: true if to take and release semaphore
163*4882a593Smuzhiyun *
164*4882a593Smuzhiyun * Returns an error code on error.
165*4882a593Smuzhiyun */
ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw * hw,u8 addr,u16 reg,u16 val,bool lock)166*4882a593Smuzhiyun s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
167*4882a593Smuzhiyun u16 reg, u16 val, bool lock)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun u32 swfw_mask = hw->phy.phy_semaphore_mask;
170*4882a593Smuzhiyun int max_retry = 1;
171*4882a593Smuzhiyun int retry = 0;
172*4882a593Smuzhiyun u8 reg_high;
173*4882a593Smuzhiyun u8 csum;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun reg_high = (reg >> 7) & 0xFE; /* Indicate write combined */
176*4882a593Smuzhiyun csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
177*4882a593Smuzhiyun csum = ixgbe_ones_comp_byte_add(csum, val >> 8);
178*4882a593Smuzhiyun csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF);
179*4882a593Smuzhiyun csum = ~csum;
180*4882a593Smuzhiyun do {
181*4882a593Smuzhiyun if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
182*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
183*4882a593Smuzhiyun ixgbe_i2c_start(hw);
184*4882a593Smuzhiyun /* Device Address and write indication */
185*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, addr))
186*4882a593Smuzhiyun goto fail;
187*4882a593Smuzhiyun /* Write bits 14:8 */
188*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, reg_high))
189*4882a593Smuzhiyun goto fail;
190*4882a593Smuzhiyun /* Write bits 7:0 */
191*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF))
192*4882a593Smuzhiyun goto fail;
193*4882a593Smuzhiyun /* Write data 15:8 */
194*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, val >> 8))
195*4882a593Smuzhiyun goto fail;
196*4882a593Smuzhiyun /* Write data 7:0 */
197*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, val & 0xFF))
198*4882a593Smuzhiyun goto fail;
199*4882a593Smuzhiyun /* Write csum */
200*4882a593Smuzhiyun if (ixgbe_out_i2c_byte_ack(hw, csum))
201*4882a593Smuzhiyun goto fail;
202*4882a593Smuzhiyun ixgbe_i2c_stop(hw);
203*4882a593Smuzhiyun if (lock)
204*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
205*4882a593Smuzhiyun return 0;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun fail:
208*4882a593Smuzhiyun ixgbe_i2c_bus_clear(hw);
209*4882a593Smuzhiyun if (lock)
210*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
211*4882a593Smuzhiyun retry++;
212*4882a593Smuzhiyun if (retry < max_retry)
213*4882a593Smuzhiyun hw_dbg(hw, "I2C byte write combined error - Retry.\n");
214*4882a593Smuzhiyun else
215*4882a593Smuzhiyun hw_dbg(hw, "I2C byte write combined error.\n");
216*4882a593Smuzhiyun } while (retry < max_retry);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun return IXGBE_ERR_I2C;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /**
222*4882a593Smuzhiyun * ixgbe_probe_phy - Probe a single address for a PHY
223*4882a593Smuzhiyun * @hw: pointer to hardware structure
224*4882a593Smuzhiyun * @phy_addr: PHY address to probe
225*4882a593Smuzhiyun *
226*4882a593Smuzhiyun * Returns true if PHY found
227*4882a593Smuzhiyun **/
ixgbe_probe_phy(struct ixgbe_hw * hw,u16 phy_addr)228*4882a593Smuzhiyun static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun u16 ext_ability = 0;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun hw->phy.mdio.prtad = phy_addr;
233*4882a593Smuzhiyun if (mdio45_probe(&hw->phy.mdio, phy_addr) != 0)
234*4882a593Smuzhiyun return false;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun if (ixgbe_get_phy_id(hw))
237*4882a593Smuzhiyun return false;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (hw->phy.type == ixgbe_phy_unknown) {
242*4882a593Smuzhiyun hw->phy.ops.read_reg(hw,
243*4882a593Smuzhiyun MDIO_PMA_EXTABLE,
244*4882a593Smuzhiyun MDIO_MMD_PMAPMD,
245*4882a593Smuzhiyun &ext_ability);
246*4882a593Smuzhiyun if (ext_ability &
247*4882a593Smuzhiyun (MDIO_PMA_EXTABLE_10GBT |
248*4882a593Smuzhiyun MDIO_PMA_EXTABLE_1000BT))
249*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_cu_unknown;
250*4882a593Smuzhiyun else
251*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_generic;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return true;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun /**
258*4882a593Smuzhiyun * ixgbe_identify_phy_generic - Get physical layer module
259*4882a593Smuzhiyun * @hw: pointer to hardware structure
260*4882a593Smuzhiyun *
261*4882a593Smuzhiyun * Determines the physical layer module found on the current adapter.
262*4882a593Smuzhiyun **/
ixgbe_identify_phy_generic(struct ixgbe_hw * hw)263*4882a593Smuzhiyun s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun u32 phy_addr;
266*4882a593Smuzhiyun u32 status = IXGBE_ERR_PHY_ADDR_INVALID;
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (!hw->phy.phy_semaphore_mask) {
269*4882a593Smuzhiyun if (hw->bus.lan_id)
270*4882a593Smuzhiyun hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
271*4882a593Smuzhiyun else
272*4882a593Smuzhiyun hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (hw->phy.type != ixgbe_phy_unknown)
276*4882a593Smuzhiyun return 0;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (hw->phy.nw_mng_if_sel) {
279*4882a593Smuzhiyun phy_addr = (hw->phy.nw_mng_if_sel &
280*4882a593Smuzhiyun IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
281*4882a593Smuzhiyun IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
282*4882a593Smuzhiyun if (ixgbe_probe_phy(hw, phy_addr))
283*4882a593Smuzhiyun return 0;
284*4882a593Smuzhiyun else
285*4882a593Smuzhiyun return IXGBE_ERR_PHY_ADDR_INVALID;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
289*4882a593Smuzhiyun if (ixgbe_probe_phy(hw, phy_addr)) {
290*4882a593Smuzhiyun status = 0;
291*4882a593Smuzhiyun break;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /* Certain media types do not have a phy so an address will not
296*4882a593Smuzhiyun * be found and the code will take this path. Caller has to
297*4882a593Smuzhiyun * decide if it is an error or not.
298*4882a593Smuzhiyun */
299*4882a593Smuzhiyun if (status)
300*4882a593Smuzhiyun hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return status;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /**
306*4882a593Smuzhiyun * ixgbe_check_reset_blocked - check status of MNG FW veto bit
307*4882a593Smuzhiyun * @hw: pointer to the hardware structure
308*4882a593Smuzhiyun *
309*4882a593Smuzhiyun * This function checks the MMNGC.MNG_VETO bit to see if there are
310*4882a593Smuzhiyun * any constraints on link from manageability. For MAC's that don't
311*4882a593Smuzhiyun * have this bit just return false since the link can not be blocked
312*4882a593Smuzhiyun * via this method.
313*4882a593Smuzhiyun **/
ixgbe_check_reset_blocked(struct ixgbe_hw * hw)314*4882a593Smuzhiyun bool ixgbe_check_reset_blocked(struct ixgbe_hw *hw)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun u32 mmngc;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* If we don't have this bit, it can't be blocking */
319*4882a593Smuzhiyun if (hw->mac.type == ixgbe_mac_82598EB)
320*4882a593Smuzhiyun return false;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC);
323*4882a593Smuzhiyun if (mmngc & IXGBE_MMNGC_MNG_VETO) {
324*4882a593Smuzhiyun hw_dbg(hw, "MNG_VETO bit detected.\n");
325*4882a593Smuzhiyun return true;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun return false;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /**
332*4882a593Smuzhiyun * ixgbe_get_phy_id - Get the phy type
333*4882a593Smuzhiyun * @hw: pointer to hardware structure
334*4882a593Smuzhiyun *
335*4882a593Smuzhiyun **/
ixgbe_get_phy_id(struct ixgbe_hw * hw)336*4882a593Smuzhiyun static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun s32 status;
339*4882a593Smuzhiyun u16 phy_id_high = 0;
340*4882a593Smuzhiyun u16 phy_id_low = 0;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw, MDIO_DEVID1, MDIO_MMD_PMAPMD,
343*4882a593Smuzhiyun &phy_id_high);
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if (!status) {
346*4882a593Smuzhiyun hw->phy.id = (u32)(phy_id_high << 16);
347*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw, MDIO_DEVID2, MDIO_MMD_PMAPMD,
348*4882a593Smuzhiyun &phy_id_low);
349*4882a593Smuzhiyun hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
350*4882a593Smuzhiyun hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun return status;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /**
356*4882a593Smuzhiyun * ixgbe_get_phy_type_from_id - Get the phy type
357*4882a593Smuzhiyun * @phy_id: hardware phy id
358*4882a593Smuzhiyun *
359*4882a593Smuzhiyun **/
ixgbe_get_phy_type_from_id(u32 phy_id)360*4882a593Smuzhiyun static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun enum ixgbe_phy_type phy_type;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun switch (phy_id) {
365*4882a593Smuzhiyun case TN1010_PHY_ID:
366*4882a593Smuzhiyun phy_type = ixgbe_phy_tn;
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun case X550_PHY_ID2:
369*4882a593Smuzhiyun case X550_PHY_ID3:
370*4882a593Smuzhiyun case X540_PHY_ID:
371*4882a593Smuzhiyun phy_type = ixgbe_phy_aq;
372*4882a593Smuzhiyun break;
373*4882a593Smuzhiyun case QT2022_PHY_ID:
374*4882a593Smuzhiyun phy_type = ixgbe_phy_qt;
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun case ATH_PHY_ID:
377*4882a593Smuzhiyun phy_type = ixgbe_phy_nl;
378*4882a593Smuzhiyun break;
379*4882a593Smuzhiyun case X557_PHY_ID:
380*4882a593Smuzhiyun case X557_PHY_ID2:
381*4882a593Smuzhiyun phy_type = ixgbe_phy_x550em_ext_t;
382*4882a593Smuzhiyun break;
383*4882a593Smuzhiyun default:
384*4882a593Smuzhiyun phy_type = ixgbe_phy_unknown;
385*4882a593Smuzhiyun break;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun return phy_type;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /**
392*4882a593Smuzhiyun * ixgbe_reset_phy_generic - Performs a PHY reset
393*4882a593Smuzhiyun * @hw: pointer to hardware structure
394*4882a593Smuzhiyun **/
ixgbe_reset_phy_generic(struct ixgbe_hw * hw)395*4882a593Smuzhiyun s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun u32 i;
398*4882a593Smuzhiyun u16 ctrl = 0;
399*4882a593Smuzhiyun s32 status = 0;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun if (hw->phy.type == ixgbe_phy_unknown)
402*4882a593Smuzhiyun status = ixgbe_identify_phy_generic(hw);
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (status != 0 || hw->phy.type == ixgbe_phy_none)
405*4882a593Smuzhiyun return status;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Don't reset PHY if it's shut down due to overtemp. */
408*4882a593Smuzhiyun if (!hw->phy.reset_if_overtemp &&
409*4882a593Smuzhiyun (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
410*4882a593Smuzhiyun return 0;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* Blocked by MNG FW so bail */
413*4882a593Smuzhiyun if (ixgbe_check_reset_blocked(hw))
414*4882a593Smuzhiyun return 0;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun /*
417*4882a593Smuzhiyun * Perform soft PHY reset to the PHY_XS.
418*4882a593Smuzhiyun * This will cause a soft reset to the PHY
419*4882a593Smuzhiyun */
420*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_CTRL1,
421*4882a593Smuzhiyun MDIO_MMD_PHYXS,
422*4882a593Smuzhiyun MDIO_CTRL1_RESET);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /*
425*4882a593Smuzhiyun * Poll for reset bit to self-clear indicating reset is complete.
426*4882a593Smuzhiyun * Some PHYs could take up to 3 seconds to complete and need about
427*4882a593Smuzhiyun * 1.7 usec delay after the reset is complete.
428*4882a593Smuzhiyun */
429*4882a593Smuzhiyun for (i = 0; i < 30; i++) {
430*4882a593Smuzhiyun msleep(100);
431*4882a593Smuzhiyun if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
432*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw,
433*4882a593Smuzhiyun IXGBE_MDIO_TX_VENDOR_ALARMS_3,
434*4882a593Smuzhiyun MDIO_MMD_PMAPMD, &ctrl);
435*4882a593Smuzhiyun if (status)
436*4882a593Smuzhiyun return status;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun if (ctrl & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
439*4882a593Smuzhiyun udelay(2);
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun } else {
443*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw, MDIO_CTRL1,
444*4882a593Smuzhiyun MDIO_MMD_PHYXS, &ctrl);
445*4882a593Smuzhiyun if (status)
446*4882a593Smuzhiyun return status;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (!(ctrl & MDIO_CTRL1_RESET)) {
449*4882a593Smuzhiyun udelay(2);
450*4882a593Smuzhiyun break;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun if (ctrl & MDIO_CTRL1_RESET) {
456*4882a593Smuzhiyun hw_dbg(hw, "PHY reset polling failed to complete.\n");
457*4882a593Smuzhiyun return IXGBE_ERR_RESET_FAILED;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun return 0;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /**
464*4882a593Smuzhiyun * ixgbe_read_phy_mdi - Reads a value from a specified PHY register without
465*4882a593Smuzhiyun * the SWFW lock
466*4882a593Smuzhiyun * @hw: pointer to hardware structure
467*4882a593Smuzhiyun * @reg_addr: 32 bit address of PHY register to read
468*4882a593Smuzhiyun * @device_type: 5 bit device type
469*4882a593Smuzhiyun * @phy_data: Pointer to read data from PHY register
470*4882a593Smuzhiyun **/
ixgbe_read_phy_reg_mdi(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)471*4882a593Smuzhiyun s32 ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
472*4882a593Smuzhiyun u16 *phy_data)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun u32 i, data, command;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun /* Setup and write the address cycle command */
477*4882a593Smuzhiyun command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
478*4882a593Smuzhiyun (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
479*4882a593Smuzhiyun (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
480*4882a593Smuzhiyun (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /* Check every 10 usec to see if the address cycle completed.
485*4882a593Smuzhiyun * The MDI Command bit will clear when the operation is
486*4882a593Smuzhiyun * complete
487*4882a593Smuzhiyun */
488*4882a593Smuzhiyun for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
489*4882a593Smuzhiyun udelay(10);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun command = IXGBE_READ_REG(hw, IXGBE_MSCA);
492*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
493*4882a593Smuzhiyun break;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
498*4882a593Smuzhiyun hw_dbg(hw, "PHY address command did not complete.\n");
499*4882a593Smuzhiyun return IXGBE_ERR_PHY;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /* Address cycle complete, setup and write the read
503*4882a593Smuzhiyun * command
504*4882a593Smuzhiyun */
505*4882a593Smuzhiyun command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
506*4882a593Smuzhiyun (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
507*4882a593Smuzhiyun (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
508*4882a593Smuzhiyun (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun /* Check every 10 usec to see if the address cycle
513*4882a593Smuzhiyun * completed. The MDI Command bit will clear when the
514*4882a593Smuzhiyun * operation is complete
515*4882a593Smuzhiyun */
516*4882a593Smuzhiyun for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
517*4882a593Smuzhiyun udelay(10);
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun command = IXGBE_READ_REG(hw, IXGBE_MSCA);
520*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
521*4882a593Smuzhiyun break;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
525*4882a593Smuzhiyun hw_dbg(hw, "PHY read command didn't complete\n");
526*4882a593Smuzhiyun return IXGBE_ERR_PHY;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* Read operation is complete. Get the data
530*4882a593Smuzhiyun * from MSRWD
531*4882a593Smuzhiyun */
532*4882a593Smuzhiyun data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
533*4882a593Smuzhiyun data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
534*4882a593Smuzhiyun *phy_data = (u16)(data);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun return 0;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /**
540*4882a593Smuzhiyun * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register
541*4882a593Smuzhiyun * using the SWFW lock - this function is needed in most cases
542*4882a593Smuzhiyun * @hw: pointer to hardware structure
543*4882a593Smuzhiyun * @reg_addr: 32 bit address of PHY register to read
544*4882a593Smuzhiyun * @device_type: 5 bit device type
545*4882a593Smuzhiyun * @phy_data: Pointer to read data from PHY register
546*4882a593Smuzhiyun **/
ixgbe_read_phy_reg_generic(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)547*4882a593Smuzhiyun s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
548*4882a593Smuzhiyun u32 device_type, u16 *phy_data)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun s32 status;
551*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == 0) {
554*4882a593Smuzhiyun status = ixgbe_read_phy_reg_mdi(hw, reg_addr, device_type,
555*4882a593Smuzhiyun phy_data);
556*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, gssr);
557*4882a593Smuzhiyun } else {
558*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun return status;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /**
565*4882a593Smuzhiyun * ixgbe_write_phy_reg_mdi - Writes a value to specified PHY register
566*4882a593Smuzhiyun * without SWFW lock
567*4882a593Smuzhiyun * @hw: pointer to hardware structure
568*4882a593Smuzhiyun * @reg_addr: 32 bit PHY register to write
569*4882a593Smuzhiyun * @device_type: 5 bit device type
570*4882a593Smuzhiyun * @phy_data: Data to write to the PHY register
571*4882a593Smuzhiyun **/
ixgbe_write_phy_reg_mdi(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)572*4882a593Smuzhiyun s32 ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr,
573*4882a593Smuzhiyun u32 device_type, u16 phy_data)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun u32 i, command;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun /* Put the data in the MDI single read and write data register*/
578*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* Setup and write the address cycle command */
581*4882a593Smuzhiyun command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
582*4882a593Smuzhiyun (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
583*4882a593Smuzhiyun (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
584*4882a593Smuzhiyun (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun /*
589*4882a593Smuzhiyun * Check every 10 usec to see if the address cycle completed.
590*4882a593Smuzhiyun * The MDI Command bit will clear when the operation is
591*4882a593Smuzhiyun * complete
592*4882a593Smuzhiyun */
593*4882a593Smuzhiyun for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
594*4882a593Smuzhiyun udelay(10);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun command = IXGBE_READ_REG(hw, IXGBE_MSCA);
597*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
598*4882a593Smuzhiyun break;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
602*4882a593Smuzhiyun hw_dbg(hw, "PHY address cmd didn't complete\n");
603*4882a593Smuzhiyun return IXGBE_ERR_PHY;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun /*
607*4882a593Smuzhiyun * Address cycle complete, setup and write the write
608*4882a593Smuzhiyun * command
609*4882a593Smuzhiyun */
610*4882a593Smuzhiyun command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
611*4882a593Smuzhiyun (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
612*4882a593Smuzhiyun (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
613*4882a593Smuzhiyun (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun /* Check every 10 usec to see if the address cycle
618*4882a593Smuzhiyun * completed. The MDI Command bit will clear when the
619*4882a593Smuzhiyun * operation is complete
620*4882a593Smuzhiyun */
621*4882a593Smuzhiyun for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
622*4882a593Smuzhiyun udelay(10);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun command = IXGBE_READ_REG(hw, IXGBE_MSCA);
625*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
626*4882a593Smuzhiyun break;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
630*4882a593Smuzhiyun hw_dbg(hw, "PHY write cmd didn't complete\n");
631*4882a593Smuzhiyun return IXGBE_ERR_PHY;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun return 0;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /**
638*4882a593Smuzhiyun * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register
639*4882a593Smuzhiyun * using SWFW lock- this function is needed in most cases
640*4882a593Smuzhiyun * @hw: pointer to hardware structure
641*4882a593Smuzhiyun * @reg_addr: 32 bit PHY register to write
642*4882a593Smuzhiyun * @device_type: 5 bit device type
643*4882a593Smuzhiyun * @phy_data: Data to write to the PHY register
644*4882a593Smuzhiyun **/
ixgbe_write_phy_reg_generic(struct ixgbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)645*4882a593Smuzhiyun s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
646*4882a593Smuzhiyun u32 device_type, u16 phy_data)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun s32 status;
649*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == 0) {
652*4882a593Smuzhiyun status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type,
653*4882a593Smuzhiyun phy_data);
654*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, gssr);
655*4882a593Smuzhiyun } else {
656*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun return status;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun #define IXGBE_HW_READ_REG(addr) IXGBE_READ_REG(hw, addr)
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /**
665*4882a593Smuzhiyun * ixgbe_msca_cmd - Write the command register and poll for completion/timeout
666*4882a593Smuzhiyun * @hw: pointer to hardware structure
667*4882a593Smuzhiyun * @cmd: command register value to write
668*4882a593Smuzhiyun **/
ixgbe_msca_cmd(struct ixgbe_hw * hw,u32 cmd)669*4882a593Smuzhiyun static s32 ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSCA, cmd);
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun return readx_poll_timeout(IXGBE_HW_READ_REG, IXGBE_MSCA, cmd,
674*4882a593Smuzhiyun !(cmd & IXGBE_MSCA_MDI_COMMAND), 10,
675*4882a593Smuzhiyun 10 * IXGBE_MDIO_COMMAND_TIMEOUT);
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun /**
679*4882a593Smuzhiyun * ixgbe_mii_bus_read_generic - Read a clause 22/45 register with gssr flags
680*4882a593Smuzhiyun * @hw: pointer to hardware structure
681*4882a593Smuzhiyun * @addr: address
682*4882a593Smuzhiyun * @regnum: register number
683*4882a593Smuzhiyun * @gssr: semaphore flags to acquire
684*4882a593Smuzhiyun **/
ixgbe_mii_bus_read_generic(struct ixgbe_hw * hw,int addr,int regnum,u32 gssr)685*4882a593Smuzhiyun static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
686*4882a593Smuzhiyun int regnum, u32 gssr)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun u32 hwaddr, cmd;
689*4882a593Smuzhiyun s32 data;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
692*4882a593Smuzhiyun return -EBUSY;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
695*4882a593Smuzhiyun if (regnum & MII_ADDR_C45) {
696*4882a593Smuzhiyun hwaddr |= regnum & GENMASK(21, 0);
697*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
698*4882a593Smuzhiyun } else {
699*4882a593Smuzhiyun hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
700*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
701*4882a593Smuzhiyun IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun data = ixgbe_msca_cmd(hw, cmd);
705*4882a593Smuzhiyun if (data < 0)
706*4882a593Smuzhiyun goto mii_bus_read_done;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /* For a clause 45 access the address cycle just completed, we still
709*4882a593Smuzhiyun * need to do the read command, otherwise just get the data
710*4882a593Smuzhiyun */
711*4882a593Smuzhiyun if (!(regnum & MII_ADDR_C45))
712*4882a593Smuzhiyun goto do_mii_bus_read;
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND;
715*4882a593Smuzhiyun data = ixgbe_msca_cmd(hw, cmd);
716*4882a593Smuzhiyun if (data < 0)
717*4882a593Smuzhiyun goto mii_bus_read_done;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun do_mii_bus_read:
720*4882a593Smuzhiyun data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
721*4882a593Smuzhiyun data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun mii_bus_read_done:
724*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, gssr);
725*4882a593Smuzhiyun return data;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun /**
729*4882a593Smuzhiyun * ixgbe_mii_bus_write_generic - Write a clause 22/45 register with gssr flags
730*4882a593Smuzhiyun * @hw: pointer to hardware structure
731*4882a593Smuzhiyun * @addr: address
732*4882a593Smuzhiyun * @regnum: register number
733*4882a593Smuzhiyun * @val: value to write
734*4882a593Smuzhiyun * @gssr: semaphore flags to acquire
735*4882a593Smuzhiyun **/
ixgbe_mii_bus_write_generic(struct ixgbe_hw * hw,int addr,int regnum,u16 val,u32 gssr)736*4882a593Smuzhiyun static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
737*4882a593Smuzhiyun int regnum, u16 val, u32 gssr)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun u32 hwaddr, cmd;
740*4882a593Smuzhiyun s32 err;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
743*4882a593Smuzhiyun return -EBUSY;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
748*4882a593Smuzhiyun if (regnum & MII_ADDR_C45) {
749*4882a593Smuzhiyun hwaddr |= regnum & GENMASK(21, 0);
750*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
751*4882a593Smuzhiyun } else {
752*4882a593Smuzhiyun hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
753*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
754*4882a593Smuzhiyun IXGBE_MSCA_MDI_COMMAND;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun /* For clause 45 this is an address cycle, for clause 22 this is the
758*4882a593Smuzhiyun * entire transaction
759*4882a593Smuzhiyun */
760*4882a593Smuzhiyun err = ixgbe_msca_cmd(hw, cmd);
761*4882a593Smuzhiyun if (err < 0 || !(regnum & MII_ADDR_C45))
762*4882a593Smuzhiyun goto mii_bus_write_done;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun cmd = hwaddr | IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND;
765*4882a593Smuzhiyun err = ixgbe_msca_cmd(hw, cmd);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun mii_bus_write_done:
768*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, gssr);
769*4882a593Smuzhiyun return err;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun /**
773*4882a593Smuzhiyun * ixgbe_mii_bus_read - Read a clause 22/45 register
774*4882a593Smuzhiyun * @bus: pointer to mii_bus structure which points to our driver private
775*4882a593Smuzhiyun * @addr: address
776*4882a593Smuzhiyun * @regnum: register number
777*4882a593Smuzhiyun **/
ixgbe_mii_bus_read(struct mii_bus * bus,int addr,int regnum)778*4882a593Smuzhiyun static s32 ixgbe_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun struct ixgbe_adapter *adapter = bus->priv;
781*4882a593Smuzhiyun struct ixgbe_hw *hw = &adapter->hw;
782*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun /**
788*4882a593Smuzhiyun * ixgbe_mii_bus_write - Write a clause 22/45 register
789*4882a593Smuzhiyun * @bus: pointer to mii_bus structure which points to our driver private
790*4882a593Smuzhiyun * @addr: address
791*4882a593Smuzhiyun * @regnum: register number
792*4882a593Smuzhiyun * @val: value to write
793*4882a593Smuzhiyun **/
ixgbe_mii_bus_write(struct mii_bus * bus,int addr,int regnum,u16 val)794*4882a593Smuzhiyun static s32 ixgbe_mii_bus_write(struct mii_bus *bus, int addr, int regnum,
795*4882a593Smuzhiyun u16 val)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun struct ixgbe_adapter *adapter = bus->priv;
798*4882a593Smuzhiyun struct ixgbe_hw *hw = &adapter->hw;
799*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun /**
805*4882a593Smuzhiyun * ixgbe_x550em_a_mii_bus_read - Read a clause 22/45 register on x550em_a
806*4882a593Smuzhiyun * @bus: pointer to mii_bus structure which points to our driver private
807*4882a593Smuzhiyun * @addr: address
808*4882a593Smuzhiyun * @regnum: register number
809*4882a593Smuzhiyun **/
ixgbe_x550em_a_mii_bus_read(struct mii_bus * bus,int addr,int regnum)810*4882a593Smuzhiyun static s32 ixgbe_x550em_a_mii_bus_read(struct mii_bus *bus, int addr,
811*4882a593Smuzhiyun int regnum)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun struct ixgbe_adapter *adapter = bus->priv;
814*4882a593Smuzhiyun struct ixgbe_hw *hw = &adapter->hw;
815*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
818*4882a593Smuzhiyun return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun /**
822*4882a593Smuzhiyun * ixgbe_x550em_a_mii_bus_write - Write a clause 22/45 register on x550em_a
823*4882a593Smuzhiyun * @bus: pointer to mii_bus structure which points to our driver private
824*4882a593Smuzhiyun * @addr: address
825*4882a593Smuzhiyun * @regnum: register number
826*4882a593Smuzhiyun * @val: value to write
827*4882a593Smuzhiyun **/
ixgbe_x550em_a_mii_bus_write(struct mii_bus * bus,int addr,int regnum,u16 val)828*4882a593Smuzhiyun static s32 ixgbe_x550em_a_mii_bus_write(struct mii_bus *bus, int addr,
829*4882a593Smuzhiyun int regnum, u16 val)
830*4882a593Smuzhiyun {
831*4882a593Smuzhiyun struct ixgbe_adapter *adapter = bus->priv;
832*4882a593Smuzhiyun struct ixgbe_hw *hw = &adapter->hw;
833*4882a593Smuzhiyun u32 gssr = hw->phy.phy_semaphore_mask;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
836*4882a593Smuzhiyun return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun /**
840*4882a593Smuzhiyun * ixgbe_get_first_secondary_devfn - get first device downstream of root port
841*4882a593Smuzhiyun * @devfn: PCI_DEVFN of root port on domain 0, bus 0
842*4882a593Smuzhiyun *
843*4882a593Smuzhiyun * Returns pci_dev pointer to PCI_DEVFN(0, 0) on subordinate side of root
844*4882a593Smuzhiyun * on domain 0, bus 0, devfn = 'devfn'
845*4882a593Smuzhiyun **/
ixgbe_get_first_secondary_devfn(unsigned int devfn)846*4882a593Smuzhiyun static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun struct pci_dev *rp_pdev;
849*4882a593Smuzhiyun int bus;
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
852*4882a593Smuzhiyun if (rp_pdev && rp_pdev->subordinate) {
853*4882a593Smuzhiyun bus = rp_pdev->subordinate->number;
854*4882a593Smuzhiyun return pci_get_domain_bus_and_slot(0, bus, 0);
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun return NULL;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun /**
861*4882a593Smuzhiyun * ixgbe_x550em_a_has_mii - is this the first ixgbe x550em_a PCI function?
862*4882a593Smuzhiyun * @hw: pointer to hardware structure
863*4882a593Smuzhiyun *
864*4882a593Smuzhiyun * Returns true if hw points to lowest numbered PCI B:D.F x550_em_a device in
865*4882a593Smuzhiyun * the SoC. There are up to 4 MACs sharing a single MDIO bus on the x550em_a,
866*4882a593Smuzhiyun * but we only want to register one MDIO bus.
867*4882a593Smuzhiyun **/
ixgbe_x550em_a_has_mii(struct ixgbe_hw * hw)868*4882a593Smuzhiyun static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun struct ixgbe_adapter *adapter = hw->back;
871*4882a593Smuzhiyun struct pci_dev *pdev = adapter->pdev;
872*4882a593Smuzhiyun struct pci_dev *func0_pdev;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun /* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
875*4882a593Smuzhiyun * are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
876*4882a593Smuzhiyun * It's not valid for function 0 to be disabled and function 1 is up,
877*4882a593Smuzhiyun * so the lowest numbered ixgbe dev will be device 0 function 0 on one
878*4882a593Smuzhiyun * of those two root ports
879*4882a593Smuzhiyun */
880*4882a593Smuzhiyun func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
881*4882a593Smuzhiyun if (func0_pdev) {
882*4882a593Smuzhiyun if (func0_pdev == pdev)
883*4882a593Smuzhiyun return true;
884*4882a593Smuzhiyun else
885*4882a593Smuzhiyun return false;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
888*4882a593Smuzhiyun if (func0_pdev == pdev)
889*4882a593Smuzhiyun return true;
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun return false;
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun /**
895*4882a593Smuzhiyun * ixgbe_mii_bus_init - mii_bus structure setup
896*4882a593Smuzhiyun * @hw: pointer to hardware structure
897*4882a593Smuzhiyun *
898*4882a593Smuzhiyun * Returns 0 on success, negative on failure
899*4882a593Smuzhiyun *
900*4882a593Smuzhiyun * ixgbe_mii_bus_init initializes a mii_bus structure in adapter
901*4882a593Smuzhiyun **/
ixgbe_mii_bus_init(struct ixgbe_hw * hw)902*4882a593Smuzhiyun s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun s32 (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
905*4882a593Smuzhiyun s32 (*read)(struct mii_bus *bus, int addr, int regnum);
906*4882a593Smuzhiyun struct ixgbe_adapter *adapter = hw->back;
907*4882a593Smuzhiyun struct pci_dev *pdev = adapter->pdev;
908*4882a593Smuzhiyun struct device *dev = &adapter->netdev->dev;
909*4882a593Smuzhiyun struct mii_bus *bus;
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun switch (hw->device_id) {
912*4882a593Smuzhiyun /* C3000 SoCs */
913*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_KR:
914*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_KR_L:
915*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_SFP_N:
916*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_SGMII:
917*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_SGMII_L:
918*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_10G_T:
919*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_SFP:
920*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_1G_T:
921*4882a593Smuzhiyun case IXGBE_DEV_ID_X550EM_A_1G_T_L:
922*4882a593Smuzhiyun if (!ixgbe_x550em_a_has_mii(hw))
923*4882a593Smuzhiyun return 0;
924*4882a593Smuzhiyun read = &ixgbe_x550em_a_mii_bus_read;
925*4882a593Smuzhiyun write = &ixgbe_x550em_a_mii_bus_write;
926*4882a593Smuzhiyun break;
927*4882a593Smuzhiyun default:
928*4882a593Smuzhiyun read = &ixgbe_mii_bus_read;
929*4882a593Smuzhiyun write = &ixgbe_mii_bus_write;
930*4882a593Smuzhiyun break;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun bus = devm_mdiobus_alloc(dev);
934*4882a593Smuzhiyun if (!bus)
935*4882a593Smuzhiyun return -ENOMEM;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun bus->read = read;
938*4882a593Smuzhiyun bus->write = write;
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun /* Use the position of the device in the PCI hierarchy as the id */
941*4882a593Smuzhiyun snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mdio-%s", ixgbe_driver_name,
942*4882a593Smuzhiyun pci_name(pdev));
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun bus->name = "ixgbe-mdio";
945*4882a593Smuzhiyun bus->priv = adapter;
946*4882a593Smuzhiyun bus->parent = dev;
947*4882a593Smuzhiyun bus->phy_mask = GENMASK(31, 0);
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun /* Support clause 22/45 natively. ixgbe_probe() sets MDIO_EMULATE_C22
950*4882a593Smuzhiyun * unfortunately that causes some clause 22 frames to be sent with
951*4882a593Smuzhiyun * clause 45 addressing. We don't want that.
952*4882a593Smuzhiyun */
953*4882a593Smuzhiyun hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22;
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun adapter->mii_bus = bus;
956*4882a593Smuzhiyun return mdiobus_register(bus);
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun /**
960*4882a593Smuzhiyun * ixgbe_setup_phy_link_generic - Set and restart autoneg
961*4882a593Smuzhiyun * @hw: pointer to hardware structure
962*4882a593Smuzhiyun *
963*4882a593Smuzhiyun * Restart autonegotiation and PHY and waits for completion.
964*4882a593Smuzhiyun **/
ixgbe_setup_phy_link_generic(struct ixgbe_hw * hw)965*4882a593Smuzhiyun s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun s32 status = 0;
968*4882a593Smuzhiyun u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
969*4882a593Smuzhiyun bool autoneg = false;
970*4882a593Smuzhiyun ixgbe_link_speed speed;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun /* Set or unset auto-negotiation 10G advertisement */
975*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, &autoneg_reg);
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
978*4882a593Smuzhiyun if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) &&
979*4882a593Smuzhiyun (speed & IXGBE_LINK_SPEED_10GB_FULL))
980*4882a593Smuzhiyun autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, autoneg_reg);
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
985*4882a593Smuzhiyun MDIO_MMD_AN, &autoneg_reg);
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun if (hw->mac.type == ixgbe_mac_X550) {
988*4882a593Smuzhiyun /* Set or unset auto-negotiation 5G advertisement */
989*4882a593Smuzhiyun autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
990*4882a593Smuzhiyun if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) &&
991*4882a593Smuzhiyun (speed & IXGBE_LINK_SPEED_5GB_FULL))
992*4882a593Smuzhiyun autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun /* Set or unset auto-negotiation 2.5G advertisement */
995*4882a593Smuzhiyun autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
996*4882a593Smuzhiyun if ((hw->phy.autoneg_advertised &
997*4882a593Smuzhiyun IXGBE_LINK_SPEED_2_5GB_FULL) &&
998*4882a593Smuzhiyun (speed & IXGBE_LINK_SPEED_2_5GB_FULL))
999*4882a593Smuzhiyun autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
1000*4882a593Smuzhiyun }
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun /* Set or unset auto-negotiation 1G advertisement */
1003*4882a593Smuzhiyun autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
1004*4882a593Smuzhiyun if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) &&
1005*4882a593Smuzhiyun (speed & IXGBE_LINK_SPEED_1GB_FULL))
1006*4882a593Smuzhiyun autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
1009*4882a593Smuzhiyun MDIO_MMD_AN, autoneg_reg);
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun /* Set or unset auto-negotiation 100M advertisement */
1012*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun autoneg_reg &= ~(ADVERTISE_100FULL | ADVERTISE_100HALF);
1015*4882a593Smuzhiyun if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) &&
1016*4882a593Smuzhiyun (speed & IXGBE_LINK_SPEED_100_FULL))
1017*4882a593Smuzhiyun autoneg_reg |= ADVERTISE_100FULL;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun /* Blocked by MNG FW so don't reset PHY */
1022*4882a593Smuzhiyun if (ixgbe_check_reset_blocked(hw))
1023*4882a593Smuzhiyun return 0;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun /* Restart PHY autonegotiation and wait for completion */
1026*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_CTRL1,
1027*4882a593Smuzhiyun MDIO_MMD_AN, &autoneg_reg);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun autoneg_reg |= MDIO_AN_CTRL1_RESTART;
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_CTRL1,
1032*4882a593Smuzhiyun MDIO_MMD_AN, autoneg_reg);
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun return status;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun /**
1038*4882a593Smuzhiyun * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities
1039*4882a593Smuzhiyun * @hw: pointer to hardware structure
1040*4882a593Smuzhiyun * @speed: new link speed
1041*4882a593Smuzhiyun * @autoneg_wait_to_complete: unused
1042*4882a593Smuzhiyun **/
ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw * hw,ixgbe_link_speed speed,bool autoneg_wait_to_complete)1043*4882a593Smuzhiyun s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
1044*4882a593Smuzhiyun ixgbe_link_speed speed,
1045*4882a593Smuzhiyun bool autoneg_wait_to_complete)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun /* Clear autoneg_advertised and set new values based on input link
1048*4882a593Smuzhiyun * speed.
1049*4882a593Smuzhiyun */
1050*4882a593Smuzhiyun hw->phy.autoneg_advertised = 0;
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_10GB_FULL)
1053*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_5GB_FULL)
1056*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_5GB_FULL;
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_2_5GB_FULL)
1059*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_2_5GB_FULL;
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_1GB_FULL)
1062*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_100_FULL)
1065*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_10_FULL)
1068*4882a593Smuzhiyun hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10_FULL;
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun /* Setup link based on the new speed settings */
1071*4882a593Smuzhiyun if (hw->phy.ops.setup_link)
1072*4882a593Smuzhiyun hw->phy.ops.setup_link(hw);
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun return 0;
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun /**
1078*4882a593Smuzhiyun * ixgbe_get_copper_speeds_supported - Get copper link speed from phy
1079*4882a593Smuzhiyun * @hw: pointer to hardware structure
1080*4882a593Smuzhiyun *
1081*4882a593Smuzhiyun * Determines the supported link capabilities by reading the PHY auto
1082*4882a593Smuzhiyun * negotiation register.
1083*4882a593Smuzhiyun */
ixgbe_get_copper_speeds_supported(struct ixgbe_hw * hw)1084*4882a593Smuzhiyun static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun u16 speed_ability;
1087*4882a593Smuzhiyun s32 status;
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
1090*4882a593Smuzhiyun &speed_ability);
1091*4882a593Smuzhiyun if (status)
1092*4882a593Smuzhiyun return status;
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun if (speed_ability & MDIO_SPEED_10G)
1095*4882a593Smuzhiyun hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
1096*4882a593Smuzhiyun if (speed_ability & MDIO_PMA_SPEED_1000)
1097*4882a593Smuzhiyun hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
1098*4882a593Smuzhiyun if (speed_ability & MDIO_PMA_SPEED_100)
1099*4882a593Smuzhiyun hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun switch (hw->mac.type) {
1102*4882a593Smuzhiyun case ixgbe_mac_X550:
1103*4882a593Smuzhiyun hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
1104*4882a593Smuzhiyun hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
1105*4882a593Smuzhiyun break;
1106*4882a593Smuzhiyun case ixgbe_mac_X550EM_x:
1107*4882a593Smuzhiyun case ixgbe_mac_x550em_a:
1108*4882a593Smuzhiyun hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
1109*4882a593Smuzhiyun break;
1110*4882a593Smuzhiyun default:
1111*4882a593Smuzhiyun break;
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun
1114*4882a593Smuzhiyun return 0;
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun /**
1118*4882a593Smuzhiyun * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
1119*4882a593Smuzhiyun * @hw: pointer to hardware structure
1120*4882a593Smuzhiyun * @speed: pointer to link speed
1121*4882a593Smuzhiyun * @autoneg: boolean auto-negotiation value
1122*4882a593Smuzhiyun */
ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * autoneg)1123*4882a593Smuzhiyun s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
1124*4882a593Smuzhiyun ixgbe_link_speed *speed,
1125*4882a593Smuzhiyun bool *autoneg)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun s32 status = 0;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun *autoneg = true;
1130*4882a593Smuzhiyun if (!hw->phy.speeds_supported)
1131*4882a593Smuzhiyun status = ixgbe_get_copper_speeds_supported(hw);
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun *speed = hw->phy.speeds_supported;
1134*4882a593Smuzhiyun return status;
1135*4882a593Smuzhiyun }
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun /**
1138*4882a593Smuzhiyun * ixgbe_check_phy_link_tnx - Determine link and speed status
1139*4882a593Smuzhiyun * @hw: pointer to hardware structure
1140*4882a593Smuzhiyun * @speed: link speed
1141*4882a593Smuzhiyun * @link_up: status of link
1142*4882a593Smuzhiyun *
1143*4882a593Smuzhiyun * Reads the VS1 register to determine if link is up and the current speed for
1144*4882a593Smuzhiyun * the PHY.
1145*4882a593Smuzhiyun **/
ixgbe_check_phy_link_tnx(struct ixgbe_hw * hw,ixgbe_link_speed * speed,bool * link_up)1146*4882a593Smuzhiyun s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
1147*4882a593Smuzhiyun bool *link_up)
1148*4882a593Smuzhiyun {
1149*4882a593Smuzhiyun s32 status;
1150*4882a593Smuzhiyun u32 time_out;
1151*4882a593Smuzhiyun u32 max_time_out = 10;
1152*4882a593Smuzhiyun u16 phy_link = 0;
1153*4882a593Smuzhiyun u16 phy_speed = 0;
1154*4882a593Smuzhiyun u16 phy_data = 0;
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun /* Initialize speed and link to default case */
1157*4882a593Smuzhiyun *link_up = false;
1158*4882a593Smuzhiyun *speed = IXGBE_LINK_SPEED_10GB_FULL;
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun /*
1161*4882a593Smuzhiyun * Check current speed and link status of the PHY register.
1162*4882a593Smuzhiyun * This is a vendor specific register and may have to
1163*4882a593Smuzhiyun * be changed for other copper PHYs.
1164*4882a593Smuzhiyun */
1165*4882a593Smuzhiyun for (time_out = 0; time_out < max_time_out; time_out++) {
1166*4882a593Smuzhiyun udelay(10);
1167*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw,
1168*4882a593Smuzhiyun MDIO_STAT1,
1169*4882a593Smuzhiyun MDIO_MMD_VEND1,
1170*4882a593Smuzhiyun &phy_data);
1171*4882a593Smuzhiyun phy_link = phy_data &
1172*4882a593Smuzhiyun IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
1173*4882a593Smuzhiyun phy_speed = phy_data &
1174*4882a593Smuzhiyun IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
1175*4882a593Smuzhiyun if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
1176*4882a593Smuzhiyun *link_up = true;
1177*4882a593Smuzhiyun if (phy_speed ==
1178*4882a593Smuzhiyun IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
1179*4882a593Smuzhiyun *speed = IXGBE_LINK_SPEED_1GB_FULL;
1180*4882a593Smuzhiyun break;
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun }
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun return status;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun /**
1188*4882a593Smuzhiyun * ixgbe_setup_phy_link_tnx - Set and restart autoneg
1189*4882a593Smuzhiyun * @hw: pointer to hardware structure
1190*4882a593Smuzhiyun *
1191*4882a593Smuzhiyun * Restart autonegotiation and PHY and waits for completion.
1192*4882a593Smuzhiyun * This function always returns success, this is nessary since
1193*4882a593Smuzhiyun * it is called via a function pointer that could call other
1194*4882a593Smuzhiyun * functions that could return an error.
1195*4882a593Smuzhiyun **/
ixgbe_setup_phy_link_tnx(struct ixgbe_hw * hw)1196*4882a593Smuzhiyun s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
1197*4882a593Smuzhiyun {
1198*4882a593Smuzhiyun u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
1199*4882a593Smuzhiyun bool autoneg = false;
1200*4882a593Smuzhiyun ixgbe_link_speed speed;
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
1205*4882a593Smuzhiyun /* Set or unset auto-negotiation 10G advertisement */
1206*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
1207*4882a593Smuzhiyun MDIO_MMD_AN,
1208*4882a593Smuzhiyun &autoneg_reg);
1209*4882a593Smuzhiyun
1210*4882a593Smuzhiyun autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
1211*4882a593Smuzhiyun if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
1212*4882a593Smuzhiyun autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
1215*4882a593Smuzhiyun MDIO_MMD_AN,
1216*4882a593Smuzhiyun autoneg_reg);
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
1220*4882a593Smuzhiyun /* Set or unset auto-negotiation 1G advertisement */
1221*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
1222*4882a593Smuzhiyun MDIO_MMD_AN,
1223*4882a593Smuzhiyun &autoneg_reg);
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
1226*4882a593Smuzhiyun if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
1227*4882a593Smuzhiyun autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
1230*4882a593Smuzhiyun MDIO_MMD_AN,
1231*4882a593Smuzhiyun autoneg_reg);
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun if (speed & IXGBE_LINK_SPEED_100_FULL) {
1235*4882a593Smuzhiyun /* Set or unset auto-negotiation 100M advertisement */
1236*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
1237*4882a593Smuzhiyun MDIO_MMD_AN,
1238*4882a593Smuzhiyun &autoneg_reg);
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun autoneg_reg &= ~(ADVERTISE_100FULL |
1241*4882a593Smuzhiyun ADVERTISE_100HALF);
1242*4882a593Smuzhiyun if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
1243*4882a593Smuzhiyun autoneg_reg |= ADVERTISE_100FULL;
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
1246*4882a593Smuzhiyun MDIO_MMD_AN,
1247*4882a593Smuzhiyun autoneg_reg);
1248*4882a593Smuzhiyun }
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun /* Blocked by MNG FW so don't reset PHY */
1251*4882a593Smuzhiyun if (ixgbe_check_reset_blocked(hw))
1252*4882a593Smuzhiyun return 0;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun /* Restart PHY autonegotiation and wait for completion */
1255*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_CTRL1,
1256*4882a593Smuzhiyun MDIO_MMD_AN, &autoneg_reg);
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun autoneg_reg |= MDIO_AN_CTRL1_RESTART;
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_CTRL1,
1261*4882a593Smuzhiyun MDIO_MMD_AN, autoneg_reg);
1262*4882a593Smuzhiyun return 0;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun /**
1266*4882a593Smuzhiyun * ixgbe_reset_phy_nl - Performs a PHY reset
1267*4882a593Smuzhiyun * @hw: pointer to hardware structure
1268*4882a593Smuzhiyun **/
ixgbe_reset_phy_nl(struct ixgbe_hw * hw)1269*4882a593Smuzhiyun s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
1270*4882a593Smuzhiyun {
1271*4882a593Smuzhiyun u16 phy_offset, control, eword, edata, block_crc;
1272*4882a593Smuzhiyun bool end_data = false;
1273*4882a593Smuzhiyun u16 list_offset, data_offset;
1274*4882a593Smuzhiyun u16 phy_data = 0;
1275*4882a593Smuzhiyun s32 ret_val;
1276*4882a593Smuzhiyun u32 i;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun /* Blocked by MNG FW so bail */
1279*4882a593Smuzhiyun if (ixgbe_check_reset_blocked(hw))
1280*4882a593Smuzhiyun return 0;
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data);
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun /* reset the PHY and poll for completion */
1285*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
1286*4882a593Smuzhiyun (phy_data | MDIO_CTRL1_RESET));
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun for (i = 0; i < 100; i++) {
1289*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
1290*4882a593Smuzhiyun &phy_data);
1291*4882a593Smuzhiyun if ((phy_data & MDIO_CTRL1_RESET) == 0)
1292*4882a593Smuzhiyun break;
1293*4882a593Smuzhiyun usleep_range(10000, 20000);
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun if ((phy_data & MDIO_CTRL1_RESET) != 0) {
1297*4882a593Smuzhiyun hw_dbg(hw, "PHY reset did not complete.\n");
1298*4882a593Smuzhiyun return IXGBE_ERR_PHY;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun /* Get init offsets */
1302*4882a593Smuzhiyun ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
1303*4882a593Smuzhiyun &data_offset);
1304*4882a593Smuzhiyun if (ret_val)
1305*4882a593Smuzhiyun return ret_val;
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
1308*4882a593Smuzhiyun data_offset++;
1309*4882a593Smuzhiyun while (!end_data) {
1310*4882a593Smuzhiyun /*
1311*4882a593Smuzhiyun * Read control word from PHY init contents offset
1312*4882a593Smuzhiyun */
1313*4882a593Smuzhiyun ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
1314*4882a593Smuzhiyun if (ret_val)
1315*4882a593Smuzhiyun goto err_eeprom;
1316*4882a593Smuzhiyun control = (eword & IXGBE_CONTROL_MASK_NL) >>
1317*4882a593Smuzhiyun IXGBE_CONTROL_SHIFT_NL;
1318*4882a593Smuzhiyun edata = eword & IXGBE_DATA_MASK_NL;
1319*4882a593Smuzhiyun switch (control) {
1320*4882a593Smuzhiyun case IXGBE_DELAY_NL:
1321*4882a593Smuzhiyun data_offset++;
1322*4882a593Smuzhiyun hw_dbg(hw, "DELAY: %d MS\n", edata);
1323*4882a593Smuzhiyun usleep_range(edata * 1000, edata * 2000);
1324*4882a593Smuzhiyun break;
1325*4882a593Smuzhiyun case IXGBE_DATA_NL:
1326*4882a593Smuzhiyun hw_dbg(hw, "DATA:\n");
1327*4882a593Smuzhiyun data_offset++;
1328*4882a593Smuzhiyun ret_val = hw->eeprom.ops.read(hw, data_offset++,
1329*4882a593Smuzhiyun &phy_offset);
1330*4882a593Smuzhiyun if (ret_val)
1331*4882a593Smuzhiyun goto err_eeprom;
1332*4882a593Smuzhiyun for (i = 0; i < edata; i++) {
1333*4882a593Smuzhiyun ret_val = hw->eeprom.ops.read(hw, data_offset,
1334*4882a593Smuzhiyun &eword);
1335*4882a593Smuzhiyun if (ret_val)
1336*4882a593Smuzhiyun goto err_eeprom;
1337*4882a593Smuzhiyun hw->phy.ops.write_reg(hw, phy_offset,
1338*4882a593Smuzhiyun MDIO_MMD_PMAPMD, eword);
1339*4882a593Smuzhiyun hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
1340*4882a593Smuzhiyun phy_offset);
1341*4882a593Smuzhiyun data_offset++;
1342*4882a593Smuzhiyun phy_offset++;
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun break;
1345*4882a593Smuzhiyun case IXGBE_CONTROL_NL:
1346*4882a593Smuzhiyun data_offset++;
1347*4882a593Smuzhiyun hw_dbg(hw, "CONTROL:\n");
1348*4882a593Smuzhiyun if (edata == IXGBE_CONTROL_EOL_NL) {
1349*4882a593Smuzhiyun hw_dbg(hw, "EOL\n");
1350*4882a593Smuzhiyun end_data = true;
1351*4882a593Smuzhiyun } else if (edata == IXGBE_CONTROL_SOL_NL) {
1352*4882a593Smuzhiyun hw_dbg(hw, "SOL\n");
1353*4882a593Smuzhiyun } else {
1354*4882a593Smuzhiyun hw_dbg(hw, "Bad control value\n");
1355*4882a593Smuzhiyun return IXGBE_ERR_PHY;
1356*4882a593Smuzhiyun }
1357*4882a593Smuzhiyun break;
1358*4882a593Smuzhiyun default:
1359*4882a593Smuzhiyun hw_dbg(hw, "Bad control type\n");
1360*4882a593Smuzhiyun return IXGBE_ERR_PHY;
1361*4882a593Smuzhiyun }
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun return ret_val;
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun err_eeprom:
1367*4882a593Smuzhiyun hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
1368*4882a593Smuzhiyun return IXGBE_ERR_PHY;
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun /**
1372*4882a593Smuzhiyun * ixgbe_identify_module_generic - Identifies module type
1373*4882a593Smuzhiyun * @hw: pointer to hardware structure
1374*4882a593Smuzhiyun *
1375*4882a593Smuzhiyun * Determines HW type and calls appropriate function.
1376*4882a593Smuzhiyun **/
ixgbe_identify_module_generic(struct ixgbe_hw * hw)1377*4882a593Smuzhiyun s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw)
1378*4882a593Smuzhiyun {
1379*4882a593Smuzhiyun switch (hw->mac.ops.get_media_type(hw)) {
1380*4882a593Smuzhiyun case ixgbe_media_type_fiber:
1381*4882a593Smuzhiyun return ixgbe_identify_sfp_module_generic(hw);
1382*4882a593Smuzhiyun case ixgbe_media_type_fiber_qsfp:
1383*4882a593Smuzhiyun return ixgbe_identify_qsfp_module_generic(hw);
1384*4882a593Smuzhiyun default:
1385*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_not_present;
1386*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1387*4882a593Smuzhiyun }
1388*4882a593Smuzhiyun
1389*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun /**
1393*4882a593Smuzhiyun * ixgbe_identify_sfp_module_generic - Identifies SFP modules
1394*4882a593Smuzhiyun * @hw: pointer to hardware structure
1395*4882a593Smuzhiyun *
1396*4882a593Smuzhiyun * Searches for and identifies the SFP module and assigns appropriate PHY type.
1397*4882a593Smuzhiyun **/
ixgbe_identify_sfp_module_generic(struct ixgbe_hw * hw)1398*4882a593Smuzhiyun s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
1399*4882a593Smuzhiyun {
1400*4882a593Smuzhiyun struct ixgbe_adapter *adapter = hw->back;
1401*4882a593Smuzhiyun s32 status;
1402*4882a593Smuzhiyun u32 vendor_oui = 0;
1403*4882a593Smuzhiyun enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
1404*4882a593Smuzhiyun u8 identifier = 0;
1405*4882a593Smuzhiyun u8 comp_codes_1g = 0;
1406*4882a593Smuzhiyun u8 comp_codes_10g = 0;
1407*4882a593Smuzhiyun u8 oui_bytes[3] = {0, 0, 0};
1408*4882a593Smuzhiyun u8 cable_tech = 0;
1409*4882a593Smuzhiyun u8 cable_spec = 0;
1410*4882a593Smuzhiyun u16 enforce_sfp = 0;
1411*4882a593Smuzhiyun
1412*4882a593Smuzhiyun if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
1413*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_not_present;
1414*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun /* LAN ID is needed for sfp_type determination */
1418*4882a593Smuzhiyun hw->mac.ops.set_lan_id(hw);
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1421*4882a593Smuzhiyun IXGBE_SFF_IDENTIFIER,
1422*4882a593Smuzhiyun &identifier);
1423*4882a593Smuzhiyun
1424*4882a593Smuzhiyun if (status)
1425*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
1428*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1429*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1432*4882a593Smuzhiyun IXGBE_SFF_1GBE_COMP_CODES,
1433*4882a593Smuzhiyun &comp_codes_1g);
1434*4882a593Smuzhiyun
1435*4882a593Smuzhiyun if (status)
1436*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1439*4882a593Smuzhiyun IXGBE_SFF_10GBE_COMP_CODES,
1440*4882a593Smuzhiyun &comp_codes_10g);
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun if (status)
1443*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1444*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1445*4882a593Smuzhiyun IXGBE_SFF_CABLE_TECHNOLOGY,
1446*4882a593Smuzhiyun &cable_tech);
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun if (status)
1449*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun /* ID Module
1452*4882a593Smuzhiyun * =========
1453*4882a593Smuzhiyun * 0 SFP_DA_CU
1454*4882a593Smuzhiyun * 1 SFP_SR
1455*4882a593Smuzhiyun * 2 SFP_LR
1456*4882a593Smuzhiyun * 3 SFP_DA_CORE0 - 82599-specific
1457*4882a593Smuzhiyun * 4 SFP_DA_CORE1 - 82599-specific
1458*4882a593Smuzhiyun * 5 SFP_SR/LR_CORE0 - 82599-specific
1459*4882a593Smuzhiyun * 6 SFP_SR/LR_CORE1 - 82599-specific
1460*4882a593Smuzhiyun * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
1461*4882a593Smuzhiyun * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
1462*4882a593Smuzhiyun * 9 SFP_1g_cu_CORE0 - 82599-specific
1463*4882a593Smuzhiyun * 10 SFP_1g_cu_CORE1 - 82599-specific
1464*4882a593Smuzhiyun * 11 SFP_1g_sx_CORE0 - 82599-specific
1465*4882a593Smuzhiyun * 12 SFP_1g_sx_CORE1 - 82599-specific
1466*4882a593Smuzhiyun */
1467*4882a593Smuzhiyun if (hw->mac.type == ixgbe_mac_82598EB) {
1468*4882a593Smuzhiyun if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
1469*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
1470*4882a593Smuzhiyun else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
1471*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_sr;
1472*4882a593Smuzhiyun else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
1473*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_lr;
1474*4882a593Smuzhiyun else
1475*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_unknown;
1476*4882a593Smuzhiyun } else {
1477*4882a593Smuzhiyun if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
1478*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1479*4882a593Smuzhiyun hw->phy.sfp_type =
1480*4882a593Smuzhiyun ixgbe_sfp_type_da_cu_core0;
1481*4882a593Smuzhiyun else
1482*4882a593Smuzhiyun hw->phy.sfp_type =
1483*4882a593Smuzhiyun ixgbe_sfp_type_da_cu_core1;
1484*4882a593Smuzhiyun } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
1485*4882a593Smuzhiyun hw->phy.ops.read_i2c_eeprom(
1486*4882a593Smuzhiyun hw, IXGBE_SFF_CABLE_SPEC_COMP,
1487*4882a593Smuzhiyun &cable_spec);
1488*4882a593Smuzhiyun if (cable_spec &
1489*4882a593Smuzhiyun IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
1490*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1491*4882a593Smuzhiyun hw->phy.sfp_type =
1492*4882a593Smuzhiyun ixgbe_sfp_type_da_act_lmt_core0;
1493*4882a593Smuzhiyun else
1494*4882a593Smuzhiyun hw->phy.sfp_type =
1495*4882a593Smuzhiyun ixgbe_sfp_type_da_act_lmt_core1;
1496*4882a593Smuzhiyun } else {
1497*4882a593Smuzhiyun hw->phy.sfp_type =
1498*4882a593Smuzhiyun ixgbe_sfp_type_unknown;
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun } else if (comp_codes_10g &
1501*4882a593Smuzhiyun (IXGBE_SFF_10GBASESR_CAPABLE |
1502*4882a593Smuzhiyun IXGBE_SFF_10GBASELR_CAPABLE)) {
1503*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1504*4882a593Smuzhiyun hw->phy.sfp_type =
1505*4882a593Smuzhiyun ixgbe_sfp_type_srlr_core0;
1506*4882a593Smuzhiyun else
1507*4882a593Smuzhiyun hw->phy.sfp_type =
1508*4882a593Smuzhiyun ixgbe_sfp_type_srlr_core1;
1509*4882a593Smuzhiyun } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
1510*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1511*4882a593Smuzhiyun hw->phy.sfp_type =
1512*4882a593Smuzhiyun ixgbe_sfp_type_1g_cu_core0;
1513*4882a593Smuzhiyun else
1514*4882a593Smuzhiyun hw->phy.sfp_type =
1515*4882a593Smuzhiyun ixgbe_sfp_type_1g_cu_core1;
1516*4882a593Smuzhiyun } else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) {
1517*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1518*4882a593Smuzhiyun hw->phy.sfp_type =
1519*4882a593Smuzhiyun ixgbe_sfp_type_1g_sx_core0;
1520*4882a593Smuzhiyun else
1521*4882a593Smuzhiyun hw->phy.sfp_type =
1522*4882a593Smuzhiyun ixgbe_sfp_type_1g_sx_core1;
1523*4882a593Smuzhiyun } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
1524*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1525*4882a593Smuzhiyun hw->phy.sfp_type =
1526*4882a593Smuzhiyun ixgbe_sfp_type_1g_lx_core0;
1527*4882a593Smuzhiyun else
1528*4882a593Smuzhiyun hw->phy.sfp_type =
1529*4882a593Smuzhiyun ixgbe_sfp_type_1g_lx_core1;
1530*4882a593Smuzhiyun } else {
1531*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_unknown;
1532*4882a593Smuzhiyun }
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun if (hw->phy.sfp_type != stored_sfp_type)
1536*4882a593Smuzhiyun hw->phy.sfp_setup_needed = true;
1537*4882a593Smuzhiyun
1538*4882a593Smuzhiyun /* Determine if the SFP+ PHY is dual speed or not. */
1539*4882a593Smuzhiyun hw->phy.multispeed_fiber = false;
1540*4882a593Smuzhiyun if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
1541*4882a593Smuzhiyun (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
1542*4882a593Smuzhiyun ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
1543*4882a593Smuzhiyun (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
1544*4882a593Smuzhiyun hw->phy.multispeed_fiber = true;
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun /* Determine PHY vendor */
1547*4882a593Smuzhiyun if (hw->phy.type != ixgbe_phy_nl) {
1548*4882a593Smuzhiyun hw->phy.id = identifier;
1549*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1550*4882a593Smuzhiyun IXGBE_SFF_VENDOR_OUI_BYTE0,
1551*4882a593Smuzhiyun &oui_bytes[0]);
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun if (status != 0)
1554*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1557*4882a593Smuzhiyun IXGBE_SFF_VENDOR_OUI_BYTE1,
1558*4882a593Smuzhiyun &oui_bytes[1]);
1559*4882a593Smuzhiyun
1560*4882a593Smuzhiyun if (status != 0)
1561*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1564*4882a593Smuzhiyun IXGBE_SFF_VENDOR_OUI_BYTE2,
1565*4882a593Smuzhiyun &oui_bytes[2]);
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun if (status != 0)
1568*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1569*4882a593Smuzhiyun
1570*4882a593Smuzhiyun vendor_oui =
1571*4882a593Smuzhiyun ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
1572*4882a593Smuzhiyun (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
1573*4882a593Smuzhiyun (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun switch (vendor_oui) {
1576*4882a593Smuzhiyun case IXGBE_SFF_VENDOR_OUI_TYCO:
1577*4882a593Smuzhiyun if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
1578*4882a593Smuzhiyun hw->phy.type =
1579*4882a593Smuzhiyun ixgbe_phy_sfp_passive_tyco;
1580*4882a593Smuzhiyun break;
1581*4882a593Smuzhiyun case IXGBE_SFF_VENDOR_OUI_FTL:
1582*4882a593Smuzhiyun if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
1583*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_ftl_active;
1584*4882a593Smuzhiyun else
1585*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_ftl;
1586*4882a593Smuzhiyun break;
1587*4882a593Smuzhiyun case IXGBE_SFF_VENDOR_OUI_AVAGO:
1588*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_avago;
1589*4882a593Smuzhiyun break;
1590*4882a593Smuzhiyun case IXGBE_SFF_VENDOR_OUI_INTEL:
1591*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_intel;
1592*4882a593Smuzhiyun break;
1593*4882a593Smuzhiyun default:
1594*4882a593Smuzhiyun if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
1595*4882a593Smuzhiyun hw->phy.type =
1596*4882a593Smuzhiyun ixgbe_phy_sfp_passive_unknown;
1597*4882a593Smuzhiyun else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
1598*4882a593Smuzhiyun hw->phy.type =
1599*4882a593Smuzhiyun ixgbe_phy_sfp_active_unknown;
1600*4882a593Smuzhiyun else
1601*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unknown;
1602*4882a593Smuzhiyun break;
1603*4882a593Smuzhiyun }
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun /* Allow any DA cable vendor */
1607*4882a593Smuzhiyun if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
1608*4882a593Smuzhiyun IXGBE_SFF_DA_ACTIVE_CABLE))
1609*4882a593Smuzhiyun return 0;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun /* Verify supported 1G SFP modules */
1612*4882a593Smuzhiyun if (comp_codes_10g == 0 &&
1613*4882a593Smuzhiyun !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
1614*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
1615*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1616*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
1617*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1618*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
1619*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1620*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun
1623*4882a593Smuzhiyun /* Anything else 82598-based is supported */
1624*4882a593Smuzhiyun if (hw->mac.type == ixgbe_mac_82598EB)
1625*4882a593Smuzhiyun return 0;
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun hw->mac.ops.get_device_caps(hw, &enforce_sfp);
1628*4882a593Smuzhiyun if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
1629*4882a593Smuzhiyun !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
1630*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
1631*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1632*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
1633*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
1634*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
1635*4882a593Smuzhiyun /* Make sure we're a supported PHY type */
1636*4882a593Smuzhiyun if (hw->phy.type == ixgbe_phy_sfp_intel)
1637*4882a593Smuzhiyun return 0;
1638*4882a593Smuzhiyun if (hw->allow_unsupported_sfp) {
1639*4882a593Smuzhiyun e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
1640*4882a593Smuzhiyun return 0;
1641*4882a593Smuzhiyun }
1642*4882a593Smuzhiyun hw_dbg(hw, "SFP+ module not supported\n");
1643*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1644*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun return 0;
1647*4882a593Smuzhiyun
1648*4882a593Smuzhiyun err_read_i2c_eeprom:
1649*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_not_present;
1650*4882a593Smuzhiyun if (hw->phy.type != ixgbe_phy_nl) {
1651*4882a593Smuzhiyun hw->phy.id = 0;
1652*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_unknown;
1653*4882a593Smuzhiyun }
1654*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1655*4882a593Smuzhiyun }
1656*4882a593Smuzhiyun
1657*4882a593Smuzhiyun /**
1658*4882a593Smuzhiyun * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules
1659*4882a593Smuzhiyun * @hw: pointer to hardware structure
1660*4882a593Smuzhiyun *
1661*4882a593Smuzhiyun * Searches for and identifies the QSFP module and assigns appropriate PHY type
1662*4882a593Smuzhiyun **/
ixgbe_identify_qsfp_module_generic(struct ixgbe_hw * hw)1663*4882a593Smuzhiyun static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
1664*4882a593Smuzhiyun {
1665*4882a593Smuzhiyun struct ixgbe_adapter *adapter = hw->back;
1666*4882a593Smuzhiyun s32 status;
1667*4882a593Smuzhiyun u32 vendor_oui = 0;
1668*4882a593Smuzhiyun enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
1669*4882a593Smuzhiyun u8 identifier = 0;
1670*4882a593Smuzhiyun u8 comp_codes_1g = 0;
1671*4882a593Smuzhiyun u8 comp_codes_10g = 0;
1672*4882a593Smuzhiyun u8 oui_bytes[3] = {0, 0, 0};
1673*4882a593Smuzhiyun u16 enforce_sfp = 0;
1674*4882a593Smuzhiyun u8 connector = 0;
1675*4882a593Smuzhiyun u8 cable_length = 0;
1676*4882a593Smuzhiyun u8 device_tech = 0;
1677*4882a593Smuzhiyun bool active_cable = false;
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
1680*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_not_present;
1681*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1682*4882a593Smuzhiyun }
1683*4882a593Smuzhiyun
1684*4882a593Smuzhiyun /* LAN ID is needed for sfp_type determination */
1685*4882a593Smuzhiyun hw->mac.ops.set_lan_id(hw);
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
1688*4882a593Smuzhiyun &identifier);
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun if (status != 0)
1691*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1692*4882a593Smuzhiyun
1693*4882a593Smuzhiyun if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
1694*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1695*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
1698*4882a593Smuzhiyun hw->phy.id = identifier;
1699*4882a593Smuzhiyun
1700*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP,
1701*4882a593Smuzhiyun &comp_codes_10g);
1702*4882a593Smuzhiyun
1703*4882a593Smuzhiyun if (status != 0)
1704*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_1GBE_COMP,
1707*4882a593Smuzhiyun &comp_codes_1g);
1708*4882a593Smuzhiyun
1709*4882a593Smuzhiyun if (status != 0)
1710*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun if (comp_codes_10g & IXGBE_SFF_QSFP_DA_PASSIVE_CABLE) {
1713*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_qsfp_passive_unknown;
1714*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1715*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0;
1716*4882a593Smuzhiyun else
1717*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1;
1718*4882a593Smuzhiyun } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
1719*4882a593Smuzhiyun IXGBE_SFF_10GBASELR_CAPABLE)) {
1720*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1721*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0;
1722*4882a593Smuzhiyun else
1723*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1;
1724*4882a593Smuzhiyun } else {
1725*4882a593Smuzhiyun if (comp_codes_10g & IXGBE_SFF_QSFP_DA_ACTIVE_CABLE)
1726*4882a593Smuzhiyun active_cable = true;
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun if (!active_cable) {
1729*4882a593Smuzhiyun /* check for active DA cables that pre-date
1730*4882a593Smuzhiyun * SFF-8436 v3.6
1731*4882a593Smuzhiyun */
1732*4882a593Smuzhiyun hw->phy.ops.read_i2c_eeprom(hw,
1733*4882a593Smuzhiyun IXGBE_SFF_QSFP_CONNECTOR,
1734*4882a593Smuzhiyun &connector);
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun hw->phy.ops.read_i2c_eeprom(hw,
1737*4882a593Smuzhiyun IXGBE_SFF_QSFP_CABLE_LENGTH,
1738*4882a593Smuzhiyun &cable_length);
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun hw->phy.ops.read_i2c_eeprom(hw,
1741*4882a593Smuzhiyun IXGBE_SFF_QSFP_DEVICE_TECH,
1742*4882a593Smuzhiyun &device_tech);
1743*4882a593Smuzhiyun
1744*4882a593Smuzhiyun if ((connector ==
1745*4882a593Smuzhiyun IXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE) &&
1746*4882a593Smuzhiyun (cable_length > 0) &&
1747*4882a593Smuzhiyun ((device_tech >> 4) ==
1748*4882a593Smuzhiyun IXGBE_SFF_QSFP_TRANSMITER_850NM_VCSEL))
1749*4882a593Smuzhiyun active_cable = true;
1750*4882a593Smuzhiyun }
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun if (active_cable) {
1753*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_qsfp_active_unknown;
1754*4882a593Smuzhiyun if (hw->bus.lan_id == 0)
1755*4882a593Smuzhiyun hw->phy.sfp_type =
1756*4882a593Smuzhiyun ixgbe_sfp_type_da_act_lmt_core0;
1757*4882a593Smuzhiyun else
1758*4882a593Smuzhiyun hw->phy.sfp_type =
1759*4882a593Smuzhiyun ixgbe_sfp_type_da_act_lmt_core1;
1760*4882a593Smuzhiyun } else {
1761*4882a593Smuzhiyun /* unsupported module type */
1762*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1763*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun }
1766*4882a593Smuzhiyun
1767*4882a593Smuzhiyun if (hw->phy.sfp_type != stored_sfp_type)
1768*4882a593Smuzhiyun hw->phy.sfp_setup_needed = true;
1769*4882a593Smuzhiyun
1770*4882a593Smuzhiyun /* Determine if the QSFP+ PHY is dual speed or not. */
1771*4882a593Smuzhiyun hw->phy.multispeed_fiber = false;
1772*4882a593Smuzhiyun if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
1773*4882a593Smuzhiyun (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
1774*4882a593Smuzhiyun ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
1775*4882a593Smuzhiyun (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
1776*4882a593Smuzhiyun hw->phy.multispeed_fiber = true;
1777*4882a593Smuzhiyun
1778*4882a593Smuzhiyun /* Determine PHY vendor for optical modules */
1779*4882a593Smuzhiyun if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
1780*4882a593Smuzhiyun IXGBE_SFF_10GBASELR_CAPABLE)) {
1781*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1782*4882a593Smuzhiyun IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0,
1783*4882a593Smuzhiyun &oui_bytes[0]);
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun if (status != 0)
1786*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1789*4882a593Smuzhiyun IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1,
1790*4882a593Smuzhiyun &oui_bytes[1]);
1791*4882a593Smuzhiyun
1792*4882a593Smuzhiyun if (status != 0)
1793*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun status = hw->phy.ops.read_i2c_eeprom(hw,
1796*4882a593Smuzhiyun IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2,
1797*4882a593Smuzhiyun &oui_bytes[2]);
1798*4882a593Smuzhiyun
1799*4882a593Smuzhiyun if (status != 0)
1800*4882a593Smuzhiyun goto err_read_i2c_eeprom;
1801*4882a593Smuzhiyun
1802*4882a593Smuzhiyun vendor_oui =
1803*4882a593Smuzhiyun ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
1804*4882a593Smuzhiyun (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
1805*4882a593Smuzhiyun (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun if (vendor_oui == IXGBE_SFF_VENDOR_OUI_INTEL)
1808*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_qsfp_intel;
1809*4882a593Smuzhiyun else
1810*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_qsfp_unknown;
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun hw->mac.ops.get_device_caps(hw, &enforce_sfp);
1813*4882a593Smuzhiyun if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
1814*4882a593Smuzhiyun /* Make sure we're a supported PHY type */
1815*4882a593Smuzhiyun if (hw->phy.type == ixgbe_phy_qsfp_intel)
1816*4882a593Smuzhiyun return 0;
1817*4882a593Smuzhiyun if (hw->allow_unsupported_sfp) {
1818*4882a593Smuzhiyun e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
1819*4882a593Smuzhiyun return 0;
1820*4882a593Smuzhiyun }
1821*4882a593Smuzhiyun hw_dbg(hw, "QSFP module not supported\n");
1822*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_sfp_unsupported;
1823*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1824*4882a593Smuzhiyun }
1825*4882a593Smuzhiyun return 0;
1826*4882a593Smuzhiyun }
1827*4882a593Smuzhiyun return 0;
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun err_read_i2c_eeprom:
1830*4882a593Smuzhiyun hw->phy.sfp_type = ixgbe_sfp_type_not_present;
1831*4882a593Smuzhiyun hw->phy.id = 0;
1832*4882a593Smuzhiyun hw->phy.type = ixgbe_phy_unknown;
1833*4882a593Smuzhiyun
1834*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1835*4882a593Smuzhiyun }
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun /**
1838*4882a593Smuzhiyun * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence
1839*4882a593Smuzhiyun * @hw: pointer to hardware structure
1840*4882a593Smuzhiyun * @list_offset: offset to the SFP ID list
1841*4882a593Smuzhiyun * @data_offset: offset to the SFP data block
1842*4882a593Smuzhiyun *
1843*4882a593Smuzhiyun * Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if
1844*4882a593Smuzhiyun * so it returns the offsets to the phy init sequence block.
1845*4882a593Smuzhiyun **/
ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw * hw,u16 * list_offset,u16 * data_offset)1846*4882a593Smuzhiyun s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
1847*4882a593Smuzhiyun u16 *list_offset,
1848*4882a593Smuzhiyun u16 *data_offset)
1849*4882a593Smuzhiyun {
1850*4882a593Smuzhiyun u16 sfp_id;
1851*4882a593Smuzhiyun u16 sfp_type = hw->phy.sfp_type;
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
1854*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
1857*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_PRESENT;
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
1860*4882a593Smuzhiyun (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
1861*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1862*4882a593Smuzhiyun
1863*4882a593Smuzhiyun /*
1864*4882a593Smuzhiyun * Limiting active cables and 1G Phys must be initialized as
1865*4882a593Smuzhiyun * SR modules
1866*4882a593Smuzhiyun */
1867*4882a593Smuzhiyun if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 ||
1868*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
1869*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
1870*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_sx_core0)
1871*4882a593Smuzhiyun sfp_type = ixgbe_sfp_type_srlr_core0;
1872*4882a593Smuzhiyun else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 ||
1873*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
1874*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
1875*4882a593Smuzhiyun sfp_type == ixgbe_sfp_type_1g_sx_core1)
1876*4882a593Smuzhiyun sfp_type = ixgbe_sfp_type_srlr_core1;
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun /* Read offset to PHY init contents */
1879*4882a593Smuzhiyun if (hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset)) {
1880*4882a593Smuzhiyun hw_err(hw, "eeprom read at %d failed\n",
1881*4882a593Smuzhiyun IXGBE_PHY_INIT_OFFSET_NL);
1882*4882a593Smuzhiyun return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
1883*4882a593Smuzhiyun }
1884*4882a593Smuzhiyun
1885*4882a593Smuzhiyun if ((!*list_offset) || (*list_offset == 0xFFFF))
1886*4882a593Smuzhiyun return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun /* Shift offset to first ID word */
1889*4882a593Smuzhiyun (*list_offset)++;
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun /*
1892*4882a593Smuzhiyun * Find the matching SFP ID in the EEPROM
1893*4882a593Smuzhiyun * and program the init sequence
1894*4882a593Smuzhiyun */
1895*4882a593Smuzhiyun if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
1896*4882a593Smuzhiyun goto err_phy;
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun while (sfp_id != IXGBE_PHY_INIT_END_NL) {
1899*4882a593Smuzhiyun if (sfp_id == sfp_type) {
1900*4882a593Smuzhiyun (*list_offset)++;
1901*4882a593Smuzhiyun if (hw->eeprom.ops.read(hw, *list_offset, data_offset))
1902*4882a593Smuzhiyun goto err_phy;
1903*4882a593Smuzhiyun if ((!*data_offset) || (*data_offset == 0xFFFF)) {
1904*4882a593Smuzhiyun hw_dbg(hw, "SFP+ module not supported\n");
1905*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1906*4882a593Smuzhiyun } else {
1907*4882a593Smuzhiyun break;
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun } else {
1910*4882a593Smuzhiyun (*list_offset) += 2;
1911*4882a593Smuzhiyun if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
1912*4882a593Smuzhiyun goto err_phy;
1913*4882a593Smuzhiyun }
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun if (sfp_id == IXGBE_PHY_INIT_END_NL) {
1917*4882a593Smuzhiyun hw_dbg(hw, "No matching SFP+ module found\n");
1918*4882a593Smuzhiyun return IXGBE_ERR_SFP_NOT_SUPPORTED;
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun return 0;
1922*4882a593Smuzhiyun
1923*4882a593Smuzhiyun err_phy:
1924*4882a593Smuzhiyun hw_err(hw, "eeprom read at offset %d failed\n", *list_offset);
1925*4882a593Smuzhiyun return IXGBE_ERR_PHY;
1926*4882a593Smuzhiyun }
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun /**
1929*4882a593Smuzhiyun * ixgbe_read_i2c_eeprom_generic - Reads 8 bit EEPROM word over I2C interface
1930*4882a593Smuzhiyun * @hw: pointer to hardware structure
1931*4882a593Smuzhiyun * @byte_offset: EEPROM byte offset to read
1932*4882a593Smuzhiyun * @eeprom_data: value read
1933*4882a593Smuzhiyun *
1934*4882a593Smuzhiyun * Performs byte read operation to SFP module's EEPROM over I2C interface.
1935*4882a593Smuzhiyun **/
ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw * hw,u8 byte_offset,u8 * eeprom_data)1936*4882a593Smuzhiyun s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
1937*4882a593Smuzhiyun u8 *eeprom_data)
1938*4882a593Smuzhiyun {
1939*4882a593Smuzhiyun return hw->phy.ops.read_i2c_byte(hw, byte_offset,
1940*4882a593Smuzhiyun IXGBE_I2C_EEPROM_DEV_ADDR,
1941*4882a593Smuzhiyun eeprom_data);
1942*4882a593Smuzhiyun }
1943*4882a593Smuzhiyun
1944*4882a593Smuzhiyun /**
1945*4882a593Smuzhiyun * ixgbe_read_i2c_sff8472_generic - Reads 8 bit word over I2C interface
1946*4882a593Smuzhiyun * @hw: pointer to hardware structure
1947*4882a593Smuzhiyun * @byte_offset: byte offset at address 0xA2
1948*4882a593Smuzhiyun * @sff8472_data: value read
1949*4882a593Smuzhiyun *
1950*4882a593Smuzhiyun * Performs byte read operation to SFP module's SFF-8472 data over I2C
1951*4882a593Smuzhiyun **/
ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw * hw,u8 byte_offset,u8 * sff8472_data)1952*4882a593Smuzhiyun s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset,
1953*4882a593Smuzhiyun u8 *sff8472_data)
1954*4882a593Smuzhiyun {
1955*4882a593Smuzhiyun return hw->phy.ops.read_i2c_byte(hw, byte_offset,
1956*4882a593Smuzhiyun IXGBE_I2C_EEPROM_DEV_ADDR2,
1957*4882a593Smuzhiyun sff8472_data);
1958*4882a593Smuzhiyun }
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun /**
1961*4882a593Smuzhiyun * ixgbe_write_i2c_eeprom_generic - Writes 8 bit EEPROM word over I2C interface
1962*4882a593Smuzhiyun * @hw: pointer to hardware structure
1963*4882a593Smuzhiyun * @byte_offset: EEPROM byte offset to write
1964*4882a593Smuzhiyun * @eeprom_data: value to write
1965*4882a593Smuzhiyun *
1966*4882a593Smuzhiyun * Performs byte write operation to SFP module's EEPROM over I2C interface.
1967*4882a593Smuzhiyun **/
ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw * hw,u8 byte_offset,u8 eeprom_data)1968*4882a593Smuzhiyun s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
1969*4882a593Smuzhiyun u8 eeprom_data)
1970*4882a593Smuzhiyun {
1971*4882a593Smuzhiyun return hw->phy.ops.write_i2c_byte(hw, byte_offset,
1972*4882a593Smuzhiyun IXGBE_I2C_EEPROM_DEV_ADDR,
1973*4882a593Smuzhiyun eeprom_data);
1974*4882a593Smuzhiyun }
1975*4882a593Smuzhiyun
1976*4882a593Smuzhiyun /**
1977*4882a593Smuzhiyun * ixgbe_is_sfp_probe - Returns true if SFP is being detected
1978*4882a593Smuzhiyun * @hw: pointer to hardware structure
1979*4882a593Smuzhiyun * @offset: eeprom offset to be read
1980*4882a593Smuzhiyun * @addr: I2C address to be read
1981*4882a593Smuzhiyun */
ixgbe_is_sfp_probe(struct ixgbe_hw * hw,u8 offset,u8 addr)1982*4882a593Smuzhiyun static bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr)
1983*4882a593Smuzhiyun {
1984*4882a593Smuzhiyun if (addr == IXGBE_I2C_EEPROM_DEV_ADDR &&
1985*4882a593Smuzhiyun offset == IXGBE_SFF_IDENTIFIER &&
1986*4882a593Smuzhiyun hw->phy.sfp_type == ixgbe_sfp_type_not_present)
1987*4882a593Smuzhiyun return true;
1988*4882a593Smuzhiyun return false;
1989*4882a593Smuzhiyun }
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun /**
1992*4882a593Smuzhiyun * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C
1993*4882a593Smuzhiyun * @hw: pointer to hardware structure
1994*4882a593Smuzhiyun * @byte_offset: byte offset to read
1995*4882a593Smuzhiyun * @dev_addr: device address
1996*4882a593Smuzhiyun * @data: value read
1997*4882a593Smuzhiyun * @lock: true if to take and release semaphore
1998*4882a593Smuzhiyun *
1999*4882a593Smuzhiyun * Performs byte read operation to SFP module's EEPROM over I2C interface at
2000*4882a593Smuzhiyun * a specified device address.
2001*4882a593Smuzhiyun */
ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data,bool lock)2002*4882a593Smuzhiyun static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
2003*4882a593Smuzhiyun u8 dev_addr, u8 *data, bool lock)
2004*4882a593Smuzhiyun {
2005*4882a593Smuzhiyun s32 status;
2006*4882a593Smuzhiyun u32 max_retry = 10;
2007*4882a593Smuzhiyun u32 retry = 0;
2008*4882a593Smuzhiyun u32 swfw_mask = hw->phy.phy_semaphore_mask;
2009*4882a593Smuzhiyun bool nack = true;
2010*4882a593Smuzhiyun
2011*4882a593Smuzhiyun if (hw->mac.type >= ixgbe_mac_X550)
2012*4882a593Smuzhiyun max_retry = 3;
2013*4882a593Smuzhiyun if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr))
2014*4882a593Smuzhiyun max_retry = IXGBE_SFP_DETECT_RETRIES;
2015*4882a593Smuzhiyun
2016*4882a593Smuzhiyun *data = 0;
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun do {
2019*4882a593Smuzhiyun if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
2020*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun ixgbe_i2c_start(hw);
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun /* Device Address and write indication */
2025*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, dev_addr);
2026*4882a593Smuzhiyun if (status != 0)
2027*4882a593Smuzhiyun goto fail;
2028*4882a593Smuzhiyun
2029*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2030*4882a593Smuzhiyun if (status != 0)
2031*4882a593Smuzhiyun goto fail;
2032*4882a593Smuzhiyun
2033*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, byte_offset);
2034*4882a593Smuzhiyun if (status != 0)
2035*4882a593Smuzhiyun goto fail;
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2038*4882a593Smuzhiyun if (status != 0)
2039*4882a593Smuzhiyun goto fail;
2040*4882a593Smuzhiyun
2041*4882a593Smuzhiyun ixgbe_i2c_start(hw);
2042*4882a593Smuzhiyun
2043*4882a593Smuzhiyun /* Device Address and read indication */
2044*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, (dev_addr | 0x1));
2045*4882a593Smuzhiyun if (status != 0)
2046*4882a593Smuzhiyun goto fail;
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2049*4882a593Smuzhiyun if (status != 0)
2050*4882a593Smuzhiyun goto fail;
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun status = ixgbe_clock_in_i2c_byte(hw, data);
2053*4882a593Smuzhiyun if (status != 0)
2054*4882a593Smuzhiyun goto fail;
2055*4882a593Smuzhiyun
2056*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_bit(hw, nack);
2057*4882a593Smuzhiyun if (status != 0)
2058*4882a593Smuzhiyun goto fail;
2059*4882a593Smuzhiyun
2060*4882a593Smuzhiyun ixgbe_i2c_stop(hw);
2061*4882a593Smuzhiyun if (lock)
2062*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
2063*4882a593Smuzhiyun return 0;
2064*4882a593Smuzhiyun
2065*4882a593Smuzhiyun fail:
2066*4882a593Smuzhiyun ixgbe_i2c_bus_clear(hw);
2067*4882a593Smuzhiyun if (lock) {
2068*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
2069*4882a593Smuzhiyun msleep(100);
2070*4882a593Smuzhiyun }
2071*4882a593Smuzhiyun retry++;
2072*4882a593Smuzhiyun if (retry < max_retry)
2073*4882a593Smuzhiyun hw_dbg(hw, "I2C byte read error - Retrying.\n");
2074*4882a593Smuzhiyun else
2075*4882a593Smuzhiyun hw_dbg(hw, "I2C byte read error.\n");
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun } while (retry < max_retry);
2078*4882a593Smuzhiyun
2079*4882a593Smuzhiyun return status;
2080*4882a593Smuzhiyun }
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun /**
2083*4882a593Smuzhiyun * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
2084*4882a593Smuzhiyun * @hw: pointer to hardware structure
2085*4882a593Smuzhiyun * @byte_offset: byte offset to read
2086*4882a593Smuzhiyun * @dev_addr: device address
2087*4882a593Smuzhiyun * @data: value read
2088*4882a593Smuzhiyun *
2089*4882a593Smuzhiyun * Performs byte read operation to SFP module's EEPROM over I2C interface at
2090*4882a593Smuzhiyun * a specified device address.
2091*4882a593Smuzhiyun */
ixgbe_read_i2c_byte_generic(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data)2092*4882a593Smuzhiyun s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
2093*4882a593Smuzhiyun u8 dev_addr, u8 *data)
2094*4882a593Smuzhiyun {
2095*4882a593Smuzhiyun return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
2096*4882a593Smuzhiyun data, true);
2097*4882a593Smuzhiyun }
2098*4882a593Smuzhiyun
2099*4882a593Smuzhiyun /**
2100*4882a593Smuzhiyun * ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C
2101*4882a593Smuzhiyun * @hw: pointer to hardware structure
2102*4882a593Smuzhiyun * @byte_offset: byte offset to read
2103*4882a593Smuzhiyun * @dev_addr: device address
2104*4882a593Smuzhiyun * @data: value read
2105*4882a593Smuzhiyun *
2106*4882a593Smuzhiyun * Performs byte read operation to SFP module's EEPROM over I2C interface at
2107*4882a593Smuzhiyun * a specified device address.
2108*4882a593Smuzhiyun */
ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data)2109*4882a593Smuzhiyun s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
2110*4882a593Smuzhiyun u8 dev_addr, u8 *data)
2111*4882a593Smuzhiyun {
2112*4882a593Smuzhiyun return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
2113*4882a593Smuzhiyun data, false);
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun
2116*4882a593Smuzhiyun /**
2117*4882a593Smuzhiyun * ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C
2118*4882a593Smuzhiyun * @hw: pointer to hardware structure
2119*4882a593Smuzhiyun * @byte_offset: byte offset to write
2120*4882a593Smuzhiyun * @dev_addr: device address
2121*4882a593Smuzhiyun * @data: value to write
2122*4882a593Smuzhiyun * @lock: true if to take and release semaphore
2123*4882a593Smuzhiyun *
2124*4882a593Smuzhiyun * Performs byte write operation to SFP module's EEPROM over I2C interface at
2125*4882a593Smuzhiyun * a specified device address.
2126*4882a593Smuzhiyun */
ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 data,bool lock)2127*4882a593Smuzhiyun static s32 ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
2128*4882a593Smuzhiyun u8 dev_addr, u8 data, bool lock)
2129*4882a593Smuzhiyun {
2130*4882a593Smuzhiyun s32 status;
2131*4882a593Smuzhiyun u32 max_retry = 1;
2132*4882a593Smuzhiyun u32 retry = 0;
2133*4882a593Smuzhiyun u32 swfw_mask = hw->phy.phy_semaphore_mask;
2134*4882a593Smuzhiyun
2135*4882a593Smuzhiyun if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
2136*4882a593Smuzhiyun return IXGBE_ERR_SWFW_SYNC;
2137*4882a593Smuzhiyun
2138*4882a593Smuzhiyun do {
2139*4882a593Smuzhiyun ixgbe_i2c_start(hw);
2140*4882a593Smuzhiyun
2141*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, dev_addr);
2142*4882a593Smuzhiyun if (status != 0)
2143*4882a593Smuzhiyun goto fail;
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2146*4882a593Smuzhiyun if (status != 0)
2147*4882a593Smuzhiyun goto fail;
2148*4882a593Smuzhiyun
2149*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, byte_offset);
2150*4882a593Smuzhiyun if (status != 0)
2151*4882a593Smuzhiyun goto fail;
2152*4882a593Smuzhiyun
2153*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2154*4882a593Smuzhiyun if (status != 0)
2155*4882a593Smuzhiyun goto fail;
2156*4882a593Smuzhiyun
2157*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_byte(hw, data);
2158*4882a593Smuzhiyun if (status != 0)
2159*4882a593Smuzhiyun goto fail;
2160*4882a593Smuzhiyun
2161*4882a593Smuzhiyun status = ixgbe_get_i2c_ack(hw);
2162*4882a593Smuzhiyun if (status != 0)
2163*4882a593Smuzhiyun goto fail;
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun ixgbe_i2c_stop(hw);
2166*4882a593Smuzhiyun if (lock)
2167*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
2168*4882a593Smuzhiyun return 0;
2169*4882a593Smuzhiyun
2170*4882a593Smuzhiyun fail:
2171*4882a593Smuzhiyun ixgbe_i2c_bus_clear(hw);
2172*4882a593Smuzhiyun retry++;
2173*4882a593Smuzhiyun if (retry < max_retry)
2174*4882a593Smuzhiyun hw_dbg(hw, "I2C byte write error - Retrying.\n");
2175*4882a593Smuzhiyun else
2176*4882a593Smuzhiyun hw_dbg(hw, "I2C byte write error.\n");
2177*4882a593Smuzhiyun } while (retry < max_retry);
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun if (lock)
2180*4882a593Smuzhiyun hw->mac.ops.release_swfw_sync(hw, swfw_mask);
2181*4882a593Smuzhiyun
2182*4882a593Smuzhiyun return status;
2183*4882a593Smuzhiyun }
2184*4882a593Smuzhiyun
2185*4882a593Smuzhiyun /**
2186*4882a593Smuzhiyun * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
2187*4882a593Smuzhiyun * @hw: pointer to hardware structure
2188*4882a593Smuzhiyun * @byte_offset: byte offset to write
2189*4882a593Smuzhiyun * @dev_addr: device address
2190*4882a593Smuzhiyun * @data: value to write
2191*4882a593Smuzhiyun *
2192*4882a593Smuzhiyun * Performs byte write operation to SFP module's EEPROM over I2C interface at
2193*4882a593Smuzhiyun * a specified device address.
2194*4882a593Smuzhiyun */
ixgbe_write_i2c_byte_generic(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 data)2195*4882a593Smuzhiyun s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
2196*4882a593Smuzhiyun u8 dev_addr, u8 data)
2197*4882a593Smuzhiyun {
2198*4882a593Smuzhiyun return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
2199*4882a593Smuzhiyun data, true);
2200*4882a593Smuzhiyun }
2201*4882a593Smuzhiyun
2202*4882a593Smuzhiyun /**
2203*4882a593Smuzhiyun * ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C
2204*4882a593Smuzhiyun * @hw: pointer to hardware structure
2205*4882a593Smuzhiyun * @byte_offset: byte offset to write
2206*4882a593Smuzhiyun * @dev_addr: device address
2207*4882a593Smuzhiyun * @data: value to write
2208*4882a593Smuzhiyun *
2209*4882a593Smuzhiyun * Performs byte write operation to SFP module's EEPROM over I2C interface at
2210*4882a593Smuzhiyun * a specified device address.
2211*4882a593Smuzhiyun */
ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw * hw,u8 byte_offset,u8 dev_addr,u8 data)2212*4882a593Smuzhiyun s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
2213*4882a593Smuzhiyun u8 dev_addr, u8 data)
2214*4882a593Smuzhiyun {
2215*4882a593Smuzhiyun return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
2216*4882a593Smuzhiyun data, false);
2217*4882a593Smuzhiyun }
2218*4882a593Smuzhiyun
2219*4882a593Smuzhiyun /**
2220*4882a593Smuzhiyun * ixgbe_i2c_start - Sets I2C start condition
2221*4882a593Smuzhiyun * @hw: pointer to hardware structure
2222*4882a593Smuzhiyun *
2223*4882a593Smuzhiyun * Sets I2C start condition (High -> Low on SDA while SCL is High)
2224*4882a593Smuzhiyun * Set bit-bang mode on X550 hardware.
2225*4882a593Smuzhiyun **/
ixgbe_i2c_start(struct ixgbe_hw * hw)2226*4882a593Smuzhiyun static void ixgbe_i2c_start(struct ixgbe_hw *hw)
2227*4882a593Smuzhiyun {
2228*4882a593Smuzhiyun u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2229*4882a593Smuzhiyun
2230*4882a593Smuzhiyun i2cctl |= IXGBE_I2C_BB_EN(hw);
2231*4882a593Smuzhiyun
2232*4882a593Smuzhiyun /* Start condition must begin with data and clock high */
2233*4882a593Smuzhiyun ixgbe_set_i2c_data(hw, &i2cctl, 1);
2234*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2235*4882a593Smuzhiyun
2236*4882a593Smuzhiyun /* Setup time for start condition (4.7us) */
2237*4882a593Smuzhiyun udelay(IXGBE_I2C_T_SU_STA);
2238*4882a593Smuzhiyun
2239*4882a593Smuzhiyun ixgbe_set_i2c_data(hw, &i2cctl, 0);
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun /* Hold time for start condition (4us) */
2242*4882a593Smuzhiyun udelay(IXGBE_I2C_T_HD_STA);
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun ixgbe_lower_i2c_clk(hw, &i2cctl);
2245*4882a593Smuzhiyun
2246*4882a593Smuzhiyun /* Minimum low period of clock is 4.7 us */
2247*4882a593Smuzhiyun udelay(IXGBE_I2C_T_LOW);
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun }
2250*4882a593Smuzhiyun
2251*4882a593Smuzhiyun /**
2252*4882a593Smuzhiyun * ixgbe_i2c_stop - Sets I2C stop condition
2253*4882a593Smuzhiyun * @hw: pointer to hardware structure
2254*4882a593Smuzhiyun *
2255*4882a593Smuzhiyun * Sets I2C stop condition (Low -> High on SDA while SCL is High)
2256*4882a593Smuzhiyun * Disables bit-bang mode and negates data output enable on X550
2257*4882a593Smuzhiyun * hardware.
2258*4882a593Smuzhiyun **/
ixgbe_i2c_stop(struct ixgbe_hw * hw)2259*4882a593Smuzhiyun static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
2260*4882a593Smuzhiyun {
2261*4882a593Smuzhiyun u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2262*4882a593Smuzhiyun u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
2263*4882a593Smuzhiyun u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw);
2264*4882a593Smuzhiyun u32 bb_en_bit = IXGBE_I2C_BB_EN(hw);
2265*4882a593Smuzhiyun
2266*4882a593Smuzhiyun /* Stop condition must begin with data low and clock high */
2267*4882a593Smuzhiyun ixgbe_set_i2c_data(hw, &i2cctl, 0);
2268*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2269*4882a593Smuzhiyun
2270*4882a593Smuzhiyun /* Setup time for stop condition (4us) */
2271*4882a593Smuzhiyun udelay(IXGBE_I2C_T_SU_STO);
2272*4882a593Smuzhiyun
2273*4882a593Smuzhiyun ixgbe_set_i2c_data(hw, &i2cctl, 1);
2274*4882a593Smuzhiyun
2275*4882a593Smuzhiyun /* bus free time between stop and start (4.7us)*/
2276*4882a593Smuzhiyun udelay(IXGBE_I2C_T_BUF);
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun if (bb_en_bit || data_oe_bit || clk_oe_bit) {
2279*4882a593Smuzhiyun i2cctl &= ~bb_en_bit;
2280*4882a593Smuzhiyun i2cctl |= data_oe_bit | clk_oe_bit;
2281*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
2282*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2283*4882a593Smuzhiyun }
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun
2286*4882a593Smuzhiyun /**
2287*4882a593Smuzhiyun * ixgbe_clock_in_i2c_byte - Clocks in one byte via I2C
2288*4882a593Smuzhiyun * @hw: pointer to hardware structure
2289*4882a593Smuzhiyun * @data: data byte to clock in
2290*4882a593Smuzhiyun *
2291*4882a593Smuzhiyun * Clocks in one byte data via I2C data/clock
2292*4882a593Smuzhiyun **/
ixgbe_clock_in_i2c_byte(struct ixgbe_hw * hw,u8 * data)2293*4882a593Smuzhiyun static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
2294*4882a593Smuzhiyun {
2295*4882a593Smuzhiyun s32 i;
2296*4882a593Smuzhiyun bool bit = false;
2297*4882a593Smuzhiyun
2298*4882a593Smuzhiyun *data = 0;
2299*4882a593Smuzhiyun for (i = 7; i >= 0; i--) {
2300*4882a593Smuzhiyun ixgbe_clock_in_i2c_bit(hw, &bit);
2301*4882a593Smuzhiyun *data |= bit << i;
2302*4882a593Smuzhiyun }
2303*4882a593Smuzhiyun
2304*4882a593Smuzhiyun return 0;
2305*4882a593Smuzhiyun }
2306*4882a593Smuzhiyun
2307*4882a593Smuzhiyun /**
2308*4882a593Smuzhiyun * ixgbe_clock_out_i2c_byte - Clocks out one byte via I2C
2309*4882a593Smuzhiyun * @hw: pointer to hardware structure
2310*4882a593Smuzhiyun * @data: data byte clocked out
2311*4882a593Smuzhiyun *
2312*4882a593Smuzhiyun * Clocks out one byte data via I2C data/clock
2313*4882a593Smuzhiyun **/
ixgbe_clock_out_i2c_byte(struct ixgbe_hw * hw,u8 data)2314*4882a593Smuzhiyun static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
2315*4882a593Smuzhiyun {
2316*4882a593Smuzhiyun s32 status;
2317*4882a593Smuzhiyun s32 i;
2318*4882a593Smuzhiyun u32 i2cctl;
2319*4882a593Smuzhiyun bool bit = false;
2320*4882a593Smuzhiyun
2321*4882a593Smuzhiyun for (i = 7; i >= 0; i--) {
2322*4882a593Smuzhiyun bit = (data >> i) & 0x1;
2323*4882a593Smuzhiyun status = ixgbe_clock_out_i2c_bit(hw, bit);
2324*4882a593Smuzhiyun
2325*4882a593Smuzhiyun if (status != 0)
2326*4882a593Smuzhiyun break;
2327*4882a593Smuzhiyun }
2328*4882a593Smuzhiyun
2329*4882a593Smuzhiyun /* Release SDA line (set high) */
2330*4882a593Smuzhiyun i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2331*4882a593Smuzhiyun i2cctl |= IXGBE_I2C_DATA_OUT(hw);
2332*4882a593Smuzhiyun i2cctl |= IXGBE_I2C_DATA_OE_N_EN(hw);
2333*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
2334*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2335*4882a593Smuzhiyun
2336*4882a593Smuzhiyun return status;
2337*4882a593Smuzhiyun }
2338*4882a593Smuzhiyun
2339*4882a593Smuzhiyun /**
2340*4882a593Smuzhiyun * ixgbe_get_i2c_ack - Polls for I2C ACK
2341*4882a593Smuzhiyun * @hw: pointer to hardware structure
2342*4882a593Smuzhiyun *
2343*4882a593Smuzhiyun * Clocks in/out one bit via I2C data/clock
2344*4882a593Smuzhiyun **/
ixgbe_get_i2c_ack(struct ixgbe_hw * hw)2345*4882a593Smuzhiyun static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
2346*4882a593Smuzhiyun {
2347*4882a593Smuzhiyun u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
2348*4882a593Smuzhiyun s32 status = 0;
2349*4882a593Smuzhiyun u32 i = 0;
2350*4882a593Smuzhiyun u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2351*4882a593Smuzhiyun u32 timeout = 10;
2352*4882a593Smuzhiyun bool ack = true;
2353*4882a593Smuzhiyun
2354*4882a593Smuzhiyun if (data_oe_bit) {
2355*4882a593Smuzhiyun i2cctl |= IXGBE_I2C_DATA_OUT(hw);
2356*4882a593Smuzhiyun i2cctl |= data_oe_bit;
2357*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
2358*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2361*4882a593Smuzhiyun
2362*4882a593Smuzhiyun /* Minimum high period of clock is 4us */
2363*4882a593Smuzhiyun udelay(IXGBE_I2C_T_HIGH);
2364*4882a593Smuzhiyun
2365*4882a593Smuzhiyun /* Poll for ACK. Note that ACK in I2C spec is
2366*4882a593Smuzhiyun * transition from 1 to 0 */
2367*4882a593Smuzhiyun for (i = 0; i < timeout; i++) {
2368*4882a593Smuzhiyun i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2369*4882a593Smuzhiyun ack = ixgbe_get_i2c_data(hw, &i2cctl);
2370*4882a593Smuzhiyun
2371*4882a593Smuzhiyun udelay(1);
2372*4882a593Smuzhiyun if (ack == 0)
2373*4882a593Smuzhiyun break;
2374*4882a593Smuzhiyun }
2375*4882a593Smuzhiyun
2376*4882a593Smuzhiyun if (ack == 1) {
2377*4882a593Smuzhiyun hw_dbg(hw, "I2C ack was not received.\n");
2378*4882a593Smuzhiyun status = IXGBE_ERR_I2C;
2379*4882a593Smuzhiyun }
2380*4882a593Smuzhiyun
2381*4882a593Smuzhiyun ixgbe_lower_i2c_clk(hw, &i2cctl);
2382*4882a593Smuzhiyun
2383*4882a593Smuzhiyun /* Minimum low period of clock is 4.7 us */
2384*4882a593Smuzhiyun udelay(IXGBE_I2C_T_LOW);
2385*4882a593Smuzhiyun
2386*4882a593Smuzhiyun return status;
2387*4882a593Smuzhiyun }
2388*4882a593Smuzhiyun
2389*4882a593Smuzhiyun /**
2390*4882a593Smuzhiyun * ixgbe_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
2391*4882a593Smuzhiyun * @hw: pointer to hardware structure
2392*4882a593Smuzhiyun * @data: read data value
2393*4882a593Smuzhiyun *
2394*4882a593Smuzhiyun * Clocks in one bit via I2C data/clock
2395*4882a593Smuzhiyun **/
ixgbe_clock_in_i2c_bit(struct ixgbe_hw * hw,bool * data)2396*4882a593Smuzhiyun static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
2397*4882a593Smuzhiyun {
2398*4882a593Smuzhiyun u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2399*4882a593Smuzhiyun u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
2400*4882a593Smuzhiyun
2401*4882a593Smuzhiyun if (data_oe_bit) {
2402*4882a593Smuzhiyun i2cctl |= IXGBE_I2C_DATA_OUT(hw);
2403*4882a593Smuzhiyun i2cctl |= data_oe_bit;
2404*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
2405*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2406*4882a593Smuzhiyun }
2407*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2408*4882a593Smuzhiyun
2409*4882a593Smuzhiyun /* Minimum high period of clock is 4us */
2410*4882a593Smuzhiyun udelay(IXGBE_I2C_T_HIGH);
2411*4882a593Smuzhiyun
2412*4882a593Smuzhiyun i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2413*4882a593Smuzhiyun *data = ixgbe_get_i2c_data(hw, &i2cctl);
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun ixgbe_lower_i2c_clk(hw, &i2cctl);
2416*4882a593Smuzhiyun
2417*4882a593Smuzhiyun /* Minimum low period of clock is 4.7 us */
2418*4882a593Smuzhiyun udelay(IXGBE_I2C_T_LOW);
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun return 0;
2421*4882a593Smuzhiyun }
2422*4882a593Smuzhiyun
2423*4882a593Smuzhiyun /**
2424*4882a593Smuzhiyun * ixgbe_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
2425*4882a593Smuzhiyun * @hw: pointer to hardware structure
2426*4882a593Smuzhiyun * @data: data value to write
2427*4882a593Smuzhiyun *
2428*4882a593Smuzhiyun * Clocks out one bit via I2C data/clock
2429*4882a593Smuzhiyun **/
ixgbe_clock_out_i2c_bit(struct ixgbe_hw * hw,bool data)2430*4882a593Smuzhiyun static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
2431*4882a593Smuzhiyun {
2432*4882a593Smuzhiyun s32 status;
2433*4882a593Smuzhiyun u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2434*4882a593Smuzhiyun
2435*4882a593Smuzhiyun status = ixgbe_set_i2c_data(hw, &i2cctl, data);
2436*4882a593Smuzhiyun if (status == 0) {
2437*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2438*4882a593Smuzhiyun
2439*4882a593Smuzhiyun /* Minimum high period of clock is 4us */
2440*4882a593Smuzhiyun udelay(IXGBE_I2C_T_HIGH);
2441*4882a593Smuzhiyun
2442*4882a593Smuzhiyun ixgbe_lower_i2c_clk(hw, &i2cctl);
2443*4882a593Smuzhiyun
2444*4882a593Smuzhiyun /* Minimum low period of clock is 4.7 us.
2445*4882a593Smuzhiyun * This also takes care of the data hold time.
2446*4882a593Smuzhiyun */
2447*4882a593Smuzhiyun udelay(IXGBE_I2C_T_LOW);
2448*4882a593Smuzhiyun } else {
2449*4882a593Smuzhiyun hw_dbg(hw, "I2C data was not set to %X\n", data);
2450*4882a593Smuzhiyun return IXGBE_ERR_I2C;
2451*4882a593Smuzhiyun }
2452*4882a593Smuzhiyun
2453*4882a593Smuzhiyun return 0;
2454*4882a593Smuzhiyun }
2455*4882a593Smuzhiyun /**
2456*4882a593Smuzhiyun * ixgbe_raise_i2c_clk - Raises the I2C SCL clock
2457*4882a593Smuzhiyun * @hw: pointer to hardware structure
2458*4882a593Smuzhiyun * @i2cctl: Current value of I2CCTL register
2459*4882a593Smuzhiyun *
2460*4882a593Smuzhiyun * Raises the I2C clock line '0'->'1'
2461*4882a593Smuzhiyun * Negates the I2C clock output enable on X550 hardware.
2462*4882a593Smuzhiyun **/
ixgbe_raise_i2c_clk(struct ixgbe_hw * hw,u32 * i2cctl)2463*4882a593Smuzhiyun static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
2464*4882a593Smuzhiyun {
2465*4882a593Smuzhiyun u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw);
2466*4882a593Smuzhiyun u32 i = 0;
2467*4882a593Smuzhiyun u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT;
2468*4882a593Smuzhiyun u32 i2cctl_r = 0;
2469*4882a593Smuzhiyun
2470*4882a593Smuzhiyun if (clk_oe_bit) {
2471*4882a593Smuzhiyun *i2cctl |= clk_oe_bit;
2472*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2473*4882a593Smuzhiyun }
2474*4882a593Smuzhiyun
2475*4882a593Smuzhiyun for (i = 0; i < timeout; i++) {
2476*4882a593Smuzhiyun *i2cctl |= IXGBE_I2C_CLK_OUT(hw);
2477*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2478*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2479*4882a593Smuzhiyun /* SCL rise time (1000ns) */
2480*4882a593Smuzhiyun udelay(IXGBE_I2C_T_RISE);
2481*4882a593Smuzhiyun
2482*4882a593Smuzhiyun i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2483*4882a593Smuzhiyun if (i2cctl_r & IXGBE_I2C_CLK_IN(hw))
2484*4882a593Smuzhiyun break;
2485*4882a593Smuzhiyun }
2486*4882a593Smuzhiyun }
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun /**
2489*4882a593Smuzhiyun * ixgbe_lower_i2c_clk - Lowers the I2C SCL clock
2490*4882a593Smuzhiyun * @hw: pointer to hardware structure
2491*4882a593Smuzhiyun * @i2cctl: Current value of I2CCTL register
2492*4882a593Smuzhiyun *
2493*4882a593Smuzhiyun * Lowers the I2C clock line '1'->'0'
2494*4882a593Smuzhiyun * Asserts the I2C clock output enable on X550 hardware.
2495*4882a593Smuzhiyun **/
ixgbe_lower_i2c_clk(struct ixgbe_hw * hw,u32 * i2cctl)2496*4882a593Smuzhiyun static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
2497*4882a593Smuzhiyun {
2498*4882a593Smuzhiyun
2499*4882a593Smuzhiyun *i2cctl &= ~IXGBE_I2C_CLK_OUT(hw);
2500*4882a593Smuzhiyun *i2cctl &= ~IXGBE_I2C_CLK_OE_N_EN(hw);
2501*4882a593Smuzhiyun
2502*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2503*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2504*4882a593Smuzhiyun
2505*4882a593Smuzhiyun /* SCL fall time (300ns) */
2506*4882a593Smuzhiyun udelay(IXGBE_I2C_T_FALL);
2507*4882a593Smuzhiyun }
2508*4882a593Smuzhiyun
2509*4882a593Smuzhiyun /**
2510*4882a593Smuzhiyun * ixgbe_set_i2c_data - Sets the I2C data bit
2511*4882a593Smuzhiyun * @hw: pointer to hardware structure
2512*4882a593Smuzhiyun * @i2cctl: Current value of I2CCTL register
2513*4882a593Smuzhiyun * @data: I2C data value (0 or 1) to set
2514*4882a593Smuzhiyun *
2515*4882a593Smuzhiyun * Sets the I2C data bit
2516*4882a593Smuzhiyun * Asserts the I2C data output enable on X550 hardware.
2517*4882a593Smuzhiyun **/
ixgbe_set_i2c_data(struct ixgbe_hw * hw,u32 * i2cctl,bool data)2518*4882a593Smuzhiyun static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
2519*4882a593Smuzhiyun {
2520*4882a593Smuzhiyun u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
2521*4882a593Smuzhiyun
2522*4882a593Smuzhiyun if (data)
2523*4882a593Smuzhiyun *i2cctl |= IXGBE_I2C_DATA_OUT(hw);
2524*4882a593Smuzhiyun else
2525*4882a593Smuzhiyun *i2cctl &= ~IXGBE_I2C_DATA_OUT(hw);
2526*4882a593Smuzhiyun *i2cctl &= ~data_oe_bit;
2527*4882a593Smuzhiyun
2528*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2529*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2530*4882a593Smuzhiyun
2531*4882a593Smuzhiyun /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
2532*4882a593Smuzhiyun udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA);
2533*4882a593Smuzhiyun
2534*4882a593Smuzhiyun if (!data) /* Can't verify data in this case */
2535*4882a593Smuzhiyun return 0;
2536*4882a593Smuzhiyun if (data_oe_bit) {
2537*4882a593Smuzhiyun *i2cctl |= data_oe_bit;
2538*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2539*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2540*4882a593Smuzhiyun }
2541*4882a593Smuzhiyun
2542*4882a593Smuzhiyun /* Verify data was set correctly */
2543*4882a593Smuzhiyun *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2544*4882a593Smuzhiyun if (data != ixgbe_get_i2c_data(hw, i2cctl)) {
2545*4882a593Smuzhiyun hw_dbg(hw, "Error - I2C data was not set to %X.\n", data);
2546*4882a593Smuzhiyun return IXGBE_ERR_I2C;
2547*4882a593Smuzhiyun }
2548*4882a593Smuzhiyun
2549*4882a593Smuzhiyun return 0;
2550*4882a593Smuzhiyun }
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun /**
2553*4882a593Smuzhiyun * ixgbe_get_i2c_data - Reads the I2C SDA data bit
2554*4882a593Smuzhiyun * @hw: pointer to hardware structure
2555*4882a593Smuzhiyun * @i2cctl: Current value of I2CCTL register
2556*4882a593Smuzhiyun *
2557*4882a593Smuzhiyun * Returns the I2C data bit value
2558*4882a593Smuzhiyun * Negates the I2C data output enable on X550 hardware.
2559*4882a593Smuzhiyun **/
ixgbe_get_i2c_data(struct ixgbe_hw * hw,u32 * i2cctl)2560*4882a593Smuzhiyun static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl)
2561*4882a593Smuzhiyun {
2562*4882a593Smuzhiyun u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw);
2563*4882a593Smuzhiyun
2564*4882a593Smuzhiyun if (data_oe_bit) {
2565*4882a593Smuzhiyun *i2cctl |= data_oe_bit;
2566*4882a593Smuzhiyun IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
2567*4882a593Smuzhiyun IXGBE_WRITE_FLUSH(hw);
2568*4882a593Smuzhiyun udelay(IXGBE_I2C_T_FALL);
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun
2571*4882a593Smuzhiyun if (*i2cctl & IXGBE_I2C_DATA_IN(hw))
2572*4882a593Smuzhiyun return true;
2573*4882a593Smuzhiyun return false;
2574*4882a593Smuzhiyun }
2575*4882a593Smuzhiyun
2576*4882a593Smuzhiyun /**
2577*4882a593Smuzhiyun * ixgbe_i2c_bus_clear - Clears the I2C bus
2578*4882a593Smuzhiyun * @hw: pointer to hardware structure
2579*4882a593Smuzhiyun *
2580*4882a593Smuzhiyun * Clears the I2C bus by sending nine clock pulses.
2581*4882a593Smuzhiyun * Used when data line is stuck low.
2582*4882a593Smuzhiyun **/
ixgbe_i2c_bus_clear(struct ixgbe_hw * hw)2583*4882a593Smuzhiyun static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
2584*4882a593Smuzhiyun {
2585*4882a593Smuzhiyun u32 i2cctl;
2586*4882a593Smuzhiyun u32 i;
2587*4882a593Smuzhiyun
2588*4882a593Smuzhiyun ixgbe_i2c_start(hw);
2589*4882a593Smuzhiyun i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
2590*4882a593Smuzhiyun
2591*4882a593Smuzhiyun ixgbe_set_i2c_data(hw, &i2cctl, 1);
2592*4882a593Smuzhiyun
2593*4882a593Smuzhiyun for (i = 0; i < 9; i++) {
2594*4882a593Smuzhiyun ixgbe_raise_i2c_clk(hw, &i2cctl);
2595*4882a593Smuzhiyun
2596*4882a593Smuzhiyun /* Min high period of clock is 4us */
2597*4882a593Smuzhiyun udelay(IXGBE_I2C_T_HIGH);
2598*4882a593Smuzhiyun
2599*4882a593Smuzhiyun ixgbe_lower_i2c_clk(hw, &i2cctl);
2600*4882a593Smuzhiyun
2601*4882a593Smuzhiyun /* Min low period of clock is 4.7us*/
2602*4882a593Smuzhiyun udelay(IXGBE_I2C_T_LOW);
2603*4882a593Smuzhiyun }
2604*4882a593Smuzhiyun
2605*4882a593Smuzhiyun ixgbe_i2c_start(hw);
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun /* Put the i2c bus back to default state */
2608*4882a593Smuzhiyun ixgbe_i2c_stop(hw);
2609*4882a593Smuzhiyun }
2610*4882a593Smuzhiyun
2611*4882a593Smuzhiyun /**
2612*4882a593Smuzhiyun * ixgbe_tn_check_overtemp - Checks if an overtemp occurred.
2613*4882a593Smuzhiyun * @hw: pointer to hardware structure
2614*4882a593Smuzhiyun *
2615*4882a593Smuzhiyun * Checks if the LASI temp alarm status was triggered due to overtemp
2616*4882a593Smuzhiyun **/
ixgbe_tn_check_overtemp(struct ixgbe_hw * hw)2617*4882a593Smuzhiyun s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
2618*4882a593Smuzhiyun {
2619*4882a593Smuzhiyun u16 phy_data = 0;
2620*4882a593Smuzhiyun
2621*4882a593Smuzhiyun if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
2622*4882a593Smuzhiyun return 0;
2623*4882a593Smuzhiyun
2624*4882a593Smuzhiyun /* Check that the LASI temp alarm status was triggered */
2625*4882a593Smuzhiyun hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
2626*4882a593Smuzhiyun MDIO_MMD_PMAPMD, &phy_data);
2627*4882a593Smuzhiyun
2628*4882a593Smuzhiyun if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
2629*4882a593Smuzhiyun return 0;
2630*4882a593Smuzhiyun
2631*4882a593Smuzhiyun return IXGBE_ERR_OVERTEMP;
2632*4882a593Smuzhiyun }
2633*4882a593Smuzhiyun
2634*4882a593Smuzhiyun /** ixgbe_set_copper_phy_power - Control power for copper phy
2635*4882a593Smuzhiyun * @hw: pointer to hardware structure
2636*4882a593Smuzhiyun * @on: true for on, false for off
2637*4882a593Smuzhiyun **/
ixgbe_set_copper_phy_power(struct ixgbe_hw * hw,bool on)2638*4882a593Smuzhiyun s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
2639*4882a593Smuzhiyun {
2640*4882a593Smuzhiyun u32 status;
2641*4882a593Smuzhiyun u16 reg;
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun /* Bail if we don't have copper phy */
2644*4882a593Smuzhiyun if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
2645*4882a593Smuzhiyun return 0;
2646*4882a593Smuzhiyun
2647*4882a593Smuzhiyun if (!on && ixgbe_mng_present(hw))
2648*4882a593Smuzhiyun return 0;
2649*4882a593Smuzhiyun
2650*4882a593Smuzhiyun status = hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, ®);
2651*4882a593Smuzhiyun if (status)
2652*4882a593Smuzhiyun return status;
2653*4882a593Smuzhiyun
2654*4882a593Smuzhiyun if (on) {
2655*4882a593Smuzhiyun reg &= ~IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
2656*4882a593Smuzhiyun } else {
2657*4882a593Smuzhiyun if (ixgbe_check_reset_blocked(hw))
2658*4882a593Smuzhiyun return 0;
2659*4882a593Smuzhiyun reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
2660*4882a593Smuzhiyun }
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun status = hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, reg);
2663*4882a593Smuzhiyun return status;
2664*4882a593Smuzhiyun }
2665